想象一下这种情况:
# edit two files
git add -p // add hunks from one file
现在,当您运行git stash -p
时,它会再次询问您是否要通过git add -p
存储您刚刚选择的帅哥。有没有办法配置git默认忽略这些已经添加的帅哥?大多数时候,我不想隐藏已添加的东西。
答案 0 :(得分:10)
联机帮助页中有一个类似的示例:
man git stash:
"Testing partial commits
You can use git stash save --keep-index when you want
to make two or more commits out of the changes in the
work tree, and you want to test each change before
committing:
# ... hack hack hack ...
$ git add --patch foo # add just first part to the index
$ git stash save --keep-index # save all other changes to the stash"*
我可以确认:
如果您使用git stash -p
(暗示--keep-index
),您仍会被问到是否应该隐藏索引中已有的更改(如您所述)。
因此,该联机帮助页似乎令人困惑,其他地方也提到了这一点:https://github.com/progit/progit2/issues/822
总结一下:
--keep-index
(或-p
暗示--keep-index
)只保留索引。已经上演的更改仍会插入到存储中。而AFAIK,没有办法做你所描述的。
或者,更准确地说(再次来自联机帮助页):
With --patch, you can interactively select hunks from
the diff between HEAD and the working tree to be stashed.
The stash entry is constructed such that its index state
is the same as the index state of your repository, and its
worktree contains only the changes you selected interactively.
<强>备选方案:强>
至少有3种方法可以达到你想要的效果(或多或少):
-p
与git stash一起使用。存放所有内容(使用--keep-index
和可能--all
,以确保您已安全地存放所有内容)。 --amend
更改现有提交。答案 1 :(得分:2)
好的,根据评论,我们想要的是隐藏所有更改但尚未添加(无论是在git add -p
期间排除,还是仅添加了。)
这样做的原因是在提交之前对分阶段状态应用一些测试/潜在调整。
这是一个直的git stash -k
,像往常一样藏匿所有内容,但保持索引状态和相应的工作树,即从工作区清除我不想提交的所有内容。
所以:
git stash -k
git clang-format
git commit
并且存储库现在有四个有趣的快照:原始内容,即存储库,快照索引,快照工作树和当前索引(,提交和工作树),它是stash^2
处的索引快照清理应用。请注意,此处提交的所有三个新快照都将stash base作为父级。
现在你希望你的工作树更改回来,但显然从基础到stashed索引和worktree的更改与当前索引和工作树(以及新提交,那些都匹配)中的更改不匹配,所以当git转到弹出存储它会发现冲突:从存储基础到存储索引的更改与存储基础到当前索引的更改不匹配。
如果Git直接提供了你想要的东西,那么&#34;存储所有工作树的更改除了索引中的那些&#34;,你可以使用它,然后stash pop wouldn&# 39;有任何麻烦,直接git stash pop
会这样做。幸运的是,如果Git擅长任何事情,那就是它的融合,合并,分裂以及全面的差异化。
git cherry-pick -nm2 stash
# cherry-pick updated the index, too. maybe git reset here to unstage that stuff.
git stash drop
Stash pop是从存储库到stashed状态的更改与从存储库(通常与当前基础非常相似)到当前状态的更改的合并。你希望在你的工作树中恢复被隐藏的工作树,但只有那些你已经添加的工具树,因为你添加的那些仍然在这里,他们只是一点点现在不同了。
所以,挑选是-n
,没有提交,-m2
,更改的主线是它的第二个父级,即你所做的所有差异,但在存储时没有添加。
一个例子可能会有所帮助,
cd `mktemp -d`
git init
printf >file %s\\n 1 2 3 4 5
git add .;git commit -m1
printf >file %s\\n 1 2a 3 4 5
git add .
printf >file %s\\n 1 2a 3 4a 5
现在您有效地git add -p
了2a更改,而4a更改仅在您的工作树中。
$ git stash -k
$ cat file
1
2a
3
4
5
$ sed -i '2s,^,_,' file # indent the 2a line
$ git commit -am2
现在,初始提交:/1
为1 2 3 4 5
,您当前的提交,索引和工作树都是1 _2a 3 4 5
,您的存储索引是1 2a 3 4 5
,您的存储工作树是是1 2a 3 4a 5
。
您想要的更改是您的藏匿索引与隐藏的工作树之间的差异,这是隐藏提交与其第二个父级的差异。因此,那个樱桃挑选。
拼写樱桃选择的替代方法包括
git cherry-pick -nm1 -Xours stash
应用所有隐藏的工作树更改,但在发生冲突时采用本地版本(基本上它找到并丢弃冲突的差异,而不是像-m2
那样避免它们)和
git diff stash^2..stash|git apply -3
让所有这些变得更加轻松自己是脚本领域,谈论设置它的最简单方法是作为git别名,
git config --global alias.poptree '!git cherry-pick -nm2 stash; git reset; git stash pop'
现在你有一个git poptree
命令来做你想做的事。
编辑:作为进一步的补充,假设你已经完成了更多的工作,然后记住你的stashed worktree更改,cherry-pick将正确更新工作树和索引,但重置将取消你已经添加的任何更改到新的索引。现在你处于核心指挥领域,
( index=`git write-tree` &&
git cherry-pick -nm2 stash &&
git read-tree $index &&
git stash drop
)
是我如何实现这一点。