我在git stash中保存了一个小补丁。我已使用git stash apply
将其应用于我的工作副本。现在,我想通过反向应用修补程序来回退这些更改(有点像git revert
会对存储进行操作。)
有谁知道怎么做?
澄清:我的工作副本中还有其他更改。我的特殊情况很难描述,但您可以想象一些存储中的调试或实验代码。现在它在我的工作副本中混合了一些其他的变化,我希望看到效果有和没有来自藏匿处的变化。
它当前看起来不像stash支持,但git stash apply --reverse
将是一个不错的功能。
答案 0 :(得分:162)
根据git-stash manpage,“存储被表示为一个提交,其树记录了工作目录的状态,其第一个父节点是创建存储时HEAD
的提交,”并且git stash show -p
给了我们“存储中记录的变化,作为被藏匿状态与其原始父母之间的差异。
要保持其他更改不变,请使用git stash show -p | patch --reverse
,如下所示:
$ git init
Initialized empty Git repository in /tmp/repo/.git/
$ echo Hello, world >messages
$ git add messages
$ git commit -am 'Initial commit'
[master (root-commit)]: created 1ff2478: "Initial commit"
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 messages
$ echo Hello again >>messages
$ git stash
$ git status
# On branch master
nothing to commit (working directory clean)
$ git stash apply
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: messages
#
no changes added to commit (use "git add" and/or "git commit -a")
$ echo Howdy all >>messages
$ git diff
diff --git a/messages b/messages
index a5c1966..eade523 100644
--- a/messages
+++ b/messages
@@ -1 +1,3 @@
Hello, world
+Hello again
+Howdy all
$ git stash show -p | patch --reverse
patching file messages
Hunk #1 succeeded at 1 with fuzz 1.
$ git diff
diff --git a/messages b/messages
index a5c1966..364fc91 100644
--- a/messages
+++ b/messages
@@ -1 +1,2 @@
Hello, world
+Howdy all
修改强>
对此的轻微改进是使用git apply
代替补丁:
git stash show -p | git apply --reverse
或者,您也可以使用git apply -R
作为git apply --reverse
的简写。
我最近发现这个非常方便......
答案 1 :(得分:71)
git stash
[save]
获取您的工作目录状态和索引状态,并将其存储起来,将索引和工作区设置为HEAD
版本。
git stash apply
带回了这些更改,因此git reset --hard
会再次删除它们。
git stash pop
会带回这些更改并删除最高级别的更改,因此在这种情况下git stash [save]
将返回上一个(pre-pop)状态。
答案 2 :(得分:55)
git checkout -f
将删除任何非提交更改。
答案 3 :(得分:18)
从git man page直接剪切n贴 它的措辞明确,甚至包括别名;
取消申请藏匿 在某些用例场景中,您可能希望应用隐藏的更改,执行某些操作,但随后取消应用最初来自存储的更改。 Git没有提供这样的stash unapply命令,但只需检索与存储关联的补丁并反向应用它就可以达到效果:
$ git stash show -p stash@{0} | git apply -R
同样,如果您没有指定存储,Git会采用最新的存储:
$ git stash show -p | git apply -R
您可能想要创建别名并有效地向Git添加stash-unapply命令。例如:
$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply
答案 4 :(得分:12)
这已经过了,但如果我正确地解释了问题,我找到了一个简单的解决方案,请注意,这是我自己的术语中的解释:
git stash [save]
将保存当前更改并将当前分支设置为“干净状态”
git stash list
提供了类似:stash@{0}: On develop: saved testing-stuff
git apply stash@{0}
会将当前分支设置为之前 stash [save]
git checkout .
将当前分支设置为 stash [save]
后的
保存在存储中的代码不会丢失,可以再次由git apply stash@{0}
找到。
Anywhay,这对我有用!
答案 5 :(得分:1)
除了@Greg Bacon的回答,如果二进制文件被添加到索引并且是使用
的一部分存储git stash show -p | git apply --reverse
可能导致
error: cannot apply binary patch to '<YOUR_NEW_FILE>' without full index line
error: <YOUR_NEW_FILE>: patch does not apply
添加--binary
可以解决问题,但遗憾的是还没有找到原因。
git stash show -p --binary | git apply --reverse
答案 6 :(得分:1)
如果您不小心轻按了藏书,您可以按照我共享的图像进行藏书。
答案 7 :(得分:1)
你可以应用两个命令
git reset .
// 反转文件
然后
git checkout .
// 反转更改
答案 8 :(得分:0)
除了上述答案之外,还添加了基于消息的git stash搜索,因为当保存新的存储时存储号码可以更改。 我写了几个bash函数:
apply(){
if [ "$1" ]; then
git stash apply `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"`
fi
}
remove(){
if [ "$1" ]; then
git stash show -p `git stash list | grep -oPm1 "(.*)(?=:.*:.*$1.*)"` | git apply -R
git status
fi
}
$ git stash save "my stash"
$ apply "my stash"
$ remove "my stash"
答案 9 :(得分:0)
如何反向应用隐藏?
除了别人所说的,最简单的方法是先做
git reset HEAD
然后签出所有本地更改
git checkout .
答案 10 :(得分:0)
我本人也遇到过类似的问题,我认为您需要做的只是git reset --hard
,您不会丢失更改或任何未跟踪的更改。
如果您阅读了git stash --help
中的文档,则表明apply是“像流行音乐,但不要从存储列表中删除该状态”,因此该状态仍然驻留在此处,您可以将其取回。
或者,如果您没有冲突,则可以在测试更改后再次git stash
。
如果您确实有冲突,请不要担心,git reset --hard
不会失去冲突,因为
“应用状态可能会因冲突而失败;在这种情况下,不会从存储列表中删除该状态。您需要手动解决冲突,然后手动调用git stash drop。”
答案 11 :(得分:0)
git stash show -p | git apply --reverse
警告,并非在所有情况下都这样:“ git apply -R
” (man)不能正确处理两次接触同一路径的补丁,已通过Git 2.30(Q1 2021)。
这与将路径从常规文件更改为符号链接(反之亦然)的补丁程序最相关。
请参见commit b0f266d的Jonathan Tan (jhowtan
)(2020年10月20日)。
(由Junio C Hamano -- gitster
--在commit c23cd78中合并,2020年11月2日)
apply
:当-R
时,还反转部分列表帮助者:Junio C Hamano
签名人:Jonathan Tan
将符号链接更改为文件的补丁分为两部分(在代码中,表示为“结构补丁”):首先,删除符号链接,其次,创建文件。
使用
-R
应用该补丁时,这些部分将颠倒过来,因此我们得到:(1)创建符号链接,然后(2)删除文件。这导致当一节“的文件的删除”被选中的一个问题,因为GIT中指出,所谓的文件不是文件,而是一个符号链接,从而产生“错误类型”的错误消息。
我们想要的是:(1)删除文件,然后(2)创建符号链接。
在代码中,这反映了在检查删除后从
previous_patch()
调用check_preimage()
的行为。
创建然后删除意味着删除后,previous_patch()
返回创建部分,触发模式冲突,导致“错误类型”错误消息。但缺失然后创建装置,当删除被选中,
previous_patch()
返回NULL
,所以删除模式被核对LSTAT,这是我们所希望的。补丁还可以通过其他方式包含2个引用同一文件的部分,例如,在7a07841c0b中(“
git-apply
:处理一次接触同一路径的补丁不止一次”, 2008-06-27,Git v1.6.0-rc0-merge)。 “git apply -R
” (man)以相同的方式失败,并且这种提交使这种情况成功。因此,在构建节列表时,如果传递
-R
,则以相反的顺序(通过添加到列表的前面而不是后面)来构建它们。