When should I force push after rebasing?
05 Jul 2017tl;dr: assuming it’s your own branch, immediately.
On the last few projects I have been a part of, I have been the defacto Git problem solver.
On more than one occasion, I was presented with something like the following:
$ git l master
* 232e985 (origin/master, origin/HEAD, master) Feature 4
* 94989d0 Feature 3
* 296d0b3 Feature 2
* 4b856cd Feature 1
$ git l feature-5
* 5c31f6d (HEAD -> feature-5) Feature 4
* 420f83b Feature 3
* 724236a (origin/feature-5) Feature 5
* 296d0b3 Feature 2
* 4b856cd Feature 1
In the above, the commits adding features 3 and 4 on each branch are logically
the same, but on the feature-5
branch they’ve somehow ended up after the
commit adding feature 5.
The team was using feature branches, and the author of feature 5 above was trying to rebase their changes onto master, but somehow ended up inserting their commit between commits on master. At this stage, you’re in a pretty bad place, as you’ve diverged from master.
How did this happen? I’m guessing it was the following series of events:
- Developer branches from master to create feature-5
- Features 3 & 4 are pushed to master
- Feature 5 is committed to the feature-5 branch
- Developer runs
git pull --rebase origin master
or similar - … some time passes …
- Developer runs
git pull --rebase
without really thinking about it
After the first few steps above, we have something like the following:
So far, so good. We want to rebase our changes onto master, so that we can test
and push our code. After git pull --rebase origin master
:
Still looking good. At this stage, we could git push --force origin feature-5
and all would be well in the world.
But what happens if we go for a tea and forget what we were doing (or we use an
overzealous git GUI tool), and we try to rebase onto origin/feature-5
?
What we see above is the result of Git rebasing commits 94989d0
, 232e985
and 44e1c44
on top of origin/feature-5
. As the commit ID is computed by
hashing of the contents of a commit and its parent, the same logical commits
from master now exist on our branch with different IDs.
This could have been avoided if we followed this rule of thumb:
If you’re working on your own branch, always push immediately after rebasing.
Some people on the team were seeing a message like the following:
Your branch and 'origin/feature-5' have diverged,
and have 3 and 1 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
and assuming that they should git pull --rebase
, which in this case is exactly what you don’t want.
If you’re looking for further reading Getting Started - Git Basics covers the fundamentals and LearnGitBranching is a great interactive tool.
Diagrams were created using Gitgraph.js, and this script creates an example repository.