“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 log
commit 53f783b676b7de43ff9dd45b04d59748070840e9 (HEAD -> dev, origin/dev)
Author: Armen96 <barsegyan96armen@gmail.com>
Date: Sat Nov 30 11:37:49 2019 +0400
'Update Readme file :books: /play nyan'
commit 70deb939cd8ec4f2cab401dc871dbb3c51b6502f
Author: Armen96 <barsegyan96armen@gmail.com>
Date: Sat Nov 30 11:30:59 2019 +0400
'I am about to ...
Remove unnecessary prop from env file'
commit 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
...
pick <commit> just means to use the current commit. As we want to change commit message, we need to use reword <commit> option. In your case commit message will be different but it does not matter. Just change pick to reword or just r
reword 53f783b Update Readme file :books: /play nyan
Save changes and then move on. It will open another window.
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 (removing emoji part)
Update Readme file
Then 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
git 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
Stopped at 3f97704... Update Readme file
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
Now time to make fixes, when fixes completed you need to add your changes
git add .
git rebase --continue
git push origin dev -f
Done!
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. It will open 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 push your changes to the repository
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
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 change number of commits
git rebase -i HEAD~n // n=1, 7 or how much 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 Rebase vs Merge article.