如何撤消任意提交中的更改?

时间:2017-07-05 22:29:59

标签: git

我有一些提交是HEAD之前的几次提交。在提交时,我发现了一些我没有注意到的变化。浏览我的git log,我发现了这些不必要的变化。在Google上搜索'undo changes for an arbitrary commit',会在撤消整个提交并删除索引中的更改时返回许多结果。但是,在这个任意提交中删除这些更改的方法是什么?

1 个答案:

答案 0 :(得分:2)

首先,确保您的工作树干净。 git status可以帮助您找到这个。它不应报告任何等待提交的更改。如果有更改,您可以提交它们(如果需要,可以在临时分支中)或stash它们。

确保工作树干净后,在当前提交中创建一个分支但不检查它:

$ git branch backup

实际上并不需要,您可以使用reflog,但这种方式更容易(也更明显)。 backup只是我为分支选择的名称,它没有什么特别之处;唯一的限制是它必须不存在。

假设您想要修改过去的第三次提交,请运行:

$ git rebase --interactive HEAD~4

Git在默认编辑器中打开一个临时文件,其内容如下所示:

pick 7f0c5e794 the commit you want to change
pick 9f96dcae9 commit message #2
pick 02ed04062 commit message #3
pick beac35780 the most recent commit

这是rebase的计划。当然,它包含哈希和你最后三次提交的主题。它们是按时间顺序排列的最后四次提交(因为HEAD~4)(较早的一次)。

编辑要修改的提交行(第一行);将pick更改为edit,然后保存文件并退出编辑器。

当你退出编辑器时,Git开始重新定位。它会检出提交HEAD~3并退出,允许您按照计划中的要求edit提交。

进行所需的更改,暂存它们然后运行git commit --amend以修改提交(您的目标)。执行更改的最佳方法是运行:

$ git reset --mixed HEAD~1

这使得repo处于您要修改的提交之前的状态,在工作树中更改了文件,并且没有添加到索引中。仅将您需要和提交的文件添加到索引中(不带 --amend)。这是您想要的"编辑过的" 1 提交。

编辑提交后,您仍然可以在工作树中进行未提交的更改。您必须提交它们(创建一个在原始历史记录中不存在的新提交),存储它们(并在完成rebase后应用它们)或完全丢弃它们(git reset --hard这样做; make确保在运行此命令之前你真的不需要它们。)

以这种或那种方式解决未提交更改的问题后,运行:

$ git rebase --continue

Git继续坚持下去;它正如你在计划中告诉它的那样处理其他提交。我们的计划为其他提交提及pick,这意味着Git只会应用您不想修改的这些提交的更改。

如果一切顺利,在此命令完成后,您将拥有一个看起来像您想要的新历史记录行。如果它看起来不像您想要的那样可以运行

$ git reset --hard backup

回到你开始的地方并重新开始。

如果rebase没有成功完成(可能会遇到冲突),您可以通过运行git rebase --abort来中止它。 Git将撤消所有更改,您将成为开始的地方(在backup分支指向的提交上)。

或者,您可以解决冲突,提交和运行git rebase --continue,直到rebase完成。

以这种或那种方式结束rebase并且您对结果感到满意或者已经退出更改过去提交的想法,运行git branch -D backup以删除备份分支。

1 Git提交是不可变的。无法编辑提交。 "编辑"实际上,提交会创建一个用于代替旧提交的新提交。当然,新提交的哈希值与原始哈希值不同。

旧提交仍然存在于存储库中,可通过其哈希或使用分支访问。当没有可用于访问它的分支并且reflog中没有对它的引用时,将在下一个垃圾回收周期中删除提交对象。