In systems that record full merge history (e.g. DAG-based systems like Git, Mercurial, and others), it may make the most sense to develop features and fixes on branches that are forked from the oldest place that will need the particular changes.
This makes it easier to merge a finished branch into all the target branches.
You start out with just development
.
--o--o--o development
Eventually, you decide the content is ready to be used. You make the production
branch. Work continues on development
, but that work is not yet suitable for production
(which means that you should not try to merge development
into production
).
--o--o--o--o production
\
o--o--o development
A bug is discovered and it needs to be fixed in both branches.
The branch for the bug fix changes should be forked from a common ancestor of all the branches that will need the fix.
--o--o--o--o production
|\
| \------o--o bugfix-1
\
o--o--o development
Once the fix is ready, it is merged into both production
and development
. This is possible because bugfix-1
is forked from a common ancestor of both branches.
--o--o--o--o----------o production
|\ /
| \------o--o bugfix-1
\ \
o--o--o-----o development
Instead of just using the common ancestor, you might even fork the bug fix branch from the commit that introduced the bug. This will make sure the bug fix can be merged into any possible branch that itself incorporates the flawed commit (since in a fully distributed system, you might not know about all the branches that are using the flawed commit).
The “hotfix” branches from A successful Git branching model are a variation of this type of workflow. Git's maintainer has a blog post about the purposes of branches that might also help clarify how/why branches should be created and how to use them effectively when their content might be used in multiple descendent branches (e.g. why you might want to avoid merging an ‘upstream’ branch into a feature branch).
If you work the other way around (fork the bug fix branch from a commit that is only on one of your target branches), you will end up having to “replay” (i.e. “cherry pick” or “rebase”) individual changes from the bug fix branch to the other target branches instead of doing a normal merge. This method will work, but it means that you have to keep track of all the incarnations of the bug fix branch to verify whether a particular target branch contains (a version) of the bug fix (or fall back on manual code inspection).
Make bug fix “on top of” development
.
--o--o--o--o production
\
o--o--o development
\
b--b bugfix-1
Merge it to development
(example shows what is called a ‘non-fast-forward’ merge in Git), and rebase/cherry-pick the bug fix commits (b
) on to production
(b'
) since merging development
into production
would be a bad idea—not all of its content is ready for production:
--o--o--o--o--b'--b' production
\
o--o--o------o development
\ /
b--b bugfix-1
There is no recorded relationship between the b
commits and the b'
commits in the production
branch. This lack of relationship means that you have to ask about both the b
and the b'
commits if you want to be able to answer the question “Does some branch, W, have the bug fix?” in an automated fashion.