是否可以在多文件提交中仅恢复单个文件或文件中的某些更改?
完整故事 我提交了一堆文件。经过多次提交后,一个无名的人(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
您可以使用
checkout
命令以交互方式应用旧版本的文件。
例如,如果您知道要添加回来的代码被删除的
COMMIT
,则可以运行以下命令:
git checkout -p COMMIT^ -- FILE_TO_REVERT
Git 会提示您添加回当前版本文件中缺少的块。您可以使用
e
创建更改的补丁,然后再将其应用回来。
您可以使用
git checkout
手动查看要恢复的文件中旧的、好的内容。例如,如果您想将 my-important-file
恢复到 abc123
版本中的版本,您可以这样做
git checkout abc123 -- my-important-file
现在您已经恢复了
my-important-file
的旧内容,如果您愿意,甚至可以编辑它们,并像往常一样进行提交,这将恢复他所做的更改。如果您只想恢复他提交的某些部分,请使用 git add -p
从您正在提交的补丁中仅选择几个部分。
我在 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>
匹配的更改的文件。这正是我在用例中所需要的(一些单独的提交对不同文件引入了类似的更改,以及以我不想恢复的不相关方式更改了其他文件)。如果您在
diff.noprefix=true
中设置了
~/.gitconfig
,那么您需要将
-p0
添加到
git apply
命令,例如
git show <commit> -- <path> | git apply -p0 --reverse
git revert --no-commit
选项。我调整了自动生成的恢复提交消息,以澄清哪些更改未恢复。解决方案
$ git revert COMMIT
# Revert the revert. This means our files will be in the same state
# as they were before the revert, which is what we want for
# the one file we didn't want to change.
$ git revert HEAD --no-commit
# Since we want to revert most of the files, unstage them so we can
# remove their changes. Don't unstage the file you want to remain
# untouched in the end
$ git reset file1 file2
$ git checkout file1 file2
# Make sure the one file we don't want to change is still staged
$ git status
# Amend the autogenerated revert commit to remove
# the file we didn't want to touch
$ git commit --amend -C HEAD
# View the revert commit and make sure the file we didn't want
# to touch isn't there!
$ git show
# Done!
$ git push
为什么有人想要这样做?