如何从分支中间移除一个提交

30

我已经提交了一些更改并将它们推送到我的远程仓库。其中一个我想要删除。它只包含一个二进制文件,在那个分支的那次提交中才发生了更改。如何在不影响后续提交的情况下删除它?


6
git rebase -i TARGET_COMMIT~1 然后不要选择 TARGET_COMMIT,我认为这样会起作用。 - CollinD
1
在@CollinD的解决方案中,你将不得不强制推送到远程仓库(首选--force-with-lease),因为你的更改无法快速前进。 如果你想避免这些问题,可以使用git revert来撤销此次提交。 - kolejnik
3个回答

60
你可以使用交互式(-i)变基来删除以前的提交。
$ git log                          # copy the target commit 

$ git rebase -i <target-commit>~1  # start rebase from the previous commit of target commit

编辑器将打开一个包含提交列表的窗口,每行一个提交。这些行中的每一行都以pick开头。 注释掉您要目标提交的那一行(在目标提交行的开头放置#)。

或者,可以用dropd代替注释掉带有#的行。

$ git rebase --continue      # repeat the command until finish rebase

现在,由于 Git 历史记录已经被更改,你需要进行强制推送 (-f) 到远程仓库!

$ git push -f origin HEAD 

最后一步即推送 -f 后会发生什么? - AKSHAY SHINGOTE
@AKSHAYSHINGOTE,你的远程仓库(origin)将会被更新(从Git历史中删除提交)。 - Sajib Khan
2
做得好,谢谢你。注意:如果你想更明确,你也可以使用“drop”或“d”代替注释掉带有“#”的行。 - Joshua Pinter
1
是的,@joshu Pinter。已更新答案。谢谢! - Sajib Khan
为什么没有人谈论 --rebase-merges 标志呢?这个解决方案应该被考虑在答案中,因为它将删除 HEAD 和目标提交+1 之间的合并提交。 - KJanek
显示剩余2条评论

8

应该考虑使用标志 --rebase-merges,因为接受的解决方案将删除头部和目标提交之间的合并提交~1

示例:

Before any rebase:

f3e07b4 (HEAD -> dev, origin/dev) headCommit
dd3d182 Merged PR 425: added playoutServerUsage
7ed3eb5 added playoutServerUsage
03b52af feat: add Description Series  #targetCommit
0a1217c some_older_commit

git rebase -i target-commit~1

c11fa07 (HEAD -> dev) headCommit
7ed3eb5 added playoutServerUsage
0a1217c some_older_commit

git rebase -i target-commit~1 --rebase-merge

a1943b6 (HEAD -> dev) headCommit
12411a1 Merged PR 425: added playoutServerUsage
7ed3eb5 added playoutServerUsage
0a1217c some_older_commit

Rebase with flag --rebase-merges can be harder and whole process will be longer (bigger tree), but still we have to locate target commit and change 'pick' to 'drop'

之后,我建议使用
git push --force-with-lease origin HEAD 

不要只使用强制。

强制 vs 强制带租约

附注:值得注意的是哪些提交哈希值发生了变化


-3
如果您不介意取消跟踪所有文件,那么您可以尝试从目录中删除.git文件。
这个文件包含了所有Git提交的详细信息。
这对我有用,也可能对您有用。

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