Magic is everywhere! Specially in your terminal, and our git has some of its own. In this post I'm going to show you a little of this magic that lives inside the
git rebase
command.
🐻 Bear in mind, this post assumes you are already familiar with git.
git rebase
📖 Reapply commits on top of another base tip.
This sounds and looks just like git merge
... right?
git checkout feature
git rebase master
Not quite. git rebase
, moves the branch and incorporates all of the new commits, but re-writing the project history by creating brand new commits for each commit in the original branch.
These brand new commits thingy thing, brings up the golden rule of rebase: do not rebase on public branches.
Besides rewriting commits, we can add two other key features of git rebase
:
- Doesn't make new commits (because it rewrites them)
- Can be used in the same branch we are working on
This three key features gives us the opportunity to tweak our commits, which comes really in handy when
- we messed up with the commit message
- made a very tiny file change and its commit would be better off inside a larger one
- when we need to change the order of the commits
- remove a whole commit
Getting our hands dirty
Let's say I've been working on this new feature branch, and 4 commits in, I want to make some changes to them using rebase.
git rebase -i HEAD~4
- git rebase: calls, of course, the git-rebase command
- -i: Shorthand for interactive, this makes a list of the commits that we are about to rebase, letting us edit that list and how we are going to rebase them. This file is where we are going to do today's magic.
- HEAD~4: The tilde is used to point to a position relative to a specific commit, in this case, the HEAD; giving us its 4th parent.
Now, a file has been opened on your designed IDE called git-rebase-todo and we are ready to do some magic with out git project.
# git-rebase-todo
pick 4acdb1d First Commit of Feature
fixup be76710 Second Commit of Feature
drop 78acdd0 Third Commit of Feature
reword 9480b3d Fourth Commit of Feature
When we use --interactive
/-i
this file is going to tell git what to do with each of the commits listed. The list can be re-ordered and git will execute your orders from top to bottom!
By default, all commits come with the option pick, but there are many options we can use to alter our commits.
Let's see what that means and what we can do with the other commands rebase has for us.
pick
Pick signals git to use the commit, this means, it will keep this commit and use it in its rebasing.
➡ When should I use pick? Every time we want to keep a commit!
pick be76710 Super awesome commit message
# You can also use the short version: p
p be76710 Super awesome commit message
reword
Reword signals git to use the commit just like pick but lets us change the commit message when it's about to be commited again. This option will prompt you with a file to edit with the previous commit message for you to edit.
➡ When should I use reword? Every time we want to keep a commit, but we need to make changes to it.
reword be76710 Super awesome commit message
# You can also use the short version: r
r be76710 Super awesome commit message
edit
Edit signals git to use the commit, but stops just before commiting to let us make changes or adjustments. This amendments to the code are not limited at all. Everything will be included in the commit long as you stage them: this includes typos, a few more lines of code, or a whole new file.
➡ When should I use edit? Every time we want to keep a commit, but we need to slip in a few more changes to it.
edit be76710 Super awesome commit message
# You can also use the short version: e
e be76710 Super awesome commit message
squash
Squash signals git to merge the commit with the previous one, this means, both commits will become one with a new hash. Git will let you reword the commit message of this newly created commit and will prompt you with a file to edit it.
➡ When should I use squash? Every time we want you want to meld one or more commits with a previous one.
squash be76710 Super awesome commit message
# You can also use the short version: s
s sbe76710 Super awesome commit message
fixup
Fixup signals git to merge the commit with the previous one, just like squash but discarding the commit's message.
➡ When should I use fixup? Every time we wan to meld one or more commits with a previous one disregarding its message is.
pick 4acdb1d Super Awesome Commit
fixup be76710 This commit is going to be merged with the one on top of it
pick 9480b3d Another Super Awesome Commit
# You can also use the short version: f
f be76710 Super awesome commit message
drop
Drop signals git to remove the whole commit.
➡ When should I use fixup? Every time you want to discard all the changes made by a commit.
drop be76710 Super awesome commit message
# You can also use the short version: d
d be76710 Super awesome commit message
So, again, how do I use this magic tricks?
You've just commited a very big change to your new website index.html. Your eyes wonder upon the job done, and suddenly, a nasty typo appears out of nowhere.
✨ Just make another commit with the fixed typo. Invoke the magic words on your terminal git -i rebase HEAD~2
and then, use fixup to merge the commit done for the typo.
After making three commits, you've noticed the first one has a commit message that others in your team would find confusing.
✨ Just call upon the greatness of rebase with git rebase -i HEAD~3
and use reword on the commit you'd like to change its message.
You have noticed the whole commit you've done, five commits ago is wrong, but... there are many commits you don't want to lose using reset!
✨ Rebase comes to hide all of those silly mistakes! Let's recite together on our terminal git rebase -i HEAD~5
and using drop that commit is now gone forever!
With great power comes great responsibility
Before using rebase, you have to make sure if at any point, the commits you are going to merge have already been merged to public branch, if that's the case... don't us rebase. Remember what we've learned about rebase making new commits? You'll have issues because we've just rewritten the commits history!
Another thing to keep in mind is, when we rebase, all the commits are applied one after the other, this means, dropping or changing the order of any commit might pop up conflicts you'll have to fix and then commit before rebase can continue. After you've successfully dealt with them, gracefully resume your rebase with git rebase --continue
. Or just go with git rebase --abort
and cry yourself to sleep remembering those conflicts... oh lord... those conflicts.
📚 Let's read more!
- By the way, I'm aware this post doesn't cover in depth the differences between
merge
andrebase
, but I have good news 🔗Atlassian has a great post about it. - If you need a better way to visualize what
rebase
does to your branch, @lydiahallie has 🔗 excellent animations on how git works on this gorgeous post. - The options I've presented here are not the only ones
rebase
has. If this topic got you hooked, and you crave to expand your knowledge on them and rewriting history, 🔗 git documentation on has a lot of good insight. - If you feel like getting a little more technical, @jessekphillips goes slightly 🔗 more in depth with rebase in a short but sweet post.
That's it from me for now, I hope you find it useful and on your next project less of these pesky typos plague your commit history, thanks to the magic of rebase
✨
Top comments (2)
Nice, I tried my explanation as describing it in terms of scripting.
Interactively Rebase with git
Jesse Phillips ・ Jan 24 ・ 3 min read
I've added your post to the bottom links since I think your explanation goes slightly more in depth. Good post!