撤销 Git 中的特定文件

23

我想撤销某个提交,但只想针对某些文件进行操作。(不是检出操作;是撤销操作。 如果你不了解区别,请继续阅读。)

我尝试过这样做:

git revert --no-commit abcdef123456 -- my/path/to/revert

而我遇到了这个错误

fatal: ambiguous argument 'my/path/to/revert': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
但这正是我所做的!(是的,`my/path/to/revert` 在我的工作树中。)
我认为我的工作理论是不可能只还原一些文件,并且Git的错误信息是误导性的。
(Git 1.7.9.5)
这不是关于在Git中将单个文件还原到先前版本的重复问题。
  • 那个问题(尽管标题如此)涉及到git-checkout。检出将文件恢复到以前的版本,删除该点之后的所有提交。
  • 我的问题涉及到git-revert。还原撤销特定提交中进行的更改,而不影响可能在其后进行的其他提交。 它应用(仅)该提交的相反操作。

1
你能解释一下为什么要使用“还原”而不是使用“检出”吗?据我所知,适当文件的检出后跟提交就相当于还原。 - Chris
2
我认为你不能还原单个文件,你在哪里读到的,是在文档中吗?但是你可以使用反向补丁,与git apply一起使用:git show <commit> -- <path> | git apply -R,在这里找到:http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html - steabert
1
我认为这可能是这篇帖子的重复:https://dev59.com/HHE85IYBdhLWcg3whT9r - Chris Maes
1
@ChrisMaes,看一下我对checkoutrevert之间区别的解释。 - Paul Draper
1
@PaulDraper,有趣的是,我显然多年来一直误解了revert。所以如果您有提交A(较旧),BC ,您想要反转来自A的更改,同时保留来自更新提交BC的更改。 - Chris
@steabert,在我的情况下,这是一个合理的选择。 - Paul Draper
4个回答

33

我认为Git不允许您指定要还原的特定文件。我能想到的最好的方法是:

git revert --no-commit <commit hash> # Revert, don't commit it yet
git reset # Unstage everything
git add yourFilesToRevert # Add the file to revert
git commit -m "commit message"
git reset --hard # Undo changes from the part of the revert that we didn't commit

顺便说一句,将其封装在一个shell脚本中应该很容易,如果你发现自己经常这样做,那么这将使它更加容易。 - vcsjones
或者,如果您想保留大多数文件并仅撤消一些文件,您可以使用git-revert,在不想还原的文件上使用git reset --hard,然后提交。 - vcsjones

11

当你能列出一个简短的清单时,使用以下简短序列:

git revert that_commit           # do the whole revert
git reset --hard HEAD^           # in what turns out to have been a throwaway commit
git checkout HEAD@{1} -- one/folder   # and just take what you want of the results

9

vcsjones的回答可能是最好的方法,因为还原使用了三方合并机制。然而,在许多情况下,您可以将补丁git apply -R(反向)应用到相关文件中,例如:

git show <rev> -- path/to/file | git apply -R

(或 git diff——任何允许你将结果限制为特定文件的差异生成器,但对于非合并提交,git show 是显而易见的首选;对于合并提交,您需要指定正确的父提交)。


这绝对是最简单的方法。 - Paul Draper
这种方法不够健壮,不如其他答案:error: patch failed: ...\n error: ...: patch does not apply - nyanpasu64
1
@jimbo1qaz:是的,这就是为什么我说vcsjones的答案通常最好(尽管jthill的答案同样出色,而且可能更容易——在我写上面的内容时它还不存在)。 - torek

0

Git 通过提交来工作。您无法 git 撤销文件。即使提交中只有一个文件,您仍然会撤销该提交。解决方案是模拟 git 撤销以获取新提交所需的内容。我没有看到这里展示的最清洁和最安全的方法 - 在另一个分支上撤销并检出所需内容。与 git 应用程序不同,如果存在合并冲突,则不会中断,而撤消/重置确实只适用于撤消一个提交。

git checkout -b tmpbranch
git revert commitref                   # complete commit, follow with more reverts as needed
git checkout mainbranch
git checkout tmpbranch -- file/i/need  # while on mainbranch and to index by default
git commit -m "this is a new commit message"
git branch -d tmpbranch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接