As you begin creating commits you might ‘accidentally’ create a commit message that is borderline atrocious; something like ‘Fixed the thing’. Although you are definitely aware of the thing you just fixed, other collaborators (including future you) will not know what you fixed and more importantly, why you needed to fix it. Thankfully, Git is well aware of our tendency to craft terrible commit messages and has a handful of commands that save even the vaguest commit message.
Keep in mind, all exercises expect you to have run the script to create files using the scripts found on the Set Up Your Environment page.
I didn't push
You have a couple of options when it comes to fixing a bad commit message. First, you need to ask yourself:
Am I trying to fix the last commit I made or one a few commits back?
Fixing the Last Commit
If you are fixing the last commit you made you can do the following:
- Ensure you are on the correct
branch
- Use
git log --oneline
to ensure the commit you want to fix is at the top of the list. - Enter:
git commit --amend
. - Enter the desired commit message and close the text editor.
BOOM you just fixed your terrible commit message and now no one is the wiser. Congratulations!!!
Fixing an Older Commit
If you aren’t fixing your last commit, you can perform the following:
- Ensure you are on the correct
branch
and enter:git log --oneline
- Identify the SHA-1 hash associated with the commit just before the one you want to fix. For practice, let’s use the one where file 4 was added.
- Enter
git reset --mixed SHA-1
, where SHA-1 is the SHA-1 of the commit before the one you want to fix. - The changes you made in the file 5 and file 6 commits are now sitting in your working directory. Simply re-add and re-commit the changes.
I pushed
Before you begin worrying about that terrible commit message you have pushed to the remote, let’s talk about the risks associated with fixing it. Fixing a commit message you have already pushed is going to require you to use git push --force-with-lease
. Using push --force-with-lease
can cause some serious problems for other collaborators on your project. The embarrassment of a mispelled word is nothing compared to the embarrassment of messing up your collaborators. If your commit is really that bad, or if causing problems doesn’t trouble you, keep reading.
Start by asking yourself:
Am I trying to fix the last commit I made or one a few commits back?
Fixing the Last Commit
If you are fixing the last commit you made you can do the following:
- Ensure you are on the correct
branch
- Use
git log --oneline
to ensure the commit you want to fix is at the top of the list. - Enter:
git commit --amend
. - Enter the desired commit message and close the text editor.
- Enter:
git push --force-with-lease
to force your change to your remote.
BOOM you just fixed your terrible commit message and you potentially caused problems for other collaborators. Congratulations!!! In all seriousness, editing a commit message might seem important at the time, but pushing a terrible commit message isn’t the worst thing in the world, so it is recommended that you do this sparingly.
Fixing an Older Commit
If you aren’t fixing your last commit, you can perform the following…actually wait, this process is very complex and you really need to figure out if you need to fix those commit messages that badly.
Still here? Ok, here we go:
- Ensure you are on the correct
branch
and enter:git log --oneline
- Identify the SHA-1 hash for the commit just before the one you would like to change. For this example, let’s pretend we want to fix the commit for file 5, so we will pick the SHA-1 associated with the file 4 commit.
- Enter:
git rebase -i SHA-1
, where SHA-1 is the SHA-1 of the commit for adding file 4. The-i
is the interactive option and will open your text editor, allowing you to modify therebase
script. - Identify the commits you want to modify in the list and replace the word
pick
with ane
or the wordedit
. When you are happy with your selections, close the editor and go back to the terminal. - The rebase will stop at the first commit to be edited. To begin editing the first commit message, enter
git commit --amend
. Your text editor will open, allowing you to edit the commit message. - Close the text editor and enter:
git rebase --continue
. - Repeat the two previous steps for each commit you would like to edit.
- When you have edited the last commit, the rebase will finish. Enter:
git push --force-with-lease
to push your new commits to the remote.
Tell me why
Commit –amend
The commit --amend
command enables you to modify the message and contents of the last commit you made.
This can be helpful if you identify a spelling error or grammatical issue with the commit message you created or if you forgot to add some of the changes in the working directory.
How commit –amend Works
git commit --amend
will combine the changes in your staging area with the changes in the last commit you made. Your text editor will also open, allowing you to edit the commit message.
Push –force-with-lease
The push --force
command allows you to override a branch history. This can be problematic if another collaborator pushed some commits to the branch you are working on. If you forgot to fetch the latest updates before pushing with the --force
flag, those commits will be deleted.
On the other hand, the less known --force-with-lease
flag checks if you have fetched the latest updates before you decide to rewrite history, avoiding problematic situations. If there are updates to the branch you are working on, and you didn’t fetch them, the --force-with-lease
will make the push command fail.
Reset
For more information on git reset
, check out the ‘Tell me why’ section in the Too Many (small) Commits scenario.
Rebase
The git rebase
command is a powerful tool that can be used to reorder commits, edit commits, or even pick up entire branches and move them.
How Rebase Works
Let’s start with a fairly common use case for rebase:
In the above image, we created a branch called test
and did some work. The branch test
is “based” on the first commit on master
: e137e
. While we were working on our test
branch, some of our collaborators merged their work into master
. If we want to merge in our test
branch, git would need to recursively combine the history on the two branches. This recursive merge strategy would result in a new commit being made as you see below:
Alternatively, you can use rebase
to move the “base” of your test
branch to the current tip of master:
As you can see from the diagram, git picked up the commits on our original test branch a55e
, 97d6
and 1c70
and replayed the entire branch as if we had just created it from master. However, you should also notice the commits that occurred on the test
branch have new SHA-1 hashes because the “base” commit for the branch has changed.
If we were to merge these two branches now, git would do a fast-forward merge, giving us a nice linear history (without the recursive merge commit).
Rebase Interactive
Rebase includes an interactive option that allows us to make changes to the commits as they are being replayed. For example, we can edit our commit messages as well as combine (squash), re-order, and even delete commits.