完整故事: 我提交了一堆文件。几次提交后,有人(JACK!!!)将一个文件复制到他的存储库,并提交了几个文件,覆盖了我所做的一些更改。我想撤销那个被破坏的文件,或者更好地说,去撤销该文件中的两个更改。由于该文件已被拉取和推送,这将是一个单独的撤销提交。
通过添加--no-commit
选项,您可以在不创建新提交的情况下还原提交。这将使所有被还原的文件留在暂存区。
接下来,我会执行混合重置(重置的默认值)以取消暂存文件,并添加我真正想要的更改。然后,提交(如果您想要多个提交,则可以添加和提交更多文件),最后,检出当前目录以清除由revert
导致的任何未提交和未暂存的修改。以下是一个示例工作流程:
git revert <sha-of-bad-commit> --no-commit
git reset # This gets them out of the staging area
# ...edit bad file to look like it should, if necessary
git add <bad-file>
git commit
git checkout . # This wipes all the undesired reverts still hanging around in the working copy
git add -p
来启动交互式会话,以允许您选择性地添加文件的块,而不是整个文件。 (还有 git reset -p
用于有选择地取消暂存更改。这很好知道,但可能不是您在此情况下想要的。) - Stéphan Kochenrevert
、reset
、stash -p
(储藏“我不想实际执行的取消操作”)、添加其余内容、commit
。 - Cyril CHAPONgit reset
是 git reset --mixed HEAD
的简写。因此,这个答案显示的 git reset
实际上是一个 --mixed
重置,而不是所述的--soft
重置,因为根据 git help reset
,混合重置是默认的。也就是说,混合重置既重置了当前分支指向的提交(在本例中表示为 HEAD
所代表的提交),同时还将文件从索引/暂存区中删除(即使用 HEAD
现在指向的任何快照更新暂存区,Pro Git,第217页)。我确认 git reset --soft
不会取消暂存的文件。如果有人能够确认,我将编辑帖子。 - Life5ign您可以使用 checkout
命令交互式地应用文件的旧版本。
例如,如果您知道将添加回来的代码被删除的 COMMIT
,则可以运行以下命令:
git checkout -p COMMIT^ -- FILE_TO_REVERT
Git会提示您添加当前文件版本中缺少的补丁。您可以使用e
命令在应用更改之前创建更改的补丁。
git checkout -p path/to/file
。 - falstaff您可以使用 git checkout
手动检出想要还原的文件的旧版本。例如,如果您想将 my-important-file
还原为版本 abc123
中的版本,则可以执行以下操作:
git checkout abc123 -- my-important-file
现在,您已经回到了my-important-file
的旧内容,如果需要,甚至可以编辑它们,然后像往常一样提交以撤销他所做的更改。如果只想还原他部分提交的更改,请使用git add -p
从要提交的补丁中选择一些碎片。
git checkout -p
中。 - Léo Lam我在Git邮件列表上找到了一种方法:
git show <commit> -- <path> | git apply --reverse
来源:http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html#a6064406
如果补丁无法应用,该命令会失败(不会造成任何更改),但使用--3way
选项,则会出现冲突,您可以手动解决这些冲突(在这种情况下,Casey的答案可能更实用):
git show <commit> -- <path> | git apply --reverse --3way
您还可以使用此方法来部分还原多个提交,例如:
git log -S<string> --patch | git apply --reverse
为了还原任何提交中符合 <string>
更改的文件。这正是我在使用场景中所需的(几个独立的提交引入了类似的更改到不同的文件,以及对其他文件进行了不相关的更改,我不想还原)。
如果您在~/.gitconfig
中设置了diff.noprefix=true
,则需要将-p0
添加到git apply
命令中,例如:
git show <commit> -- <path> | git apply -p0 --reverse
git show ... > foo.txt
(2) 编辑 foo.txt
以删除我不想撤销的差异 (3) git apply --reverse foo.txt
来撤销仍在 foo.txt
中列出的差异。 - cxw<path>
中传递了一个模式,这也可以正常工作。太棒了! - lnogueir
--3way
会导致合并冲突而不是无法应用补丁。 - ntc2