想象一下这种情况:
# edit two files
git add -p // add hunks from one file
Run Code Online (Sandbox Code Playgroud)
现在,当你跑步时git stash -p,它会再次询问你是否想藏匿你刚才选择的帅哥git add -p.有没有办法配置git默认忽略这些已经添加的帅哥?大多数时候,我不想隐藏我已添加的东西.
Syb*_*ers 10
手册页中有一个类似的例子:
男人git藏匿:
"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"*
Run Code Online (Sandbox Code Playgroud)
我可以证实:
如果您使用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.
Run Code Online (Sandbox Code Playgroud)
备择方案:
至少有3种方法可以达到你想要的效果(或多或少):
-pgit stash.存放一切(有--keep-index可能--all,确保你已经安全地存放了所有东西).--amend更改现有提交.好的,从评论来看,需要的是尚未添加的所有git add -p更改的存储(无论是在 期间排除,还是只是尚未添加)。
这样做的原因是在提交之前对暂存状态应用一些测试/潜在的调整。
这是一个直接的操作git stash -k,像往常一样存储所有内容,但保留索引状态和相应的工作树,即从工作树中清除我不打算提交的所有内容。
所以:
git stash -k
git clang-format
git commit
Run Code Online (Sandbox Code Playgroud)
存储库现在有四个有趣的快照:原始内容(又名存储库)、快照索引、快照工作树和当前索引(、提交和工作树),这是stash^2应用清理后的索引快照。请注意,此处的所有三个新快照(又称为提交)都将存储库作为父级。
现在您希望工作树更改回来,但显然从基础到隐藏索引和工作树的更改与当前索引和工作树中的更改不匹配(以及新提交,这些都匹配),因此当 git 去弹出存储时它将发现冲突:从存储库到存储索引的更改与从存储库到当前索引的更改不匹配。
如果 Git 直接提供你想要的东西,“存储除索引中的工作树之外的所有工作树更改”,你可以使用它,然后存储弹出不会有任何麻烦,直接就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
Run Code Online (Sandbox Code Playgroud)
存储弹出是从存储基础到存储状态的更改与从存储基础(通常与当前基础非常相似)到当前状态的更改的合并。您希望隐藏的工作树更改回到您的工作树中,但只有您尚未添加的工作树更改,因为您添加的工作树仍然在这里,它们现在只是有点不同。
因此,最好的选择是-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
Run Code Online (Sandbox Code Playgroud)
现在您已经有效地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
Run Code Online (Sandbox Code Playgroud)
现在,初始提交:/1是1 2 3 4 5,您当前的提交、索引和工作树都是1 _2a 3 4 5,您隐藏的索引是1 2a 3 4 5,您隐藏的工作树是1 2a 3 4a 5。
您想要恢复的更改是隐藏索引和隐藏工作树之间的差异,即隐藏提交与其第二个父级的差异。因此,选择樱桃。
拼写cherry-pick的其他方法包括
git cherry-pick -nm1 -Xours stash
Run Code Online (Sandbox Code Playgroud)
它应用所有隐藏的工作树更改,但在发生冲突时采用本地版本(基本上它是找到并丢弃冲突的差异,而不是像以前那样避免它们-m2)并且
git diff stash^2..stash|git apply -3
Run Code Online (Sandbox Code Playgroud)
让这一切对你自己来说更容易的是脚本领域,谈论设置它的最简单方法是作为 git 别名,
git config --global alias.poptree '!git cherry-pick -nm2 stash; git reset; git stash pop'
Run Code Online (Sandbox Code Playgroud)
现在你有一个git poptree命令可以做你想做的事。
编辑:作为进一步的补充,假设您在记住隐藏的工作树更改之前已经完成了更多工作,樱桃选择将正确更新工作树和索引,但重置将取消您已添加到新工作树中的任何更改指数。现在你处于核心指挥领域,
( index=`git write-tree` &&
git cherry-pick -nm2 stash &&
git read-tree $index &&
git stash drop
)
Run Code Online (Sandbox Code Playgroud)
这就是我真正实现这一点的方式。