Amending a commit
One of the better things about Git is that you can undo almost anything; you only need to know how to. This is because no matter how carefully you craft your commits, sooner or later, you’ll forget to add a change or mistype the commit message. That’s when the --amend
flag of the git commit
command comes in handy; it allows you to change the very last commit really easily. Note that with git commit -- amend
, you can also amend the merge commits (for example, to fix a merging error). Figure 2.4 shows how this amend operation changes the graph of revisions which represents the history of the project.
Tip
If you want to change a commit deeper in the history (assuming that it was not published, or, at least, there isn’t anyone who based their work on the old version of the said commit), you need to use interactive rebase, or some specialized tool such as StGit (a patch stack management interface on top of Git). Refer to Chapter 10, Keeping History Clean, for more information.
Figure 2.4 – The graph of revisions before and after amending the last commit
If you just want to correct the commit message, assuming you don’t have any staged changes, you simply run git commit --amend
and fix it (note that we use git commit
without the -a
/ --
all
flag):
$ git commit --amend
If you want to add some more changes to that last commit, you can simply stage them as normal with git add
and then amend the last commit, as shown in the preceding example, or make the changes and then use git commit -
a --amend
:
Important note
There is a very important caveat: you should never amend a commit that has already been published! This is because amending effectively produces a completely new commit object that replaces the old one, as can be seen in Figure 2.4. In this figure, you can see that the most recent commit before the operation, denoted by C5, is replaced in the project history by the commit C5’, with amended changes.
If you’re the only person who had this commit, doing this is safe. However, after publishing the original commit to a remote repository, other people might already have based their new work on that version of the commit. In this case, replacing the original with an amended version will cause problems downstream. You will find out more about this issue in Chapter 10, Keeping History Clean.
That is why, if you try to push (publish) a branch with the published commit amended, Git prevents overwriting the published history and asks you to force push if you really want to replace the old version (unless you configure it to force push by default). More about that in Chapter 6, Collaborative Development with Git.
The old version of the commit before amending would be available in the branch reflog and in the HEAD reflog; for example, just after amending, the amended version would be available as @{1}
. This means that you can undo the amend operation with, for example, git reset --keep HEAD@{1}
, as described in the Rewinding or resetting a branch section. Git would keep the old version for a month (30 days) by default if not configured otherwise, unless the reflog is manually purged.
You can always check the log of operations in the reflog by using the git reflog
command. Just after amending a commit, that command output would look like the following:
$ git reflog --no-decorate 94d3e03 HEAD@{0}: commit (amend): After amending d69a0a9 HEAD@{1}: commit: Before amending
Here, HEAD@{1}
means the position of the current branch 1
operation back. Besides the HEAD reflog, there is also a reflog for each branch, as described later. Note that you can read more about using reflog to refer to commits in Chapter 4, Exploring Project History.