从历史中删除 git 次提交

Removing a git commit from history

假设我在 git

中有以下提交
A---B---C---D---E---F

还假设提交 BD 是空的(不包含文件,即空快照)。

所以,我想去掉 BD;我正在做以下事情:

git filter-branch --prune-empty

最后我得到以下结果:

A---B---C---D---E---F
 \
  \--C'---E'---F'

但这不是我想要的,我想以

结束
A---C'---E'---F'

我该怎么做?

注:我也试过:

git rebase -i HEAD~6

但是还是不行。


重要更新

事实证明我做对了。来自 mu 无 的回答启发了我更多地研究为什么它对他有效但对我无效。我原来的分支从未被删除。经过进一步调查,似乎我在 C 广告 F 中有标签导致分支保留。因此,在 运行 filter-branch 命令之前,我删除了两个标签并且它起作用了。

您实际上已经以正确的提交结束,现在就git checkout F'

如果您将这些更改推送到远程存储库,则需要使用 git push -f origin branch_F':branch_F.

强制更新那里的分支

示例:

  1. 创建一个新的存储库

    $ git init 
    $ touch a && git add a && git commit -m "added a"
    $ git commit --allow-empty -m "empty 1"
    $ touch b && git add b && git commit -m "added b"
    $ git commit --allow-empty -m "empty 2"
    $ touch c && git add c && git commit -m "added c"
    
  2. 检查提交历史

    $ git log --oneline
    27196e9 (HEAD, master) added c
    24e10de empty 2
    a2d3931 added b
    88be904 empty 1
    564d4e4 added a
    
  3. 运行 过滤分支

    $ git filter-branch --prune-empty
    Rewrite 27196e9bc27e93ff54ebd10a5c8435e7fe496c78 (5/5)
    Ref 'refs/heads/master' was rewritten
    
  4. 再次检查日志中的提交

    $ git log --oneline
    221f0d0 (HEAD, master) added c
    ab6bf5f added b
    564d4e4 added a
    

编辑

正如 OP 在他的 中提到的那样,这是由于中间提交中存在的标签而发生的。删除标签使这项工作。

在 git 中有几种方法可以做到这一点,但首先你必须确保没有人已经拉过分支。如果有人确实拉了它,你不能并且不应该改变树的历史。

如果有人已经提取了它,您只需重新添加 "old" 内容并覆盖当前数据。

万一还没有人拉,这里有一些你的选择:

  1. 键入 git reflog 并检查更改之前的最后一次良好提交,您将获得一个分离的头部,因此创建一个新分支,删除远程分支并再次推送它。

  2. 使用git revert

  3. git format-patch** <number of commit to choose> 然后按照项目符号#1 中的描述检查分支并应用所需的提交(删除您希望跳过的提交)

还有更多选项,但这些是最简单的选项。