撤消git中未分段的更改的一部分


158

如何撤消git中未分段的更改的一部分,但其余部分保持未分段的状态?我发现的方法是:

git commit --interactive
# Choose the parts I want to delete
# Commit the changes
git stash
git rebase -i master # (I am an ancestor of master)
# Delete the line of the most recent commit
git stash apply

这行得通,但是如果有诸如git commit --interactive仅用于还原更改之类的东西,那就太好了。有更好的方法吗?

Answers:


264

您可以使用git checkout -p,使您可以从工作副本和索引之间的差异中选择单个块,以进行还原。同样,git add -p允许您选择要添加到索引的块,也git reset -p可以从索引和HEAD之间的差异中选择单个块以退出索引。

$ git checkout -p file/to/partially/revert
# or ...
$ git checkout -p .

如果您希望在恢复之前先为git存储库创建快照以保留这些更改,则可以执行以下操作:

$ git stash; git stash apply

如果经常使用,则可能要给它起别名:

[alias]
    checkpoint = !git stash; git stash apply

如果您使用良好的编辑器模式或插件,则还原单个块或行可能会更加容易,这可能会为直接选择要还原的行提供支持,-p有时使用起来可能有些笨拙。我使用Magit,这是一种Emacs模式,对使用Git很有帮助。在Magit中,您可以运行magit-status,找到要还原的更改的差异,选择要还原的行(或者如果想一次还原一个粗体,只需将光标放在要还原的粗体上,而不是一次一行),然后按k还原这些特定的行。如果您使用Emacs,我强烈建议Magit。


我认为这与我最初提出的解决方案一样复杂,但是我认为我原来的解决方案具有将删除的行保存30天的好处,因为它们已提交。我在想,也许写一个shell脚本会更好。
asmeurer 2010年

1
抱歉,我刚刚意识到git checkout也有一个-p标志,它恰好满足您在单个命令中的要求。为先前的复杂步骤道歉;您可以使用git checkout -p。就保存东西而言,在做可能具有破坏性的事情之前,我经常做一个git stash; git stash apply(或创建一个别名,以git checkpoint某种方式记录)树中的当前树,以便在出现问题时恢复原状。
Brian Campbell

解决了,这就是解决方案!至于别名,我在想类似的东西 git commit -a -m "Backup Commit" --edit; git reset HEAD^ 会更好,因为这样就不会弄脏我的存储状态,这可能是我用于其他用途的状态。然后,只要您拥有SHA1,就可以在接下来的30天内挑选它。使用--edit,您可以将信息添加到提交消息中,以帮助您稍后在需要时找到SHA1。另一方面,这会使git reflog变脏,所以我想这是根据您的操作进行的折衷。
asmeurer 2010年

检查点别名对我不起作用:仅执行第一个命令,而不执行第二个命令。真可悲,因为我本来会喜欢的。我正在使用git版本1.7.10.4。
法比恩(Fabien)2015年

有没有一种方法可以git checkout -p不将补丁应用到索引,而仅将其暂存?
Geremia

28
git diff > patchfile

然后编辑补丁文件并删除您不想撤消的部分,然后:

patch -R < patchfile

6
但是,此答案的简单性和易用性尤其令人赞叹。+1
2015年

生成patchfile的文件在vim中看起来很棒,并且确实有帮助!
Bily 2016年

完善。可以确认它也可以在Windows下与Cygwin和Ubuntu bash for Windows一起使用。
Checo R

1
请注意,您也可以使用git apply -R代替patch(只是停留在git的范围内,或在patch不可用的
同类

patch: **** malformed patch at line 41: @@ -428,9 +443,9 @@ you should place your code here."
HappyFace


1

怎么样

  1. 通过索引的更改撤消受影响的文件
  2. 用于git add -p仅将所需的更改添加回索引。

1

当我运行“ git status”时,它说:

$ git status
# On branch fr/fr.002
# 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:   makefile
#
no changes added to commit (use "git add" and/or "git commit -a")
$

因此,要取消未进行的编辑,它会告诉我运行:

git checkout -- makefile

3
我认为他想知道如何还原单个块,而不是一次还原整个文件。当然,如果您只需要撤消文件中的所有更改,这就是解决方案。
布莱恩·坎贝尔,2010年

是的-我怀疑你是正确的。正如您所说,'git checkout -p'和'git add -p'选项似乎很需要。
乔纳森·莱夫勒

1

Brian Campbell的答案由于未知原因而使我的git版本1.9.2.msysgit.0崩溃,所以我的方法是暂存要保留的块,丢弃工作副本中的更改,然后取消暂存。

$ git add -p
   ... select the hunks to keep
$ git checkout -- .
$ git reset HEAD .

1
也有git stash -p。你可以做的git stash -p; git reset --hard; git stash pop。这实际上与您所做的相同,只是您不必编写提交消息。
asmeurer

@asmeurer干杯。我的不需要提交消息,但是使用存储比使用索引更有意义。
G-Wiz 2015年

0

您可以这样做git checkout并为其指定要撤消的零件的名称。

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.