It can often happen that you did something wrong by using GIT: you gave the wrong commit message, created too few or too many commits, you have commits in the wrong order or with the wrong content. To change such things, you have to change history in GIT. Interactive rebase in GIT is an efficient and powerful tool for that.
The Idea of Interactive Rebase
Git rebase can change the commits between the current HEAD
and a dedicated commit. You can define the commit either by its hash or by its index relative to the current HEAD
by giving HEAD~n
, where n
is the index. So HEAD~10
means the 10.th commit before the current HEAD
.
To change the last 3 commits before the current HEAD
type git rebase --interactive HEAD~3
or git rebase --interactive hash_of_the_third_commit_after_head
. Pay attention, the third commit after HEAD
is practically the fourth commit in git log, since the first is the HEAD
itself. Instead of --interactive you can also type -i
. This command will open your default editor and list your last three commits. The format is something like:
pick hash_id commit_message
for each commit.
The very first thing you can do is to change the order of the commits in this file. It is pretty straight-forward, just change to order of the lines.
Other than that, you have the following options with each of the commits:
-
Pick (p
): You would like to keep that commit as it is, this is the default action.
-
Reword (r
): You would like to change the commit message of the commit.
-
Edit (e
): You would like to change the content of the commit
-
Squash (s
): It merges the commit with the previous one, keeping both the commit messages
-
Fixup (f
): Same as squash, but it keeps the commit message of the previous commit
-
Exec (x
): Executes a custom shell command
-
Break (b
): It stops the rebasing at that commit, you can continue later with git rebase --continue
-
Drop (d
): It drops that commit together with its content. That’s the best way of getting rid of a commit
-
Label (l
): It attaches a label to the given which is the actual HEAD
: Pay attention! The parameter here is not a commit id.
-
Reset (t
): It resets the label of the current HEAD
commit. It is also not expecting a commit id.
-
Merge (m
): It creates a merge commit.
You should just write the right keyword or its abbreviation (in brackets) before the commit id.
Resolve Issues by Interactive Rebase
Here is a small collection of real life scenarios which can be resolved by interactive rebase.
Change Commit Order
As already mentioned, you can change the order of the commits. If you want to change the order of the last 10 commits:
-
Type git rebase --interactive HEAD~10
-
You see now the list of commits is your default editor. Change their order as you wish.
-
Save this file, resolve all conflicts
There’s a huge chance that you have to resolve some rebase conflicts, in this case change them, add the changed file with calling git add and type git rebase --continue
at the end. Since the rebasing is commit based, it can be that you have to fix similar conflicts in the same file multiple times.
Get Rid of Unnecessary Commits
It can happen that you would like to remove a commit with its content, do the following:
-
Type git rebase --interactive HEAD~10
(to remove some commits from the last 10).
-
Change the “pick
” to “drop
” in the lines of commits to be removed.
-
Save the file and resolve the conflicts.
That’s it, you removed the unnecessary commits with all their content.
One Commit Instead of Multiple Commits
Sometimes, you created too many simple commits and you would like to make your history more clean with less commits. You can simply merge the content of multiple commits into one.
-
Type git rebase --interactive HEAD~10
(to merge some commits from the last 10).
-
Change the “pick
” to “fixup
” in the lines of commits to be merged into the previous ones.
-
Save the file.
Change the Commit Message of Old Commits
What to do if you want to change the commit message of an older commit?
-
Type git rebase --interactive HEAD~10
(to change the message of some commits from the last 10)
-
Change the “pick
” to “reword
” in the lines of commits to be renamed.
-
Save the file.
-
The current commit message will appear in your editor, change it and save it.
Edit an Old Commit
How to change the content of an older commit?
-
Type git rebase --interactive HEAD~10
(to change some commits from the last 10).
-
Change the “pick
” to “edit
” in the lines of commits to be edited.
-
Save the file.
-
Do the changes you want, add them by git add
and commit them by git commit --amend
.
-
Type git rebase --continue
-
Resolve all the conflicts.
Split Commit
How to split an already existing commit?
-
Type git rebase --interactive HEAD~10
(to split a commit from the last 10)
-
Change the “pick
” to “edit
” in the lines of the commit to be split.
-
Save the file.
-
Type git reset
.
-
Add the changes for the first commit and commit it.
-
Add the changes for the second commit and commit it.
-
git rebase --continue
Summary
In my view, interactive rebasing in git is a very powerful option which can make several scenarios easier and faster. But in order to use it in an efficient way, you have to really know how it works.
History
- 20th March, 2020: Initial version