If I push an amended commit will it create a new commit?
git commit --amend
, just like git rebase
, will create a new commit object. That object is based on a previously existing commit but it is still a new commit and replaces the old one completely.
Looking at the history, this could look like this:
master
↓
* --- * --- * --- A
Considering that A
is the original commit. If we now amend this commit, then we get the following result:
* --- * --- * --- A
\
--- A'
↑
master
So we get a different commit object A'
, with a different hash, and the branch we were on (here: master) is updated to point to this one.
Now, if we add a remote repository to that view, and we pushed A
previously to the remote, then it looks like this:
origin/master
↓
* --- * --- * --- A
\
--- A'
↑
master
So the remote still points at the original commit A
, but our local branch points at the modified A'
. This is a problem because we cannot push A'
and make origin/master
point at A'
as this would remove the already pushed commit A
from the history.
We can perform a forced push using git push --force
to force Git to update the remote branch and indeed delete A
from the history. It is important to note though that this will break everyone’s history who already fetched A
from the remote. If some other developer has A
and now the remote points at A'
, then they have a conflict which they have to fix manually. This is often a pain to do, so there is a rule you should follow at all times:
Never rebase (or amend) previously published commits.
The better alternative is to add a new commit B
which simply does the fixes to A
:
origin/master
↓
* --- * --- * --- A --- B
↑
master
That way, the already published history is still compatible with the new history, so we can push B
to the remote without conflicts, and everyone is happy.
tl;dr
Pushing an amended commit means pushing a different commit.
Anatomy of a Commit ID
The unique ID of a commit is made up of the SHA-1 hash of its metadata. Which metadata? One of the ways to find out is by using the cat-file
plumbing command:
git cat-file -p HEAD
After you run this command you'll see a list containing these fields:
- Tree
- Parent
- Author
- Committer
- Message
If any of these fields change, their SHA-1 hash is also going to change granting the commit a whole new ID.
Amending is Rewriting History
That's why if you amend a commit – for example by changing its message – it's going to have a different ID than it had previously. You're effectively rewriting history.
Note that the ID of the commit's parent is also included in the metadata. This means that once a commit changes ID, all of its descendants are also going to change IDs like a domino effect.