我很久以前就提交了一个糟糕的提交,我想将它完全从git历史中删除,好像它从未发生过一样。我知道提交ID让我们说1f020。我已经尝试了git rebase并将其删除,但是在重新定位时存在很多冲突,这是不可能的。该提交是一个简单的1行代码更改,并推送一些与项目无关的文件。 所以我想写一行代码更改并提交它,然后替换以某种方式用很久以前的那个替换这个新的提交。
答案 0 :(得分:6)
如果违规提交在私有存储库中,那么您想要做的事情并不是什么大问题。重写已发布的git历史记录会让您的协作者感到恼火,因此请确保删除此行是值得的。
git-rebase
documentation有一段有用的段落。
git rebase [...] [<--onto newbase>] [<upstream>] [<branch>]
也可以使用rebase删除一系列提交。如果我们有以下情况:
E---F---G---H---I---J topicA
然后命令
git rebase --onto topicA~5 topicA~3 topicA
将导致删除提交 F 和 G :
E---H'---I'---J' topicA
如果 F 和 G 以某种方式存在缺陷,或者不应该成为
topicA
的一部分,则此功能非常有用。请注意,--onto
和上游参数的参数可以是任何有效的commit-ish。
假设您的历史记录是线性的并且违规提交位于您的主分支中,您可以通过运行
来调整上述示例git rebase --onto 1f020~ 1f020 master
对于更多的情况,请使用交互式rebase。您可能会发现按下an example that merges two commits会很有帮助,但不要使用s
标记提交,而是删除整行以从历史记录中删除提交。
答案 1 :(得分:5)
这有点复杂,但无论如何,这是如何进行的:
分离头并移动以提交 AFTER 该错误提交。使用git log查找1f020之后的下一次提交。
git checkout <SHA1-for-commit-just-after-bad-commit-1f020>
移动HEAD只提交 BEFORE 提交错误,但保留索引和工作树
git reset --soft <SHA1-for-just-previous-to-bad-commit-1f020>
重做提交只是 AFTER 错误提交重新使用提交消息,但现在提交只是 BEFORE 那个错误的提交。因此,删除那个错误的提交
git commit -C <SHA1-for-commit-just-after-bad-commit-1f020>
重新应用提交中的所有内容,只需将 AFTER 提交到此新地点
git rebase --onto HEAD <SHA1-for-commit-just-after-bad-commit-1f020> master
答案 2 :(得分:1)
你永远不应该从git的历史中删除提交。你以后会遇到问题。
但是如果你知道自己在做什么,你可以在本地回溯你的历史记录,用当前的提交替换那个提交,然后再次重播所有提交 - 然后对你的存储库进行强制推送。
但我强烈建议不要这样做。只是做一个新的提交,并认为历史上有一个错误的提交。
答案 3 :(得分:1)
所以,你想要的是:
从历史记录中删除错误提交,
不必重做已删除提交后出现的所有合并。即从已删除的提交中下降的每个提交都应保持原样,只需最低限度地更改为不包括从历史记录中删除的更改。
基于git rebase --onto
和git rebase -i
的解决方案在第二点失败,因为它们需要重做以后发生的所有合并。但是,理论上可以简单地重新创建所有这些其他提交,就好像违规提交从未发生过一样,前提是错误提交足够小,从而将其从后继者本身恢复会产生冲突。
正如迈克尔和其他人所指出的那样,这样做是非常不可取的。这也是一项重大任务,几乎肯定不值得付出努力。但是,对于教育价值,这里是一个实现目标的综合解决方案的概述:
备份存储库。
使用git rev-list
生成一个以错误提交开头的提交列表,并指向可以从中提交提交的所有分支头。
初始化一个空地图,将旧提交映射到新提交。
对于列表中的每个提交,请执行以下操作:
git write-tree
git commit-tree
创建一个新提交,其中包含新树,旧提交消息以及使用上述地图从旧父母翻译的父母(如果某些父母不在地图中,只需使用旧父母)< / LI>
浏览标记和标记对象,并重新创建它们以指向新提交,并查看地图。
通过分支机构并致电git update-ref
,将他们指向新的提交,咨询地图。
如果提交引入的单行更改(以及不必要的文件)与以后提交的更改不冲突,则此过程可以完全自动化,并且不要求您手动重做以后提交的所有合并和冲突。
缺点是它仍然需要重写所有后续提交,如果它们已在别处共享则使它们无效,并使提交消息中的提交引用无效,例如由git revert
生成的提交。