These examples were created during a discussion with j416 on #github about how best to manage long-running feature branches.
The scenario is this: You have a long-running feature branch, based off master. The feature branch and master both touch the same parts of the same files, so you know that there will be conflicts when you finally merge the feature branch in. What can you do to minimise the conflicts?
The simplest answer is to rebase the feature branch frequently onto master. This will work fine, so long as the feature branch isn't public. If it is, you get the standard rewriting-public-history problem. Another consideration is that, if the feature branch is large, it might take a long time to rebase.
The other option is to merge master into the feature branch frequently. This gist shows how this approach works, and
This gist has four examples:
- The feature branch is never merged into.
- Master is merged into the feature branch.
- Master is merged into the feature branch, then the feature branch is rebased onto master before it's merged into master.
- The above, but with the help of git-rerere.
In all of the examples, master makes a single change, A1, which modifies the two files, file1 and file2. The feature branch makes two changes, B1 (which modifies file1) and B2 (which modifies file2).
A1 and B1 conflict, as do A1 and B2.
Here, master makes the change A1, and the feature branch makes the changes B1 and B2. When the feature branch is merged into master, the conflicts A1/B1 (in file1) and A1/B2 (in file2) both occur.
Here, master makes the change A1, and the feature branch makes the change B1. Master is then merged into feature, causing A1/B1 to conflict in file1. The feature branch then makes the change B2, and the feature branch is merged into master without conflict.
Example 3: Master is merged into the feature branch, then the feature branch is rebased onto master before it's merged into master
This example is largely the same as above. However, before the final merge, the feature branch is rebased on top of master. This results in the merges into the feature branch being stripped, and the history is nice and linear (git-flow style). The downside is that the conflict A1/B1 must be resolved twice -- once on the merge into the feature branch, and once on the rebase.
This example is exactly the same as before, except we use git-rerere to avoid the second merge conflict. Git-rerere automatically records the result of the first merge conflict, and then uses this to automatically resolve the second one (the results of the rebase).