如何反向申请藏匿?

时间:2009-06-19 21:34:59

标签: git git-stash

我在git stash中保存了一个小补丁。我已使用git stash apply将其应用于我的工作副本。现在,我想通过反向应用修补程序来回退这些更改(有点像git revert会对存储进行操作。)

有谁知道怎么做?

澄清:我的工作副本中还有其他更改。我的特殊情况很难描述,但您可以想象一些存储中的调试或实验代码。现在它在我的工作副本中混合了一些其他的变化,我希望看到效果有和没有来自藏匿处的变化。

它当前看起来不像stash支持,但git stash apply --reverse将是一个不错的功能。

12 个答案:

答案 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
}
  1. 使用名称(消息)$ git stash save "my stash"
  2. 创建存储
  3. $ apply "my stash"
  4. 命名
  5. 删除已命名的藏匿$ 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 -Rman不能正确处理两次接触同一路径的补丁,已通过Git 2.30(Q1 2021)。

这与将路径从常规文件更改为符号链接(反之亦然)的补丁程序最相关。

请参见commit b0f266dJonathan 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 -Rman以相同的方式失败,并且这种提交使这种情况成功。

因此,在构建节列表时,如果传递-R,则以相反的顺序(通过添加到列表的前面而不是后面)来构建它们。