假设
我最近添加了或未添加到索引中的更改。现在,我正在挑选一个特定的提交而不在我的HEAD上创建新的提交......
git cherry-pick -n <commit>
如何从索引中删除cherry-pick更改?我可以做一个
git reset HEAD
但我必须重做之前添加的所有更改。
目的
如果有人藏匿藏匿物,则无法将藏匿物推送到遥控器。无法从另一个系统上的遥控器上拉出当前的WIP。所以我编写了shell函数来模拟git-stash,除了我为每个存储使用分支。
apply
或pop
通常会将隐藏的更改应用于WIP,但不会应用当前索引。虽然我使用cherry-pick来应用来自隐藏分支的更改,但所有这些更改都会添加到索引中,然后我需要将它们从索引中删除。
修改(2018-01-29)
我阅读了@torek的回答并理解它。不过我喜欢分享我以前用过的bash函数。
function git-stash {
local gitbranch="$( git branch | grep \* )"
local currentbranch="$( [ "${gitbranch}" == "* (HEAD"* ] && echo "${gitbranch}" | cut -d ' ' -f5 | cut -d ')' -f1 || echo "${gitbranch}" | cut -d ' ' -f2- )"
local stashname="stash/$( date +%s )"
git stash save -u ${stashname}
git checkout -b ${stashname}
git stash pop
git add .
[ ${1} ] && git commit -m "WIP: "$1 || git commit -m "WIP"
git checkout ${currentbranch}
}
function git-stash-apply {
local stashbranches="$( git branch | grep stash/ | cut -d ' ' -f3- | sort -r )"
local stashbranches=(${stashbranches[@]})
local lateststashbranch="${stashbranches[0]}"
git cherry-pick -n "${lateststashbranch}"
}
function git-stash-pop {
local stashbranches="$( git branch | grep stash/ | cut -d ' ' -f3- | sort -r )"
local stashbranches=(${stashbranches[@]})
local lateststashbranch="${stashbranches[0]}"
git cherry-pick -n "${lateststashbranch}"
git branch -D "${lateststashbranch}"
git push origin :"${lateststashbranch}"
}
这还不是一个合适的解决方案,更不用说stash pop
中缺少错误处理了。
答案 0 :(得分:1)
在这种特殊情况下,您可以尝试git revert -n <commit>
,这与反向应用这些更改基本相同。但一般来说,这不是一个可逆的操作,首先完成git cherry-pick -n
是不明智的。
例如,考虑如果delta计算的结果:
git diff $commit^ $commit
表示git cherry-pick $commit
应向README
添加一行,从f1.txt
删除一行,然后更改f2.txt
中的一行(&#34;更改&#34;被remove-old-add-new暗示,真的。)
但是,如果你已经将该行添加到README
并将其更改为f2.txt
,那么实际运行cherry-pick只会修改{{1} }}。 (这是因为Git使用其合并机制,它将发现您的更改及其更改重叠,从而减少重叠。)如果您现在决定取消选择并运行f1.txt
,Git将从git revert -n $commit
删除该行,将该行添加回README
,然后在f1.txt
中恢复原始行,撤消该行。 Git 赢了知道合并操作已经删除了这三个更改中的两个,因为&#34;已经到位&#34;,并将撤消所有这三个。
如果有藏匿者,则无法将藏匿物推送到遥控器。
这不太正确(但也不是很假)。 f2.txt
做的是提交两个或三个提交,其中没有一个提交在一个分支上:一个存储当前索引,一个存储当前工作树(但仅用于当前索引中的文件) )。如果存在第三个提交,它会存储未删除文件减去忽略文件或未跟踪文件(包括忽略文件)。
安排提交,以便工作树提交是最后一个提交,并且另外两个(加上当前提交)作为其父项。然后,最终提交的哈希ID被&#34;推送到&#34;使用git stash
的存储堆栈。
因为这些是提交,所以可以git update-ref
- 编辑。但是,您必须在遥控器上为它们创建一个名称,遥控器将允许您设置该名称。 git push
名称通常不可写。例如:
refs/stash
将使用git push fred stash:refs/heads/sneaky
在远程sneaky
上创建分支名称fred
。
可以使用上面的其他名称发送提交,然后登录到另一个系统 - 如果你想这样做,就将它们偷偷带进refs/stash
名称。但是,您甚至不必这样做,因为refs/stash
等会将任何标识符解析为&#34; stash-like&#34; commit(特别是工作树提交,如果存储是两个提交实体,则有两个父项,如果存储是三个提交实体,则有三个父项):
git stash apply
如果一切顺利且你不再想要这个,那么你可以强行删除分支:
fred$ git stash apply sneaky
fred$ git branch -D sneaky
或apply
通常会将隐藏的更改应用于WIP,但不会应用当前索引。
除非您使用pop
选项,否则也是如此。在这种情况下,存储代码尝试使用--index
恢复索引。
应用这样的存储会调用内部Git合并机制,但通常使用git show <index-commit-hash> | git apply --index
可以获得非常相似的效果。 (请注意,这与实际的挑选或合并或存储调用之间存在细微差别。)