删除 git 中的空提交

Remove empty commits in git

我刚刚将一个项目从 Mercurial 迁移到 Git。当您添加标签时,Mercurial 会添加空提交,所以我最终在 Git 中得到了我想删除的空提交。

如何从 Git 中删除空提交(其中没有任何文件的提交)?

谢谢。

一种简单(但缓慢)的方法是使用 git filter-branch--prune-empty。在没有其他过滤器的情况下,不会更改其他提交,但会丢弃任何空的提交(这将导致所有后续提交具有新的父 ID,因此仍然 "rewrites history":如果这是您的,则没什么大不了的最初从 hg 导入到 git,但如果其他人已经在使用这个存储库,那就很重要了)。

注意过滤器分支的所有常见注意事项。 (此外,作为旁注,"empty commit" 实际上是一个与前一次提交具有相同树的文件:并不是说它根本没有文件,而是它具有所有相同的文件,具有相同的模式,以及与其父提交相同的内容。这是因为 git 为每个提交存储完整的快照,而不是从一个提交到下一个提交的差异。)


这是一个小例子,它隐藏了很多你可以做更奇特的事情的地方:

$ ... create repository ...
$ cd some-tmp-dir; git clone --mirror file://path-to-original

(第一个克隆步骤是为了安全起见:filter-branch 可能具有相当大的破坏性,因此在新克隆而不是原始克隆上启动它总是好的。使用 --mirror 意味着它的所有分支和标签也反映在此副本中。)

$ git filter-branch --prune-empty --tag-name-filter cat -- --all

(现在可能会等待很长时间;请参阅有关加快速度的方法的文档。)

$ git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

(此步骤是从文档中复制的:它丢弃了 运行 过滤器之前的所有原始分支。换句话说,它使过滤永久化。由于这是一个克隆,因此相当安全即使过滤器出了问题也要做。)

$ cd third-tmp-dir; git clone --mirror file://path-to-filtered-tmp

(这会生成过滤副本的干净、压缩良好的副本,没有过滤步骤留下的对象。)

$ git log     # and other commands to inspect

一旦您确定过滤克隆的克隆是好的,您就不需要过滤克隆,并且可以使用最后一个克隆代替第一个。 (也就是说,您可以将 "true original" 替换为最终的克隆。)

使用 --commit-filter 应该比使用 --prune-empty 更快

$ git filter-branch --tag-name-filter cat --commit-filter 'git_commit_non_empty_tree "$@"' -- --all

然后按照torek的回答

清理备份引用

$ git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

取自此处:Git - remove commits with empty changeset using filter-branch