在开发过程中,我经常将工作版本的文件(但不提交它们)添加到我的git repo中。我继续处理这些文件,直到它们达到可执行阶段,当我可以提交它们时。所以回购看起来像下面
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: testfile1
#
# 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: testfile1
# modified: testfile2
当我执行git stash
,然后执行git stash pop
时,我会
# 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: testfile1
# modified: testfile2
问题
目前,我手动执行
git stash --keep-index
git stash
git stash pop
git add <stashed_files>
git stash pop
问题是
编辑 - 我更喜欢命令行解决方案,因为我在测试服务器上以类似的方式工作。
答案 0 :(得分:5)
我看到这已经得到了解答,但是让我再补充一点,并发出警告:git stash
中有一个小错误。
当您运行git stash
或git stash save
(默认为save
所以这些是相同的事情)而不使用-p
时,stash
脚本 - 它存在于git-core
目录中,其位置因git安装而异,例如可能在/usr/libexec/git-core
或/usr/local/libexec/git-core
中 - 创建一个包含两个(有时是三个)父提交的提交。按顺序,这些提交是:
-u
或-a
,未跟踪甚至忽略的文件(并且它还使用git clean
从工作目录中删除它们)HEAD
提交之间的增量(这是buglet的来源;见下文)。然后设置refs/stash
指向最后一个提交,即工作目录提交。这个提交有其父母:
stash^
(第一个父级)stash^2
(第二个父级)stash^3
(第三个父级),如果存在。此存储实际上包含存储时所有内容,但当您使用git stash pop --index
或git stash apply --index
恢复“预存状态”时,该错误最佳显示。 (我将在下方使用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
脚本首先尝试将索引添加到原始{{1 }}。 (如果还没有暂存,则会恢复原始状态。)假设它可以执行此操作,然后尝试类似地设置工作目录(再次使用合并机制)。如果它无法正确设置索引,则它对索引不执行任何操作,并建议您在没有save
的情况下重试。
这是buglet的用武之地。假设您从一个文件开始,比如--index
,没有任何变化。你做了一个改变并进行了分步:
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
在索引中被修改,然后在work-dir中再次修改,但第二次更改将其恢复为basefile
提交中的内容。当您运行HEAD
时,存储脚本会意外地记录索引版本,就像它是正在进行中的版本一样。
如果您现在执行git stash save
并运行git stash apply --index
:
git status --short
这里git已将索引版本恢复到索引中,然后将工作目录版本设置为与索引版本相同的内容:
$ 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
存储脚本的修复是一个单词更改,但到目前为止似乎没有人喜欢它。也许问题在于,如果您应用隐藏而不使用 $ cat basefile
base
add to basefile
,这有效地将索引更改(额外行--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
如果我们查看index和work-dir版本,我们现在可以看到$ git reset --hard HEAD
HEAD is now at 94824e1 initial
$ git stash apply -q --index
$ git status --short
MM basefile
的两个版本。)
(对隐藏脚本的单字修复是将行中的basefile
更改为HEAD
:
$i_tree
第118行。我把它发布到git邮件列表并得到了...蟋蟀。 :-))
答案 1 :(得分:3)
使用--index选项。
git stash
git stash pop --index