I'm attempting to cleanup a large number of topic branches, primarily so that the branch overview for master
in github no longer displays spurious "n ahead" indicators in inactive topic branches due to the presence of identical changes.
Without these spurious indicators, this overview page would offer a great way to see at a glance if any commits from old topic branches were inadvertently missed and not merged back down into master
.
In the diagram below, Y
is a commit in branch topic
that was later applied to master
as Y'
(so they have different sha1 hashes, but identical patch ids).
A --- B --- C --- Y' --- E <-- master
\
X --- Y <-- topic
git cherry master topic
appropriately reports:
- Y
But if I try to clean this up by issuing a git merge topic
from master
, I get a merge conflict since change E
in master
has since altered the context against which the patch applied.
Is there a way to tell master
"Hey, you really do have Y
already, so you can stop reporting that you don't."? (Being able to do this in such a way that it could be applied automatically/programmatically is key.)
You can see the effective difference in revisions between branches by passing the --cherry-pick option to git log.
My favourite incantation runs:
git log --left-right --graph --cherry-pick --oneline branch1...branch2
(which I have aliases as git lr
).
From the man page:
--cherry-pick
Omit any commit that introduces the same change as another commit on the "other side" when the set of commits are limited with symmetric difference.
For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with
--left-right
(see the example below in the description of the--left-right
option). It however shows the commits that were cherry-picked from the other branch (for example, "3rd on b" may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.--cherry-mark
Like
--cherry-pick
(seebelowabove) but mark equivalent commits with=
rather than omitting them, and inequivalent ones with+
.
In order to permanently make git stop worrying about commits that were actually cherry-picked, you can always merge the other branh. The merge commit will be marked as a child revision of both the previous commit and the tip of the merged revision tree.
This tells the revision tree traversal to stop walking the history at that point. Doing so would only be safe when merging a revision from the 'other' branch IFF you **know that all it's parents have been merged (as far as you would ever want them merged).
There is also some way to use grafts. This really means nothing more than that you'll tell git - out of band1 - that a certain revision is a child of another revision, without having to actually rebase onto/merge from it.
1 as in, a handwritten file with pairs of sha1 hashes :)
The positive thing about this is that you don't have to rewrite history for this to work. However, if you want to, you can use git filter-branch
to make the grafts permanent. You no longer need the grafts file then, but of course, you'll be back with the disadvantages of having to rewrite the history (and possibly invalidating published revision ids).
If all else fails, sometimes you can be stuck with remote (topic) branches that you frequently want to merge from, but there are differences that you simply never want to take. These would probably result in the same merge conflicts over and over.
In that case I'll just point at git-rerere (Reuse recorded resolution of conflicted merges) which can make life considerably easier, albeit more complicated
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With