Why is git rebase discarding my commits?
This has bitten me at least a dozen times after a certain git upgrade. There is now a difference between git rebase
and git rebase master
: the former was changed to use same fancy "fork-point" machinery. There is a detailed explanation in answer to this question:
- Understanding "git pull --rebase" vs "git rebase"
Today for the first time I figured out concrete steps to reproduce it.
MY SCENARIO: I have 4 commits on master
which I've decided should now move into a topic
branch, plus I want to reorder them. If I do it this way...
Create a new
topic
branch, tracking the current branch (master
)git checkout -b topic -t
Rewind
master
back :git checkout master git reset --hard origin/master
Reorder the commits on
topic
git checkout topic git status # "Your branch is ahead of 'master' by 4 commits" Good! git rebase --interactive
... then the interactive rebase screen comes up with this ominous list of commits:
# no-op
Uh-oh... I save the file and continue anyway. Yup, looks like git's thrown away my work again. topic
now points to the same commit as master
and origin/master
.
So I presume what triggered this for you is:
upgrading git
You had done something like my step 2 on your
master
branch.
In my lay-man's understanding, the fork-point
machinery searches back through the reflog and notices that those commits had been removed from the upstream branch, and comes to the conclusion that to bring your topic branch "up to date" they should be removed there too.
The solution is, instead of:
git rebase
Use one of:
git rebase --no-fork-point
git rebase master
But I suspect like me you wouldn't do this every time. (I mean, we set an upstream branch for a reason, right?) So you'd just learn to recognise when this disaster strikes, use git reflog
and git reset --hard
to recover, and then use the above command.
Still, you need to be careful now - I think this is extremely dangerous. I have had times when I've rebased a large branch and a few commits silently disappeared from the beginning, and I didn't notice for days! I'm fairly comfortable mining git reflog
to do disaster recovery, but I'm not sure everyone is. I wonder if git has started being too clever here.