# HG changeset patch # User Bryan O'Sullivan # Date 1175321128 25200 # Node ID 5fc4a45c069fd8f260e0557e943de7e292f50e6b # Parent 1b55292716a46688bfbece0bdd9ed17c27bcfe21 Continue documentation of collaboration models. diff -r 1b55292716a4 -r 5fc4a45c069f en/Makefile --- a/en/Makefile Thu Mar 29 19:55:18 2007 +0100 +++ b/en/Makefile Fri Mar 30 23:05:28 2007 -0700 @@ -24,6 +24,7 @@ undo.tex image-sources := \ + feature-branches.dot \ filelog.svg \ kdiff3.png \ metadata.svg \ @@ -53,6 +54,7 @@ example-sources := \ backout \ bisect \ + branching \ cmdref \ daily.copy \ daily.files \ diff -r 1b55292716a4 -r 5fc4a45c069f en/collab.tex --- a/en/collab.tex Thu Mar 29 19:55:18 2007 +0100 +++ b/en/collab.tex Fri Mar 30 23:05:28 2007 -0700 @@ -74,7 +74,7 @@ \subsection{A single central repository} -For smaller projects, migrating from a centralised revision control +For smaller projects migrating from a centralised revision control tool, perhaps the easiest way to get started is to have changes flow through a single shared central repository. This is also the most common ``building block'' for more ambitious workflow schemes. @@ -84,7 +84,7 @@ developers have permission to push a change back when they're ready for other people to see it. -Under this model, it can still sometimes make sense for people to pull +Under this model, it can still often make sense for people to pull changes directly from each other, without going through the central repository. Consider a case in which I have a tentative bug fix, but I am worried that if I were to publish it to the central repository, @@ -102,6 +102,97 @@ needs of people who don't have push access, and those who want to use web browsers to browse the repository's history. +\subsection{Working with multiple branches} + +Projects of any significant size naturally tend to make progress on +several fronts simultaneously. In the case of software, it's common +for a project to go through periodic official releases. A release +might then go into ``maintenance mode'' for a while after its first +publication; maintenance releases tend to contain only bug fixes, not +new features. In parallel with these maintenance releases, one or +more future releases may be under development. People normally use +the word ``branch'' to refer to one of these many slightly different +directions in which development is proceeding. + +Mercurial is particularly well suited to managing a number of +simultaneous, but not identical, branches. Each ``development +direction'' can live in its own central repository, and you can merge +changes from one to another as the need arises. Because repositories +are independent of each other, unstable changes in a development +branch will never affect a stable branch unless someone explicitly +merges those changes in. + +Here's an example of how this can work in practice. Let's say you +have one ``main branch'' on a central server. +\interaction{branching.init} +People clone it, make changes locally, test them, and push them back. + +Once the main branch reaches a release milestone, you can use the +\hgcmd{tag} command to give a permanent name to the milestone +revision. +\interaction{branching.tag} +Let's say some ongoing development occurs on the main branch. +\interaction{branching.main} +Using the tag that was recorded at the milestone, people who clone +that repository at any time in the future can use \hgcmd{update} to +get a copy of the working directory exactly as it was when that tagged +revision was committed. +\interaction{branching.update} + +In addition, immediately after the main branch is tagged, someone can +then clone the main branch on the server to a new ``stable'' branch, +also on the server. +\interaction{branching.clone} + +Someone who needs to make a change to the stable branch can then clone +\emph{that} repository, make their changes, commit, and push their +changes back there. +\interaction{branching.stable} +Because Mercurial repositories are independent, and Mercurial doesn't +move changes around automatically, the stable and main branches are +\emph{isolated} from each other. The changes that you made on the +main branch don't ``leak'' to the stable branch, and vice versa. + +You'll often want all of your bugfixes on the stable branch to show up +on the main branch, too. Rather than rewrite a bugfix on the main +branch, you can simply pull and merge changes from the stable to the +main branch, and Mercurial will bring those bugfixes in for you. +\interaction{branching.merge} +The main branch will still contain changes that are not on the stable +branch, but it will also contain all of the bugfixes from the stable +branch. The stable branch remains unaffected by these changes. + +\subsection{Feature branches} + +For larger projects, an effective way to manage change is to break up +a team into smaller groups. Each group has a shared branch of its +own, cloned from a single ``master'' branch used by the entire +project. People working on an individual branch are typically quite +isolated from developments on other branches. + +\begin{figure}[ht] + \centering + \grafix{feature-branches} + \caption{Feature branches} + \label{fig:collab:feature-branches} +\end{figure} + +When a particular feature is deemed to be in suitable shape, someone +on that feature team pulls and merges from the master branch into the +feature branch, then pushes back up to the master branch. + +\subsection{The release train} + +Some projects are organised on a ``train'' basis: a release is +scheduled to happen every few months, and whatever features are ready +when the ``train'' is ready to leave are allowed in. + +This model resembles working with feature branches. The difference is +that when a feature branch misses a train, someone on the feature team +pulls and merges the changes that went out on that train release, and +the team continues its work on top of that release so that their +feature can make the next release. + \subsection{The Linux kernel model} The development of the Linux kernel has a shallow hierarchical diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/backout --- a/en/examples/backout Thu Mar 29 19:55:18 2007 +0100 +++ b/en/examples/backout Fri Mar 30 23:05:28 2007 -0700 @@ -6,7 +6,7 @@ export HGMERGE=$(mktemp) echo '#!/bin/sh' >> $HGMERGE echo 'echo first change > "$1"' >> $HGMERGE -echo 'echo third change > "$1"' >> $HGMERGE +echo 'echo third change >> "$1"' >> $HGMERGE chmod 700 $HGMERGE #$ name: init diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/backout.manual.merge.out --- a/en/examples/backout.manual.merge.out Thu Mar 29 19:55:18 2007 +0100 +++ b/en/examples/backout.manual.merge.out Fri Mar 30 23:05:28 2007 -0700 @@ -4,4 +4,5 @@ (branch merge, don't forget to commit) $ \textbf{hg commit -m 'merged backout with previous tip'} $ \textbf{cat myfile} +first change third change diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/backout.non-tip.cat.out --- a/en/examples/backout.non-tip.cat.out Thu Mar 29 19:55:18 2007 +0100 +++ b/en/examples/backout.non-tip.cat.out Fri Mar 30 23:05:28 2007 -0700 @@ -1,2 +1,3 @@ $ \textbf{cat myfile} +first change third change diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,62 @@ +#!/bin/bash + +#$ name: init + +hg init main +cd main +echo 'This is a boring feature.' > myfile +hg commit -A -m 'We have reached an important milestone!' + +#$ name: tag + +hg tag v1.0 +hg tip +hg tags + +#$ name: main + +cd ../main +echo 'This is exciting and new!' >> myfile +hg commit -m 'Add a new feature' +cat myfile + +#$ name: update + +cd .. +hg clone -U main main-old +cd main-old +hg update v1.0 +cat myfile + +#$ name: clone + +cd .. +hg clone -rv1.0 main stable + +#$ name: stable + +hg clone stable stable-fix +cd stable-fix +echo 'This is a fix to a boring feature.' > myfile +hg commit -m 'Fix a bug' +hg push + +#$ name: + +export HGMERGE=$(mktemp) +echo '#!/bin/sh' > $HGMERGE +echo 'echo "This is a fix to a boring feature." > "$1"' >> $HGMERGE +echo 'echo "This is exciting and new!" >> "$1"' >> $HGMERGE +chmod 700 $HGMERGE + +#$ name: merge + +cd ../main +hg pull ../stable +hg merge +hg commit -m 'Bring in bugfix from stable branch' +cat myfile + +#$ name: + +rm $HGMERGE diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching.clone.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching.clone.out Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,8 @@ +$ \textbf{cd ..} +$ \textbf{hg clone -rv1.0 main stable} +requesting all changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files +1 files updated, 0 files merged, 0 files removed, 0 files unresolved diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching.init.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching.init.out Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,5 @@ +$ \textbf{hg init main} +$ \textbf{cd main} +$ \textbf{echo 'This is a boring feature.' > myfile} +$ \textbf{hg commit -A -m 'We have reached an important milestone!'} +adding myfile diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching.main.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching.main.out Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,6 @@ +$ \textbf{cd ../main} +$ \textbf{echo 'This is exciting and new!' >> myfile} +$ \textbf{hg commit -m 'Add a new feature'} +$ \textbf{cat myfile} +This is a boring feature. +This is exciting and new! diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching.merge.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching.merge.out Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,17 @@ +$ \textbf{cd ../main} +$ \textbf{hg pull ../stable} +pulling from ../stable +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files (+1 heads) +(run 'hg heads' to see heads, 'hg merge' to merge) +$ \textbf{hg merge} +merging myfile +0 files updated, 1 files merged, 0 files removed, 0 files unresolved +(branch merge, don't forget to commit) +$ \textbf{hg commit -m 'Bring in bugfix from stable branch'} +$ \textbf{cat myfile} +This is a fix to a boring feature. +This is exciting and new! diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching.stable.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching.stable.out Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,12 @@ +$ \textbf{hg clone stable stable-fix} +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +$ \textbf{cd stable-fix} +$ \textbf{echo 'This is a fix to a boring feature.' > myfile} +$ \textbf{hg commit -m 'Fix a bug'} +$ \textbf{hg push} +pushing to /tmp/branchingfJgZac/stable +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching.tag.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching.tag.out Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,11 @@ +$ \textbf{hg tag v1.0} +$ \textbf{hg tip} +changeset: +tag: tip +user: Bryan O'Sullivan + +summary: Added tag v1.0 for changeset + +$ \textbf{hg tags} +tip +v1.0 diff -r 1b55292716a4 -r 5fc4a45c069f en/examples/branching.update.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/examples/branching.update.out Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,7 @@ +$ \textbf{cd ..} +$ \textbf{hg clone -U main main-old} +$ \textbf{cd main-old} +$ \textbf{hg update v1.0} +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +$ \textbf{cat myfile} +This is a boring feature. diff -r 1b55292716a4 -r 5fc4a45c069f en/feature-branches.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/en/feature-branches.dot Fri Mar 30 23:05:28 2007 -0700 @@ -0,0 +1,8 @@ +digraph feature_branches { + master -> crypto; + master -> filesystems; + master -> ipc; + master -> memory; + master -> network; + master -> security; +}