Search code examples
gitpushgit-amend

If I push an amended commit will it create a new commit?


I have already pushed a commit on the remote branch and now I want to change its content, so I tried git amend.

If do git status it says that the two branches have 1 and 1 different commits each, respectively.

Now if I push the amended commit with the same commit message, will that add a new commit or it will change the last commit I have pushed?


Solution

  • 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.