如何反向应用收藏?

我在我的私房钱里存了一小块。我已经使用git stash apply将它应用到我的工作副本。现在,我想通过反向应用补丁来撤销这些更改(有点像git revert所做的,但针对的是stash)。

有人知道怎么做吗?

在我的工作副本中有其他更改。我的具体情况很难描述,但您可以想象在存储库中有一些调试或实验代码。现在,它混合在我的工作副本与其他一些变化,我想看看效果与不从隐藏的变化。

目前stash似乎不支持这个功能,但git stash apply --reverse将是一个不错的功能。

278017 次浏览

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

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

git stash pop带回这些更改并删除顶部存储的更改,因此在这种情况下git stash [save]将返回到先前(预弹出)状态。

根据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来代替patch:

git stash show -p | git apply --reverse

或者,你也可以使用git apply -R作为git apply --reverse的简写。

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

这早就应该了,但如果我正确地解释这个问题,我已经找到了一个简单的解决方案,注意,这是我自己的术语解释:

git stash [save]将保存当前的更改,并将当前分支设置为“干净状态”

git stash list给出了类似stash@{0}: On develop: saved testing-stuff的值

git apply stash@{0}将当前分支设置为之前 stash [save]

git checkout .将当前分支设置为 stash [save]

保存在stash中的代码不会丢失,它可以通过git apply stash@{0}再次找到。

不管怎样,这对我很管用!

V1 git手册页有一个关于取消应用存储的参考。节选如下。

更新的V2 Git手册页不包括任何关于取消应用隐藏的引用,但下面仍然可以很好地工作

取消应用Stash 在某些用例场景中,您可能希望应用存储的更改,做一些工作,但随后取消应用最初来自存储的那些更改。Git没有提供这样的stash unapply命令,但是可以通过简单地检索与stash相关的补丁并反向应用它来实现此效果:

$ 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
git checkout -f

将删除任何非提交的更改。

除了@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
这是对上述答案的补充,但增加了基于消息的git存储的搜索,因为当保存新的存储时,存储编号可以改变。 我已经写了几个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"

如何反向应用收藏?

除了别人提到的,最简单的方法是先做

git reset HEAD

然后签出所有本地更改

git checkout .

你可以按照我分享的图像,以取消藏匿,如果你不小心点了藏匿。

.

我自己也有类似的问题,我认为你所需要做的就是git reset --hard,你不会丢失你的更改或任何未跟踪的更改。

如果你阅读git stash --help中的文档,它指出apply是“像pop,但不从stash列表中删除状态”。所以状态仍然存在,你可以把它拿回来。

或者,如果没有冲突,可以在测试更改后再次git stash

如果你确实有冲突,不要担心,git reset --hard不会失去它们,因为 “运用状态可能会因冲突而失败;在这种情况下,它不会从收藏列表中删除。你需要手动解决冲突,然后手动调用git stash drop。"

git stash show -p | git apply --reverse

警告,这不会在所有情况下:"git apply -R"(man)不能正确处理两次触及同一路径的补丁,这已在Git 2.30(2021年第一季度)中得到更正。

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

参见提交b0f266d (20 Oct 2020) by 谭恩美(jhowtan)
(由Junio C Hamano—gitster提交c23cd78中合并,02 Nov 2020)

apply:当-R时,也是反向的section列表

< p > 协助:Junio C Hamano
署名:Jonathan Tan

将符号链接更改为文件的补丁由两个部分编写(在代码中,表示为“struct patch"):首先,删除符号链接,其次,创建文件。

当使用-R应用该补丁时,部分颠倒,因此我们得到:(1)创建符号链接,然后(2)删除文件。

这将导致一个问题,当“删除文件”;section被检查,因为Git观察到所谓的文件不是文件而是符号链接,导致“错误的类型”。错误消息。

我们想要的是:(1)删除一个文件,然后(2)创建一个符号链接。

在代码中,这反映在检查删除时从check_preimage()调用previous_patch()时的行为中。
创建然后删除意味着当删除被选中时,previous_patch()返回创建部分,触发模式冲突,导致“错误类型”;错误消息。< / p >

但是先删除后创建意味着当检查删除时,previous_patch()返回NULL,因此根据lstat检查删除模式,这就是我们想要的。

还有其他方法可以让一个补丁包含两个引用同一个文件的部分,例如,在7 a07841c0b中(“git-apply: handle a patch that touch the same path more than once”,2008-06-27,Git v1.6.0-rc0——合并)。git apply -R"(man)以同样的方式失败,这个提交使这个案例成功。

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

您可以应用两条命令

git reset . //反向文件

然后

git checkout . //反向更改

对我来说,签出时我刚刚输入了错误的存储库名称。所以根本就没有遥控器可以拉。

因此,除了检查外壳之外,还要检查分支名称拼写,或者更好的是,复制并粘贴它,以排除它。