Git存储删除添加的更改

mu *_*u 無 7 git git-stash git-index

在开发过程中,我经常将文件的工作版本(但不提交它们)添加到我的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
Run Code Online (Sandbox Code Playgroud)

当我做一个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
Run Code Online (Sandbox Code Playgroud)

问题

  1. 为什么git不像以前那样存放它们?
  2. 如何一次性存储我的更改,以便在进行存储弹出时,我获得较旧的状态,而不是较新的状态?

目前,我手动做

git stash --keep-index
git stash
git stash pop
git add <stashed_files>
git stash pop
Run Code Online (Sandbox Code Playgroud)

这个问题是

  1. 隐藏和弹出需要5个步骤,我正在寻找2
  2. 我有时可能不记得有2个背靠背的东西,这使任务稍微复杂化.

编辑 - 我更喜欢命令行解决方案,因为我在测试服务器上以类似的方式工作.

tor*_*rek 5

我看到这已经回答了,但是让我再补充一点,并发出一个警告:里面有一个小问题git stash.

当你运行git stashgit stash save(默认是save这些是相同的东西)没有使用时-p,stash脚本 - 它存在于git-core目录中,其位置根据git安装而变化,它可能在/usr/libexec/git-core/usr/local/libexec/git-core例如 - 创建一个带有两个的提交(或有时三)家长提交.按顺序,这些提交是:

  • 目前的指数
  • 使用-uor -a,未跟踪甚至忽略文件(它还用于git clean从工作目录中删除它们)
  • 工作目录,基于当前工作目录和HEAD提交之间的增量(这是buglet的来源;见下文).

然后它设置refs/stash为指向最后一个提交,即工作目录提交.这个提交有它的父母:

  • HEAD提交,为stash^(第一个父)
  • 索引提交,为stash^2(第二个父)
  • 未跟踪/忽略的提交,如stash^3(第三个父级),如果它存在.

事实上,这个藏匿包含了藏匿时所有内容,但当你使用git stash pop --indexgit 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脚本首先会尝试将索引与原始索引完全相同save.(如果还没有暂存,则会恢复原始状态.)假设它可以执行此操作,然后尝试类似地设置工作目录(再次使用合并机制).如果它无法正确设置索引,则它对索引没有任何作用,并建议您在没有的情况下重试--index.

这是buglet的用武之地.假设你从一个文件开始,比如basefile没有任何变化.你做了一个改变,并分阶段:

$ cat basefile
base
$ git status --short
$ echo add to basefile >> basefile; git add basefile
Run Code Online (Sandbox Code Playgroud)

但是你决定要让工作目录副本从HEAD修订版中没有变化:

$ ed basefile
21
2d
w
5
q
$ git status --short
MM basefile
Run Code Online (Sandbox Code Playgroud)

这里棘手的一点是basefile在索引中修改,然后在work-dir中再次修改,但第二个更改将其恢复到HEAD提交中的内容.运行时git stash save,存储脚本会意外地将索引版本记录为工作进行中的版本.

如果您现在执行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
Run Code Online (Sandbox Code Playgroud)

这里git已将索引版本恢复到索引中,然后将工作目录版本设置为索引版本中的相同内容:

$ cat basefile
base
add to basefile
Run Code Online (Sandbox Code Playgroud)

存储脚本的修复是一个单词更改,但到目前为止似乎没有人喜欢它.也许问题是,如果你没有 应用存储--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
Run Code Online (Sandbox Code Playgroud)

在这里,通过"拼凑"索引和工作树的变化,但不应用--index,我们恢复工作树的变化.

(幸运的是,因为我们正在使用apply而不是pop我们现在可以改变主意:

$ git reset --hard HEAD
HEAD is now at 94824e1 initial
$ git stash apply -q --index
$ git status --short
MM basefile
Run Code Online (Sandbox Code Playgroud)

如果我们查看index和work-dir版本,我们现在可以看到两个版本basefile.)

(对存储脚本的单字修复是在行读取中更改HEAD$i_tree:

git diff --name-only -z HEAD -- >"$TMP-stagenames" &&
Run Code Online (Sandbox Code Playgroud)

我把它发布到了git邮件列表并得到了...蟋蟀.:-))


ton*_*ton 3

使用 --index 选项。

git stash
git stash pop --index
Run Code Online (Sandbox Code Playgroud)