Why does Git's stash commit need two parents?

In the Hacker's Guide to Git, I see this mental model for stashes:

enter image description here

The guide tells me that stash@{0} needs both A and B as parents. Why? Why doesn't the stash just point to B, getting rid of the need for C? I think I am missing something in my Git comprehension.

有帮助吗?

解决方案

Because two things are stashed: the indexed content and the worktree content. Both are derived from the checked-out commit. When popping the stash, both can be restored.

其他提示

It doesn't always require two parents, sometimes it actually requires three.

The following diagram illustrate the simplest scenario, with two parents:

       .----S
      /    /
-----H----I

Here H represents your current head, which is the master branch in your example, and two child commits are created when you run git-stash.

The first is I, which represents the index at the time of stashing. In other words, this commit contains the changes that were staged before stashing. It has a single parent, which is the commit which HEAD pointed to. The second (S) is the stash commit, which contains files that were modified before stashing. It has two commits because its changes might be on top of those in I and those in H, that is, they might affect files that were staged or not.

The other scenario happens when you provide the -u switch to the stash command, which tells Git to also stash untracked files. The diagram now becomes:

       .----S----.
      /    /    /
-----H----I    U

The new U commit has all the changes introduced by the untracked files. Notice that it wouldn't make sense for this commit to have any parents since those files don't exist in the current HEAD. The stash commit S now has three parents: H, I and U and now when applying the stash commit Git will also apply the untracked changes.

You can see those diagrams and the diffs clearly by running something like git log --graph stash@{0} or gitk stash@{0}.

许可以下: CC-BY-SA归因
scroll top