I have a master
branch and a topic
branch which diverged from master
at some "last common ancestor" commit.
I rewrote history on my master branch using git rebase
, but forgot, that this included the commit that was the "last common ancestor" with my topic
branch. In other words, if I now git log
the master
branch, it doesn't list the "last common ancestor" commit with topic
anymore.
I assume the "last common ancestor" commit hasn't been garbage collected yet, since it is still referenced by the topic
branch. But it isn't part of the master
branch anymore.
What happens now, if I now try to merge topic
with master
?
For this sort of thing, I find it helps to draw the commits. Of course, since you can't find the exact commit, you'll be stuck with drawing some approximation—but maybe that will help you find the right commits.
I have a
master
branch and atopic
branch which diverged frommaster
at some "last common ancestor" commit.
So, let's draw that, as a sort of rough sketch:
...--c1--c2--c3--c4--m1--...--mn <-- master
\
t1--...--tn <-- topic
where the c
commits are common to both branches, the m
commits are only on master
, and the t
commits are only on topic
. Commit c4
is the last common one.
I rewrote history on my master branch using
git rebase
, but forgot, that this included the commit that was the "last common ancestor" with mytopic
branch. In other words, if I nowgit log
themaster branch
, I can't find the commit ID anymore of the "last common ancestor" commit withtopic
.
Since rebase works by copying commits, then moving the branch name to point to the last-copied commit, let's draw that now, using '
suffixes to show the copied commits:
c2'-c3'-c4'-m1'-...--mn' <-- master
/
...--c1--c2--c3--c4--m1--...--mn [abandoned]
\
t1--...--tn <-- topic
While you can use git log
on topic
to find commit c4
, it's not actually shared with master
any more.
I assume the "last common ancestor" commit hasn't been garbage collected yet, since it is still referenced by the
topic
branch. But it isn't part of themaster
branch anymore.
That's exactly right: while m1-...-mn
are "abandoned", c4
isn't. (Note that the hash IDs of these commits are probably in at least two reflogs: the one for master
, and the one for HEAD
. These reflog entries will keep the commits alive until the reflog entries themselves expire.)
What happens now, if I now try to merge
topic
withmaster
?
The merge operation will find the first actually-common commit, which is now c1
, and diff the contents of c1
(its snapshot) with the contents of mn
(tip of master) to see what you changed on master
, then diff c1
with tn
to see what you changed on topic
. It will then combine the two changes and, if that's successful, make a merge commit on its own:
c2'-c3'-c4'-m1'-...--mn'
/ \
...--c1--c2--c3--c4 M <-- master (HEAD)
\ /
t1--...--tn <-- topic
(The abandoned commits are still in there if they haven't been GC-ed, but they were in the way so I stopped drawing them.) A git log
of master
will now show the duplicated c4
-and-c4'
commits, c3
-and-c3'
, and so on.
To eliminate them, find c4
and c4'
by some process—e.g., manual git log
and eyeballing, or using git cherry
, or using git log --left-right --cherry-mark topic...master
, or whatever you like. Once you know where c4
and c4'
are, you can use the command Omer suggested:
git checkout topic
git rebase --onto master <hash-of-c4>
(or even just put topic
on the end of the git rebase
command, but I prefer not to do that - it's confusing to start on master
and end on topic
...).