我有一些提交是HEAD
之前的几次提交。在提交时,我发现了一些我没有注意到的变化。浏览我的git log
,我发现了这些不必要的变化。在Google上搜索'undo changes for an arbitrary commit'
,会在撤消整个提交并删除索引中的更改时返回许多结果。但是,在这个任意提交中删除这些更改的方法是什么?
答案 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中没有对它的引用时,将在下一个垃圾回收周期中删除提交对象。