删除git中的空提交

时间:2015-02-04 04:43:38

标签: git version-control git-commit

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

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

感谢。

2 个答案:

答案 0 :(得分:22)

执行此操作的一种简单(但缓慢)方法是使用git filter-branch--prune-empty。没有其他过滤器,任何其他提交都不会被更改,但任何空提交都将被丢弃(这将导致所有后续提交都有新的父ID,因此仍然“重写历史记录”:如果这是你的初始从hg导入到git,但如果其他人已经在使用此存储库,那么这是一个大问题。

注意所有通常使用filter-branch的警告。 (另外,作为旁注,“空提交”实际上是与前一次提交具有相同树的那个:它不是根本没有文件,而是它具有所有相同的文件,具有相同的模式,与其父提交相同的内容。这是因为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

一旦确定已过滤的克隆的克隆是好的,您就不需要过滤的克隆,并且可以使用最后一个克隆代替第一个克隆。 (也就是说,您可以用最终克隆替换“真实原始”。)

答案 1 :(得分:5)

使用--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