I’m not Git expert and I regularly learn things in Git that changes my view of the tool.
When I was showed git rebase -i
, I stopped over-thinking about my commits.
When I discovered git reflog
, I became more confident in rebasing.
But I think one of the most important command I was taught was git rebase --onto
.
IMHO, the documentation has room for improvement regarding the result of option. If taking the image of the tree, it basically uproots a part of the tree to replant it somewhere else.
Let’s have an example with the following tree:
o---o---o---o master
\
\---o---o branch1
\
\---o branch2
Suppose we want to transplant branch2
from branch1
to master:
o---o---o---o master
\ \
\ \---o' branch2
\
\---o---o branch1
This is a great use-case!
On branch branch2
, the command would be git rebase --onto master branch1
.
That approximately translates to move everything from branch2
starting from branch1
to the tip of master
.
I try to remember the syntax by thinking the first argument is the new commit, the second is the old one.
So, but what use-cases are there to move parts of the tree?
Delete commits
While my first reflex when I want to delete commits is to git rebase -i
, it’s not always the most convenient.
It requires the following steps:
- Locating the first commit to be removed
- Effectively run the
git rebase -i
command - In the editor, for every commits that needs to be removed, delete the line
- Quit the editor
If the commits to be removed are adjacent, it’s easier to rebase --onto
, because you only need the new and the old commit and can do the "deletion" in one line.
Here’s an example:
o---A---X---Y---Z master
To remove the last 3 commits X
, Y
and Z
, you just need:
git rebase --onto A Z
Long-lived remote branches
While it’s in general a bad idea to have long-lived branches, it’s sometimes required.
Suppose you need to migrate part of your application to a new framework, library, whatever. With small applications, a small task-force can be dedicated to that. The main development team goes on week-end with instructions to commit everything before leaving on Friday. When they come back on Monday, everything has been migrated.
Sadly, life is not always so easy and applications can be too big for such an ideal scenario.
In that case, the task force works on a dedicated migration
branch for more than a week-end, in parallel with the main team.
But they need to keep up-to-date with the main
branch, and still keep their work.
Hence, every now and then, they rebase the migration
branch at the top of master
:
git rebase --onto master old-root-of-migration
This is different from merging, because you keep the history linear.
Local branches
Sometimes, I want to keep my changes locally, for a number of reasons. For example, I might tinker with additional (or harsher) rules for the code quality tool. In that case, I want to take time to evaluate whether this is relevant for the whole team or not.
As above, this is achieved by regularly rebasing my local tinker
branch onto master
.
As above, it lets me keep my history linear and change the commits relevant to tinker
if the need be.
Merging would prevent me from doing this.
Conclusion
git rebase --onto
can have different use-cases.
The most important ones are related to the handling of long-lived branches, whether local or remote.
As always, it’s just one more tool in your toolbelt, so that not everything looks like a nail.
As every command that changes the Git history, git rebase --onto should only change local commits.
You’ve been warned!
|