Our git development workflow is that topic branches are continuously rebased on the latest master until they are merged.
However, a new developer has created topic branches in which he has done several merges of master into his topic branches to keep them up-to-date.
A---B---C---D---E topic
/ / /
F---G---H---I master
While merging this topic branch to master would be perfectly correct, it results in a very messy history. I want to convert these topic branches into a clean linear rebased history which can be merged cleanly into master with a single --no-ff merge commit i.e.:
A'---B'---E' topic
/
F---G---H---I master
Ideally, there would be some git-fu that would allow me to do the rebase, taking the commits on the topic branch as-is, while automatically applying the merge conflict resolution information already available in the topic merge commits such as C and D.
I know I can simply apply the patch of “git diff master..topic” and then use rebase to work backwards and manually split apart the single patch into individual commits, but is there a simpler and more elegant approach?
I’ve tried straight git rebase and git rebase -p commands with no luck.
I found the following process seems to work reasonably well, though not perfectly. Some minor conflict resolutions may be required — see below.
Ensure the topic branch is up-to-date with the latest master by doing a final merge from master, if not done already:
Simplify the history of the topic branch by excluding merges:
From the above log, determine the branch point (the commit on master before the first topic branch commit, which should be commit F).
Rebase the topic branch onto master, ignoring merges (which is the default, i.e. do not use the
--preserve-merges/-poption), resolving any conflicts.I found that during rebasing, often a conflict would result in which a file was in a conflicted “Both Modified” state, but it contained no conflict markers, so a simple
git addandgit rebase --continuewas sufficient to resolve the conflict and continue. I believe git was using the previous resolution to resolve the conflicts.Also, in some more complex branches, multiple
git rebase --onto HEAD ...commands will be required, or alternativelygit cherry-pickcan be used to pick out individual commits. Simply work through the log given in Step #2, rebasing ranges onto HEAD and/or potentially cherry-picking individual commits as necessary.The current HEAD should now represent the rebased topic branch. Verify that the result matches the original topic branch by checking that the diff results in no output:
Name HEAD to the rebased topic branch name: