如何反向应用隐藏?


233

我的git存放区中保存了一个小补丁。我已使用将它应用于我的工作副本git stash apply。现在,我想通过反向应用补丁来撤消那些更改(有点像是git revert在隐藏的情况下那样)。

有谁知道如何做到这一点?

说明:我的工作副本中还有其他更改。我的特殊情况很难描述,但是您可以想象一些隐藏的调试或实验代码。现在,它已与其他更改混合在我的工作副本中,我希望看到隐藏与不更改的效果。

stash当前似乎不支持此功能,但是a git stash apply --reverse会是一个不错的功能。


1
不能仅通过在当前版本和先前版本之间进行区分来创建反向补丁吗?然后申请那个?
ralphtheninja

除了已应用的存储之外,工作树中是否还有其他更改?
格雷格·培根,2009年

在这里添加……应该是一个常见问题,而不是一个问题…… stackoverflow.com
Don Thomas Boyle

Answers:


188

根据git-stash联机帮助页,“存储被表示为提交,其树记录了工作目录的状态,其第一个父级是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

我最近发现这真的很方便...


2
很好,谢谢。似乎这可能是隐藏的一个不错的功能。
Pat Notz 09年

5
是的,这git apply -R是一种改进,至少对我来说,在我的git bash的Windows框上,因为patch --reverse在定位要修补的文件时遇到了问题(没有真正的线索说明替代方法为何有效)。+1和很好的解释
hakre

--index像这样添加会更好吗git stash show -p | git apply --reverse --index?因为您不再需要在索引中添加已还原回的更改。
theUnknown777'2015-4-13

3
@Greg Bacon,嘿,我尝试浏览您概述的脚本,但是当我运行git stash show -p | git apply -R -v以下消息时,补丁失败Checking patch messages... error: while searching for: Hello, world Hello again error: patch failed: messages:1。您知道什么地方可能出问题吗?
Max Koretskyi 2015年

5
我收到错误消息:补丁失败:/src/filename.java:46 错误:src / filename.java补丁不适用
Tim Boland

83

git stash[save]获取您的工作目录状态和索引状态,并将其存储起来,将索引和工作区域设置为HEAD版本。

git stash apply带回这些更改,因此git reset --hard将其再次删除。

git stash pop带回这些更改并删除最隐蔽的更改,因此git stash [save]在这种情况下将返回到先前的状态。



22

V1 git手册页上有关于取消应用隐藏的参考。摘录如下。

较新的V2 git手册页未包含取消应用隐藏的任何引用,但以下内容仍能正常工作

取消应用藏匿 在您可能希望应用藏匿变化一些用例场景,做了一些工作,但后来不应用最初来源于藏匿这些变化。Git没有提供这样的隐藏未应用命令,但是可以通过简单地检索与隐藏相关联的补丁并将其反向应用来实现此效果:

$ git stash show -p stash@{0} | git apply -R

同样,如果您不指定存储,Git会假定使用最新存储:

$ git stash show -p | git apply -R

您可能想要创建一个别名,并有效地将stash-unapply命令添加到您的Git。例如:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply

1
无论出于何种原因,这是很有帮助的部分,你链接的“非应用藏匿”从第二个版本中删除-最新版本,现在是2.1.146,2019-04-15-这本书的V2-的Git工具-积攒和清洁。可能是因为作者认为有一种更好的方法可以做到这一点,而我似乎找不到。
Nad Alaba

@NadAlaba感谢您的注意,已经更新了答案以记下v1和v2之间的区别...奇怪的git作者删除了关于不应用隐藏的部分
Choco Smith,

13

这是很长的期限,但是,如果我正确地解释了问题,我已经找到了一个简单的解决方案,请注意,这是用我自己的术语进行的解释:

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,这对我有用!


可以肯定的是,我先申请了git stash apply --reverse,然后又回到了git stash apply stash@{x}您提到的位置。工作没有问题。
卡洛斯·加西亚

3

如何反向应用隐藏?

除了别人所说的,最简单的方法是先做

git reset HEAD

然后签出所有本地更改

git checkout . 

到目前为止,这是最简单的方法,只要您完全没有要保存的本地工作即可。如果您对分支应用了错误的存储或遇到了您不想解决的合并冲突,这是通过将工作集完全还原为分支的最新提交来撤消它的快捷简便方法。
Shadoninja

2

除了@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

0

这是上述答案的补充,但根据消息增加了对git stash的搜索,因为保存新的stash时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. 申请命名 $ apply "my stash"
  3. 删除命名的存储 $ remove "my stash"

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.