hanki.dev

What happens when you amend a commit?

It's common knowledge that you can change your last commit with git commit --amend. It opens an editor to change the commit message, and if you have staged any changes they get added to the commit.

Now, let's look what happens under the hood when we amend a commit. This isn't something one must know, but I do find it interesting and it gives a better overall understanding of how git works.

Current situation

I made an example repo with a few commits. Here's what it looks like currently:

> ls
.git   hello.py   README.md


> git log
commit e93f53459e999398c68929659ef6a41ba4fa59c2 (HEAD -> master)
Author: Hannes Kinnunen <hankilapio@gmail.com>
Date:   Fri Sep 16 10:27:44 2022 +0300

    Add another print

commit c00b6b42a5d07f132851859087167f2b0cf3918a
Author: Hannes Kinnunen <hankilapio@gmail.com>
Date:   Fri Sep 16 10:26:25 2022 +0300

    Add readme

commit 7d757538bba9e68a16047cdd027364fd563c0f06
Author: Hannes Kinnunen <hankilapio@gmail.com>
Date:   Fri Sep 16 10:25:19 2022 +0300

    Initial commit

We can see that our HEAD (= what commit our repo is currently pointing at) is currently at the latest commit of master branch.

Amending the commit

Now let's do some changes to hello.py and amend our latest commit:

  • vim hello.py
  • git add hello.py
  • git commit --amend

Let's check what the commit looks like now with git log:

> git log
commit 9c3f52466eb6c6a18cc2c59e43924abbc7bbe141 (HEAD -> master)
Author: Hannes Kinnunen <hankilapio@gmail.com>
Date:   Fri Sep 16 10:27:44 2022 +0300

    Add another print (amended)

The commit message has changed, commit hash has changed (e93f5349c3f524) but the date is still the same. Now, what happened to the previous commit? Did amend create a new commit and delete the previous, or did it just merge staged changes into the old commit and change the hash?

Orphan commits

From now on, I'm gonna use gitk because it's much easier to inspect our commits using GUI. If we run gitk --reflog we can see all our commits, including orphan ones.

Orphan commit in gitk

It's evident that our original commit didn't get deleted: it's still there, just hidden. Our branch just continues to a different commit, the new amended one. The original commit is just kinda hanging there. So what's the difference between these commits?

Original commit Original commit

Amended commit Amended commit

We can see that both of these commits point to the same parent, but our original commit has no branch. This is known as an orphan commit. These commits are ignored, meaning they're not pushed to remote, and if remote contains orphan commits for some reason they're not fetched when you do git clone or git fetch. You also can't see them with git log, you have to use git reflog.

Once these orhpan commits are over 90 days old, they're deleted when git runs garbage collection. It's done automatically after some commands like rebase, merge, pull and commit. You can also run it yourself with git gc.

TLDR

  • --amend does not modify the commit, it creates a new one
  • The old commit is left behind as an orphan commit
  • Orphan commit is a commit without branch
  • Garbage collection deletes orphan commits after 90 days

#study #git

- 3 toasts