Following my previous post describing how every commit in Git is an immutable snapshot of your entire code base – which cannot be altered or tampered with – I got an interesting question from a friend of mine (who also happens to be a developer).
The question was: If I amend a commit by changing its commit message only (and nothing else), does that make it immutable? To put it in more general terms: Does amending a commit change its hash? Even if it's only the commit message that changes.
Let's answer the question by looking at two examples. I'll be addressing amending a commit from its most general use case, that is making changes to the last commit just created (even though it's technically possible to amend any commit in your history).
Amending a local commit
Here's a history containing three commits, two of which are already published remotely (C0 + C1) and one (C2) yet to be published; notice the spelling mistake in the message of the unpublished commit.
Now, let's see what happens if we fix the typo using
--amend. Will the hash change?
As all commits in Git are immutable, with even the commit message infused upon commit creation, making changes using
--amend actually rewrites history; just like
rebase does! As we can see in the above example, the
--amend command generated a new commit (C3) based on the content from C2 – but with the corrected message added! Since the local changes to master had not yet been pushed, it would be safe to publish the new C3 commit straight away. With C2 no longer having a reference to it, Git would delete it from your internal history next time garbage collection runs; until then it would still exist on your machine and be identified using
$ git reflog.
If you don't pay attention to the fact that the hash of your newly amended commit actually did change, it's easy to be fooled into believing that the original commit actually was changed. 🤓 Especially since
$ git log wouldn't show the original commit no more.
Amending an already published commit
What if C2 would have been published already? What would the history then look like post amending? In this scenario, the fact that no commits can be altered becomes even clearer, as we can easily see how the two histories now have diverged.
With above starting position, amending C2 would create the following case.
If we now compare this history with our final state from the first example we can see that C2 still exists in our history – as the remote master branch references it. In this case, simply pushing our newly amended commit would not work as the two branches have diverging histories.
Generally it's not good practice to rewrite history of already published commits, but as long as you know what you are doing it's perfectly fine. To replace C2 completely from history, our only option here is to force push the change; knowing that we're actually deleting existing data.
As all commits are immutable snapshots, any alterations to their content would change the hash. In more strict terms, amending a commit creates a new commit with the desired changes, leaving the original commit untouched.
Want to know how and what makes up the commit hash? Check out my other post on the subject, if you haven't done that already! 😎
Thanks for reading, and I hope you got a slightly better understanding about what amending a commit really means!