Git Interactive Rebase
“Can you please remove your last commit we decided not to use that feature ?”.
“Can you please squash your commits together so we get a clean, reversible git history?”.
“Can you rewrite your commit’s message to describe better the problem it solves, and how it solves it?”.
How to deal with these kinds of situations?
Interactive Rebase
git rebase re-applies commits, one by one, in order, from your current branch onto another. It accepts several options and parameters, so that’s a tip of the iceberg explanation, enough to bridge the gap in between StackOverflow or GitHub comments and the git man pages.
An interesting option it accepts is — interactive (-i for short), which will open an editor with a list of the commits which are about to be changed. This list accepts commands, allowing the user to edit the list before initiating the rebase action.
Let’s run git log command
git logcommit 53f783b676b7de43ff9dd45b04d59748070840e9 (HEAD -> dev, origin/dev)
Author: Armen96 <barsegyan96armen@gmail.com>
Date: Sat Nov 30 11:37:49 2019 +0400 Update Readme file :books: /play nyancommit 70deb939cd8ec4f2cab401dc871dbb3c51b6502f
Author: Armen96 <barsegyan96armen@gmail.com>
Date: Sat Nov 30 11:30:59 2019 +0400 I am about to ...
Remove unnecessary prop from env filecommit 06243e81ad3b518202648a1322207be7c70db2b9
Author: Armen96 <barsegyan96armen@gmail.com>
Date: Sun Nov 24 18:28:04 2019 +0400 Git amend command
Changing a commit message
Let’s remove :books: emoji from my last commit message
Update Readme file :books: /play nyan
Let’s run
git rebase -i HEAD~1
HEAD is a reference to the commits in the currently check-out branch. HEAD~n is a reference to the last n commits.
It will open a new window
pick 53f783b Update Readme file :books: /play nyan# Rebase 70deb93..53f783b onto 70deb93 (1 command)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message...
reword 53f783b Update Readme file :books: /play nyan
Save changes and then move on. It will open another window where you can find you commit message with instructions
Update Readme file :books: /play nyan# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Sat Nov 30 11:37:49 2019 +0400
...
Now time to modifying the message (e.g. removing emoji part)
Update Readme file
After finishing you just need to push your changes to the repository.
git push origin dev -f
The result of git log will be
commit deeef03dfa0888b27327eef1424f92a4a7b12aad (HEAD -> dev, origin/dev)
Author: Armen96 <barsegyan96armen@gmail.com>
Date: Sat Nov 30 11:37:49 2019 +0400 Update Readme file
As you can see commit message changed successfully!
Also, you can achieve the same result with
git commit --amend// chnage your commit message then push itgit push origin master --force
But if you want to go n numbers of commits back, the solution is git rebase -i HEAD~n
Editing a commit
If you committed your changes but later you noticed that something wrong in your code but you do not want to add an additional commit with this message BugFix … or something like that, you can do it with rebase edit. Imagine you want to edit the most recent commit so
git rebase -i HEAD~1
pick b50745c Update Readme file
Change pick to edit or just e then you can see a new window
Stopped at 3f97704... Update Readme file
You can amend the commit now, with git commit --amendOnce you are satisfied with your changes, run git rebase --continue
Now time to make fixes or updates, when fixes completed you need to add your changes
git add .git rebase --continuegit push origin dev -f
Done! Your new changes in the same commit and no one can detect that you make some changes except you :)
Squashing commits
Can you please squash your last 2 commits together so we get a clean, reversible git history? Yes, sure. Just a moment.
git rebase -i HEAD~2
You will see your last 2 commits
pick 70deb93 I’m about to …
pick b50745c Update Readme file
Change pick to squash or just s
pick 70deb93 I’m about to …
squash b50745c Update Readme file
It means that we want to combine this b50745c Update Readme file commit with this 70deb93 I’m about to … one. Move on. It will open a new window
# This is a combination of 2 commits.
# This is the 1st commit message:I'm about to ...Remove unnecessary prop from env file# This is the commit message #2:Update Readme file
You can edit the commit messages but the aim is to combine them together so you can just comment one of them and update another one like this
# This is a combination of 2 commits.
# This is the 1st commit message:Remove unnecessary prop from env file and Update Readme file# This is the commit message #2:#Update Readme file*
Then just push your changes to the repository. After pushing you can see only one commit and inside that very commit will be the combined version of these two commits.
git push origin dev -f
Removing a commit
Can you please remove your last commit we decided not to use that feature? Yes, sure. Just a moment.
git rebase -i HEAD~1
pick cdf92bc Remove unnecessary prop from env file and Update Readme file
Change pick to drop or just d
drop cdf92bc Remove unnecessary prop from env file and Update Readme file
Which means that we want to drop the commit, then push your changes to the repository.
git push origin dev -f
Congratulations, you removed your last commit.
Actually, you can squash, drop, fixup, … as much commits as you want just you need to change the number of commits
git rebase -i HEAD~n // n=1, 7 or how much commits you have
Git rebase is the powerful command with a bunch of options which can make our programming life more interesting and meaningful.
Also, I recommend you to read the article by Filiz Senyuzluler git Rebase vs Merge.
Thanks for reading!