我看到这已经回答了,但让我再补充一点,还有一个警告:在git stash
.
当你在不使用的情况下运行git stash
或git stash save
(默认是save
相同的东西)时-p
,stash
脚本——它位于git-core
目录中,其位置因 git 安装而异,它可能在/usr/libexec/git-core
或/usr/local/libexec/git-core
例如——创建一个包含两个 (或者有时是三个)父提交。按顺序,这些提交是:
- 当前索引
- 带有
-u
or -a
,未跟踪甚至被忽略的文件(它还用于git clean
将它们从工作目录中删除)
- 工作目录,基于当前工作目录和
HEAD
提交之间的增量(这是 buglet 的来源;见下文)。
然后它设置refs/stash
为指向这些提交中的最后一个,即工作目录提交。这个提交作为它的父母:
- HEAD 提交,作为
stash^
(第一父)
- 索引提交,作为
stash^2
(第二个父级)
- 未跟踪/忽略的提交,作为
stash^3
(第三父),如果它存在。
git stash pop --index
这个存储实际上包含存储时的所有内容,但是当您使用或git stash apply --index
恢复“预存储状态”时,buglet 显示得最好。(我将在git stash apply
下面专门使用,但pop
后面apply
紧跟drop
.)
现在,如果您只是运行git stash apply
,正如您所指出的,它会为您提供大量changes not staged for commit
文件,即使您在运行之前已经仔细准备了一些内容git stash save
。这是因为像这样将这些更改合并在一起要容易得多,无论工作目录状态如何,包括您是否签出不同的分支或其他任何内容,以及是否在运行git stash apply
. (实际上,git stash apply
使用 git 的合并代码来引入工作目录更改。)
但是,如果您运行git stash apply --index
,该stash
脚本首先会尝试将您在原始save
. (如果还没有上演任何内容,这将恢复您的原始状态。)假设它可以做到这一点,然后它会尝试类似地设置工作目录(再次使用合并机制)。如果它无法正确设置索引,它不会对索引做任何事情,并建议您在没有--index
.
这就是 buglet 的用武之地。假设您从一个文件开始,例如basefile
,没有任何更改。您进行更改并暂存:
$ cat basefile
base
$ git status --short
$ echo add to basefile >> basefile; git add basefile
但随后您决定希望工作目录副本与HEAD
修订版没有任何变化:
$ ed basefile
21
2d
w
5
q
$ git status --short
MM basefile
这里棘手的一点是basefile
在索引中修改,然后在工作目录中再次修改,但第二次更改将其恢复为HEAD
提交中的内容。运行git stash save
时,stash 脚本会意外记录索引版本,就好像它是正在进行的版本一样。
如果您现在执行git stash apply --index
并运行git status --short
:
$ git stash save
Saved working directory and index state WIP on master: 94824e1 initial
HEAD is now at 94824e1 initial
stash created
$ git stash apply --index
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: basefile
#
$ git status --short
M basefile
这里 git 已将索引版本恢复到索引中,然后将工作目录版本设置为与索引版本中相同的内容:
$ cat basefile
base
add to basefile
stash 脚本的修复是一个单词的更改,但到目前为止似乎没有人喜欢它。也许问题在于,如果您在不使用 stash 的情况下 --index
应用存储,这将有效地将索引更改(额外的行,add to basefile
)与任何内容结合起来,因此工作目录版本具有额外的行。但是,这与索引和工作目录版本不同时的行为方式不一致:
$ git stash drop
Dropped refs/stash@{0} (61c83c866bc522c58df62320b77e647ffd28aa95)
$ echo base > basefile
$ git status --short
$ echo add to basefile >> basefile
$ git add basefile
$ ed basefile
21
2c
different change
w
22
q
$ git status --short
MM basefile
$ git stash save
Saved working directory and index state WIP on master: 94824e1 initial
HEAD is now at 94824e1 initial
$ git stash apply
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: basefile
#
no changes added to commit (use "git add" and/or "git commit -a")
$ cat basefile
base
different change
在这里,通过将索引和工作树更改“混合在一起”,但不应用,我们仅--index
恢复工作树更改。
(幸运的是,因为我们使用apply
而不是pop
我们现在可以改变主意:
$ git reset --hard HEAD
HEAD is now at 94824e1 initial
$ git stash apply -q --index
$ git status --short
MM basefile
如果我们查看 index 和 work-dir 版本,我们现在可以看到这两个版本basefile
。)
(对 stash 脚本的单字修复是在以下行中更改HEAD
为$i_tree
:
git diff --name-only -z HEAD -- >"$TMP-stagenames" &&
在第 118 行左右。我将其发布到 git 邮件列表并得到了……蟋蟀。:-) )