如何在特定提交之前截断git历史记录?

5
由于不小心将所有二进制文件添加到我的git历史记录中,我有一个大约50 MB的git仓库。如何从历史记录中删除特定提交之前的所有提交?例如,有以下历史记录,我想删除C2之前的所有提交,就好像C2是第一个提交一样。(实际上,C2可能是合并提交)
我已经尝试过git-filter-branch,但它根本没有做我需要的事情,还尝试了this脚本,它似乎很流行,但它会删除整个历史记录,只留下一个提交。

History


git rebase -i 然后移除 C1 - ckruczek
附带问题:我可以问一下你是如何创建那个插图的吗? - Lasse V. Karlsen
@LasseV.Karlsen:他从git-scm网站上获取了它。但我可以推荐使用这个智能工具[https://onlywei.github.io/explain-git-with-d3/]或者[gitgraph](http://gitgraphjs.com)。 - ckruczek
@sorush-r:在 C1 之上,你有多少个分支和多少次提交? - LeGEC
如果您的问题已得到解答,请考虑接受答案;如果尚未解决,请提供更多信息以便我们帮助您。 - AnimiVulpis
3个回答

2

实现这个的一种方法是使用 git filter-branch --parent-filter,并从父节点集合中删除 C1。

git filter-branch --parent-filter "sed -e 's/-p $(git rev-parse C1)//'" -- --all

$(git rev-parse C1) 用于获取完整的40位提交ID,如果您已经知道它是什么,可以进行替换。

如果一些C1的祖先通过合并等方式被拉入,则也可以以同样的方式删除它们,或者使用更复杂的脚本,例如:

git filter-branch --parent-filter '
    for i in $(cat); do
        if [[ $i = -* ]] || git merge-base --is-ancestor "$i" C1; then
            continue
        else
            echo -n " -p $i"
        fi
    done
' -- --all

0
我建议创建一个新的孤立分支,然后进行挑选。
这样你就可以检查所有内容,甚至可以在你的机器上保留旧状态作为备份。

首先,在C2的位置创建一个新的分支。

$ git checkout <Hash of C2>
$ git checkout --orphan new-master

git checkout --orphan会创建一个没有父节点的新分支。

此时,您可以使用以下命令添加或删除文件:

  • git add:为此新的第一次提交添加文件
  • git rm --cached:删除新的第一次提交的文件,但将它们保留在硬盘上
  • git rm:从第一次提交以及硬盘中删除文件

确保所有即将被后续提交更改的文件都存在,否则挑选可能会变得非常混乱。

现在,使用git commit命令准备好您的新初始提交。

最后,通过cherry-picking正确的范围来重新应用所有其他提交。

$ git branch new-starting-point # for future reference
$ git cherry-pick ^C2 master

并且对于所有需要新历史记录的其他分支,重复执行这些步骤。

$ git checkout -b new-server new-starting-point
$ git cherry-pick ^C2 server

如果您想检查正确性,可以执行一些git diff master new-master
为了清理空间,请删除所有旧分支(以便旧提交不再可达)。在以下步骤中,您可能会丢失数据。确保您仍然拥有所需的所有内容:执行git gc应该足以清理空间。

1
挑选(和变基)除了线性历史以外不会保留任何其他内容 - 如果您想要它们出现在新历史中,您将不得不手动处理合并。 - ephemient
@ephemient,你说得完全正确。如果在你的新起始提交之后的历史记录中有合并,则“cherry-picking”不是真正的选择。使用filter-branch会更清晰。如果您扩展您的答案并解释这些选项,我将很高兴为其点赞。 - AnimiVulpis

-1

使用git filter-branch,而不是删除整个提交,您可以从提交中删除二进制文件:

git filter-branch --index-filter 'git rm --cached -rf bin/ && git rm --cached -f ./a.out' -- --all

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