如何在git日志中删除特定的提交记录

82

我只想在git日志中删除特定的提交记录,不应影响到上面的提交记录。


从本地副本还是远程获取? - Roman Marusyk
5个回答

61

它不应该受到上述提交的影响。

如果你从一个分支中间或者除了分支的HEAD以外的任何地方删除一个提交,你将会重写该分支的历史记录。因为你需要使用的工具,即git rebase --interactivegit filter-branch,需要重新提交在被删除提交之后的所有内容。这通常对于公共共享分支来说是不可取的,因为它迫使每个人采取相当苛刻的措施来跟上这种变化。

相反,对于你来说更加安全的方法是使用git revert

git revert <SHA-1 of commit to delete>

这将在你的分支顶部添加一个新的提交,有效地撤销了中间提交所做的一切。

顺便说一下,如果你真的想删除那个提交,我建议进行交互式变基。


57
如果提交记录还没有推送到远程服务器,你可以使用 git rebase 来修改 Git 历史记录。你可以这样做:
git rebase -i commit-hash^

这将显示一系列的提交记录,第一行应该是您要删除的提交记录。从您所编辑的文件中删除该行,保存并关闭。

如果在此之前已将更改推送到远程服务器,请注意,刚刚删除的提交记录之后的所有提交记录都会基于刚刚从历史记录中删除的提交记录进行重写。出于这个特定的原因,所有提交记录都会更改,因为您的历史记录刚刚分叉了。因此,如果您尝试推送,它不会是快进式的,而需要强制推送。

因此,如果您不熟悉 git rebase,我建议在修改历史记录的分支上保留一个指针指向原来的分支,以防出现问题。

此外,如果该特定提交记录在多个分支之间共享,则使一个分支的历史记录发生变化将导致多个问题,因为您将无法轻松地将一个旧历史记录的分支合并到新历史记录的分支中。它将复制许多提交记录,而您在一个分支中删除的提交记录将不会在其他分支中被删除。

请将修改 git 历史记录视为时间旅行。对某个时点的任何更改都会创建一个新的平行宇宙。过去的一切都会受到您在过去所做更改的影响。


31
你可以使用git cherry-pick来完成这个任务。假设你的 git log 看起来像这样,现在你想从你的分支中删除第二次提交。

你可以使用git cherry-pick来完成这个任务。假设你的 git log 看起来像这样,现在你想从你的分支中删除第二次提交。

COMMITS    MESSAGES
abcd123    4th commit message
xyze456    3rd commit message
98y65r4    2nd commit message wants to be removed.
bl8976t    1st commit message

步骤1 - 检查最后一个正确的提交:git checkout bl8976t

步骤2 - 从该提交创建一个新分支:git checkout -b commit-remove

步骤3 - 挑选您想要保留的提交:git cherry-pick xyze456git cherry-pick abcd123

步骤4 - 检出您的原始分支:git checkout master

步骤5 - 将原始分支重置为最后可用的提交:git reset --hard bl8976t

步骤6 - 将新分支合并到原始分支上:git merge commit-remove

步骤7 - 检查原始分支是否具有正确的提交:git log

步骤8 - 将原始分支推送到远程仓库:git push --force origin 原始分支名称

完成了。

请注意,这可能会对其他在同一仓库/分支上工作的用户产生不利影响。


1
在我的情况下或现在(git 最新版本)的第 8 步,我使用命令 git push --force origin latest sha commit from merge:original-branch-name - Yogi Arif Widodo
与rebase和revert相比,这是一种更好的方法。 - Pawara Siriwardhane
1
@PawaraSiriwardhane,这样做为什么更好?它需要更多的步骤,如果在要删除的提交之后存在更多的提交,则需要更多的代码行。 - Dylan S.
我猜最简单的方法是克隆分支,然后从原始分支中挑选想要的提交并应用到新分支上。 - aligatorr89
这应该是准确的东西。谢谢! - Shivam Papat

5

如果您正在使用IntelliJ

假设您的分支X看起来像这样

提交[A] <-- 最后一次提交

提交[B]

提交[C]

提交[D]

您想要删除2个提交B和C。

1- 使用git log对话框右键单击提交D(要删除的提交之前的最后一次提交)并创建一个名为Y的新分支,Intellij将自动切换到分支Y

新分支

3- 您可以在git log对话框的左列中看到您的分支,请右键单击分支X并选择与当前版本进行比较

与当前版本比较

现在您将看到此对话框

比较对话框

4-您可以右键单击提交A并选择Cherry-pick

挑选

现在,在分支Y中,您有提交A和D,请解决冲突,进行提交和推送。


4
我同意上述所有解决方案,尤其是在你陷入困境时。如果中间提交没有对其子提交进行重要更改,你还可以进行交互式变基并丢弃你不想要的更改。
当我意外地选择了其他开发人员的提交但我不需要时,我通常会使用这个方法。
例如情景,我有以下3个提交:
865962a1f5 Update Book Title
a3b091b427 Remove Book Link From Header
838e768df2 Add New Book To Book List

出于某种原因,我不再希望从页眉中删除我的书链接。

步骤1。 git rebase -i Head~3

这将输出:

pick 865962a1f5 Update Book Title
pick a3b091b427 Remove Book Link From Header
pick 838e768df2 Add New Book To Book List

步骤2:将中间的提交中的'pick'替换为'drop'

pick 865962a1f5 Update Book Title
drop a3b091b427 Remove Book Link From Header
pick 838e768df2 Add New Book To Book List

步骤3. 写入并退出

在此之后,您可能需要进行一些冲突解决,但如果更改足够简单,则会删除中间提交,并留下以下历史记录:

865962a1f5 Update Book Title
838e768df2 Add New Book To Book List

你现在可以选择强制推送到远程分支git push -f,但要注意这可能会有一定的破坏性;或者你可以创建一个新的分支,并将你的MR切换到新的分支上!

这在你是唯一的开发人员负责一个项目时确实很有用,而且是具有破坏性的。 - theycallmepix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接