为什么存储表示为2次提交?

Tie*_*eme 16 git git-stash git-log

当存储一些更改时,Git会创建两个单独的提交,"分支上的WIP"和"分支上的索引":

$ git log --graph --all 

*   commit 98aac13303ca086580c1ec9ccba5fe26c2a8ef3c
|\  Merge: 7d99786 82c5c76
| | Author: Tieme <my@email.com>
| | Date:   Wed Nov 19 09:58:35 2014 +0100
| |
| |     WIP on development: 7d99786 Last real commit
| |
| * commit 82c5c763357c401135675a39bfabf9b7f6805815
|/  Author: Tieme <my@email.com>
|   Date:   Wed Nov 19 09:58:35 2014 +0100
|
|       index on development: 7d99786 Last real commit
|
|
| * commit 7d9978637a0e1ef92f2432189bdebf2317f0b2f0
| Author: Tieme <my@email.com>
| Date:   Tue Nov 18 17:32:33 2014 +0100
|
|     Last real commit
|
Run Code Online (Sandbox Code Playgroud)

我查了一下这个文档,但它没有让它更清晰:

存储表示为提交,其树记录工作目录的状态,其第一个父节点是创建存储时HEAD的提交.第二个父树的树在存储时记录索引的状态,并且它成为HEAD提交的子节点.祖先图如下所示:

         .----W
        /    /
  -----H----I
Run Code Online (Sandbox Code Playgroud)

其中H是HEAD提交,我是一个记录索引状态的提交,W是一个记录工作树状态的提交.

为什么我创建的文件有2个提交而不只是一个提交?

Sas*_*olf 19

简短的回答

git stash 区分您对索引所做的更改以及您在工作树中所拥有的更改,并为它们创建提交.

答案很长

一些背景

使用git,您在工作树中所拥有的更改(您直接使用的文件)可能与您在索引上所做的更改不同.

仅向索引添加有限数量的文件,或者git add --patch甚至在文件中添加单个更改的行将使索引处于与工作树不同的状态.
这是一件好事,因为它使您能够创建专注于一个特定任务/功能的提交.

您甚至可能对索引进行了更改,这些更改不再是工作树的一部分.您可以通过向索引(git add)添加一些更改来测试它,手动将其从文件中删除,然后创建commit(git commit).
提交仍将包含您首先添加的更改,尽管它们不再存在于您的工作树中.

如果您无法理解工作树和索引之间的区别,可以查看此问题.

究竟发生了什么?

现在从一开始的陈述应该更有意义.一个"隐藏提交"包含您在工作树中所拥有的所有更改(您直接使用的文件),另一个包含您添加到索引中的更改.

默认情况下git stash popgit stash apply仅尝试恢复工作树中的更改,并忽略对索引所做的更改.git stash通过使用--indexflag(git stash (pop|apply) --index)可以告诉尝试恢复索引.