Git:如何在指定的之前完全删除提交?

时间:2016-07-04 15:41:38

标签: git

经过几年的git提交,我们想删除那些旧的。

我们有一个我们想要考虑作为新“基础”的提交号。

我们如何让git在指定的提交之前删除所有(并完全删除)提交?

2 个答案:

答案 0 :(得分:3)

您可以使用git rebase -igit filter-branch。首先请注意git rebase喜欢删除合并,因此如果您在复杂的存储库中执行此操作,并且需要保留许多分支和合并历史记录,则这是错误的工具;请改用git filter-branch

作为Paŭlo Ebermann noted in a comment,任何实现所需结果的方法都会为您提供所有新的提交ID。这是因为提交的ID ,在非常真实的意义上,该提交的内容其整个历史记录。请参阅Does a git commit hash equal a repository state? Git无法更改任何现有提交,因此,它必须复制存储库中的每个提交 -well,您要保留的每个提交,无论如何 - 新的提交具有不同的历史记录,特别是回溯到新的根提交的历史记录(它是原始提交的副本,但没有父级)。

最简单的方法是使用临时git replace或移植物,然后使用git filter-branch,这将使替换或移植永久保留在副本中。移植在概念上更简单,但在实践中有点manky(见意义2);使用截止移植物只需要足够长的时间来运行过滤器分支操作,你会没事的。有关哪些日期可以追溯到Git 1.7.x但仍然有效的说明,请参阅How do I remove the old history from a git repository?完成git filter-branch操作后(为了安全起见,您应该在临时副本克隆上执行此操作;您可以将此设置为在内存文件系统或SSD上以获得速度),您必须手动删除链接到旧历史记录的任何标记或其他外部引用。

请注意答案中的一个小错误:而不仅仅是git filter-branch -- --all您可能需要git filter-branch --tag-name-filter cat -- --all。另请注意,过滤带签名标签的签名(根据设计和安全性:签名代表签名者声明标记的项目是它声称的,并且您只是已更改它,通过filter-branch操作复制部分但不是全部,因此它不再与签名者签署的内容相同。有关其他详细信息和警告,请参阅the git filter-branch documentation

一旦历史记录看起来像您想要的那样,并且您可以确认所有提交ID都已更改且签名标记现在已取消签名 - 您可以随时使用签名标记比如,重做你自己的签名和自己签名,或让其他人重新签名,但是现在你必须处理缺少签名 - 获得一个新的,更小的存储库的最简单方法是克隆过滤的存储库,这将删除refs/original/留下的所有filter-branch引用。

由于Git's notes是按ID提交的,因此您也会丢失所有旧笔记。据我所知,没有工具可以跨过滤分支操作复制它们。在filter-branch的末尾就是这样做的地方,因为filter-branch仍然具有从旧ID到新ID的临时映射。可能filter-branch需要一个新功能,可以调用一个音符复制器(或单独使用它)。

答案 1 :(得分:2)

从该提交创建临时分支并对其进行rebase:

git checkout --orphan temp commitId
git commit -m "Truncated history"
git rebase --onto temp commitId master
git branch -D temp

commitId是新基地。查看the article了解详情。