【问题标题】:Reverting specific commits from git从 git 恢复特定的提交
【发布时间】:2023-04-03 13:10:01
【问题描述】:

我有一个 git 树,里面有很多提交和很多文件。现在,我想恢复仅涉及文件的特定提交。解释一下:

> git init
Initialized empty Git repository in /home/psankar/specific/.git/
> echo "File a" > a
> git add a ; git commit -m "File a"
[master (root-commit) 5267c21] File a
 1 file changed, 1 insertion(+)
 create mode 100644 a
> echo "File b" > b
> git add b; git commit -m "File b"
[master 7b560ae] File b
 1 file changed, 1 insertion(+)
 create mode 100644 b
> echo "File c" > c
> git add c; git commit -m "File c"
[master fd6c132] File c
 1 file changed, 1 insertion(+)
 create mode 100644 c
> echo "b and c modified" > b ; cp b c
> git commit -a -m "b and c modified"
[master 1d8b062] b and c modified
 2 files changed, 2 insertions(+), 2 deletions(-)
> echo "a modified" > a
> git commit -a -m "a modified"
[master 5b7e0cd] a modified
 1 file changed, 1 insertion(+), 1 deletion(-)
> echo "c modified" > c
> git commit -a -m "c modified"
[master b49eb8e] c modified
 1 file changed, 1 insertion(+), 1 deletion(-)
> git log --pretty=oneline c
> git log --pretty=oneline c | cat
b49eb8e03af331bddf90342af7d076f831282bc9 c modified
1d8b062748f23d5b75a77f120930af6610b8ff98 b and c modified
fd6c13282ae887598d39bcd894c050878c53ccf1 File c

现在我只想还原两个提交 b49eb81d8b06 而不将更改还原为 a。 IOW 仅还原文件中的提交(不还原不同文件中的其他中间提交(可能有数千个))这怎么可能?

【问题讨论】:

  • 使用git rebase -i <commithash>
  • git show --stat -p COMMITID 将为您提供快速的行数统计信息和显示该提交执行的确切更改的补丁。有了这些信息,您就可以决定是否要git revert COMMITID。使用-n 将允许您在提交之前进行评估,甚至可以评估git revert --abort

标签: git github git-rebase revert git-revert


【解决方案1】:

您可以将git revert--no-commit 选项一起使用。在您的示例中:

$ git revert --no-commit b49eb8e 1d8b062
# Files that were modified in those 2 commits will be changed in your working directory
# If any of those 2 commits had changed the file 'a' then you could discard the revert for it:
$ git checkout a
$ git commit -a -m "Revert commits b49eb8e and 1d8b062"

--no-commit 选项不会自动提交,它允许您编辑和添加自己的提交消息

请注意,与 git resetgit revert 不同,所有恢复的提交仍将存在于提交历史记录中

【讨论】:

  • +1 表示--no-commit 开关并提到revert 必须按反向 顺序完成
  • 我在我的机器上尝试过同样的方法,然后在这里询问,然后它没有工作。现在尝试在新的 git 设置(v 1.8)中运行良好。可能这是我拥有的旧 git (1.6) 中的一个错误。谢谢。
【解决方案2】:

这里有两种情况:

  1. 当您已经将 git 树推送到某个地方并且您不想更改历史记录时。在这种情况下,您将需要一个新的提交来表达您在恢复之前的提交时所做的更改。您应该使用@mamapitufo 的答案。

  2. 如果您从未推送过更改所在的分支,则可以更改历史记录。在这种情况下,您可以完全删除不需要的提交。这将整理历史,并意味着您不会向您的同事或公众推错路。

在第二种情况下,您应该使用git rebase -i。查找要更改的任何历史记录之前的提交。这可能是提交的哈希,或者分支或标签的名称。例如,你可以这样做

git rebase -i 23def8231

或者,如果您从分支 origin/dev_branch 开始并完成了包含要在名为 dev_branch 的分支上删除的位的工作,您可以这样做

git rebase -i origin/dev_branch

现在,您将被发送到一个编辑器窗口,您可以在其中看到您正在变基的所有提交的列表。这可能是vim - 如果您通常不在终端中进行编辑,则可以将其设置为默认值。如果是这种情况,您可能需要一份 vim 快速入门指南和开放的心态。

现在,最简单的做法是删除提交。您可以通过删除该行或添加一个# 来执行此操作,该# 表示该行开头的注释。 (文件里已经有一些cmets,给大家解释一下。忽略这些或删除它们都没有效果。)

完成后,保存文件并退出编辑器。变基是这样发生的:git 回到你命名的提交。它遍历您保存的列表并重播该列表中的每个提交。然后它使该过程的结果成为您最初所在分支的新版本。

要记住的重要事项:

  • 如果丢失或删除了太多行,可以通过删除文件中的每个提交行并保存来取消 rebase。 rebase 过程将在没有任何改变的情况下结束。
  • 可能会产生冲突。例如,如果您删除编辑文件的提交,并保留在稍后编辑相同位置的提交中。稍后的提交现在将无法正确应用,您必须手动或在合并工具中进行编辑才能获得所需的版本。

您还可以在git rebase -i 中进行许多其他操作。例如更改提交的顺序,将几个压缩为一个,在提交之间添加额外的更改,或者更改消息。这是非常有用的。经典用例是在将本地分支推送回其他人会查看您的更改的地方之前清理本地分支。

【讨论】:

    猜你喜欢
    • 2019-01-12
    • 2017-05-16
    • 2011-04-08
    • 2020-05-03
    • 2011-08-11
    • 2016-06-23
    • 1970-01-01
    • 2016-04-20
    • 1970-01-01
    相关资源
    最近更新 更多