gitrebasesquashfixup

How does git keep track of the commit hash marked with a fixup/squash flag?


I know that git commit --fixup <commit A's hash> can make a commit B that will be combined with commit A, when executing git rebase -i --autosquash.

And when I run git log, my commit log looks something like

commit <commit B's hash>
Author: xxx
Date:   xxx

fixup! commit A's comment

commit <commit A's hash>
Author: xxx
Date:   xxx

commit A's comment

To me, the fixup commit looks nothing different from a normal commit except the comment is preceded with a "fixup!".

I wonder how and where git keeps track of the fact that commit B is a fixup commit marked with <commit A's hash>, if it does at all; and if that is the case, is there a git log equivalent that allows me to access <commit A's hash> along with commit B?

Thanks!


Solution

  • (Disclaimer: this answer is based on observations)

    It doesn't keep track of which commit to fixup, it looks for it when you do a rebase and uses the commit message to find the right one.

    I tried the following:

    1. Created a new repository
    2. Made a few commits
    3. Made 2 commits, both with the message "initial"
    4. I then made a fixup commit that fixed the last of those two

      git commit --fixup bb4adbd
      

    The log now looks like this:

    λ git lg
    * 21e0572: (5 minutes ago) fixup! initial (HEAD -> master)
    | Lasse Vågsæther Karlsen <lasse@vkarlsen.no> (Wed, 16 Jan 2019 17:32:51 +0100)
    |
    * bb4adbd: (5 minutes ago) initial
    | Lasse Vågsæther Karlsen <lasse@vkarlsen.no> (Wed, 16 Jan 2019 17:32:38 +0100)
    |
    * e6549e4: (9 minutes ago) initial
    | Lasse Vågsæther Karlsen <lasse@vkarlsen.no> (Wed, 16 Jan 2019 17:28:59 +0100)
    |
    * a311a82: (9 minutes ago) second
    | Lasse Vågsæther Karlsen <lasse@vkarlsen.no> (Wed, 16 Jan 2019 17:28:12 +0100)
    |
    * 2a5ca27: (10 minutes ago) initial
      Lasse Vågsæther Karlsen <lasse@vkarlsen.no> (Wed, 16 Jan 2019 17:27:12 +0100)
    

    If I do this:

    git rebase -i HEAD~3
    

    Then git suggests this:

    pick e6549e4 initial
    fixup 21e0572 fixup! initial
    pick bb4adbd initial
    

    Here git is trying to fixup my first "initial" commit, which is not the one I told it to fixup earlier.

    However, if I just do HEAD~2, it suggests this:

    pick bb4adbd initial
    fixup 21e0572 fixup! initial
    

    Which means that git doesn't track which commit this is about, at all, it simply records a fixup! <commit message> on the end of the commit message of the fixup commit.


    A guess as to why it does this, instead of recording the SHA, would be that this would survive a rebase, a cherry-pick, etc. Additionally, this might've been added without a real way to record this sha in a proper way, because if it did record the sha of the commit it fixed, that record would either prevent a rebase, or would have to be modified as well.