我如何从git仓库中删除旧的历史logging?

恐怕我找不到像这种特殊情况的东西。

我有一个有很多历史的Git仓库:500多个分支,500多个标签,回到2007年中期。 它包含约19,500个提交。 我们希望在2010年1月1日之前删除所有的历史logging,以使它更小,更容易处理(我们将在档案库中保存完整的历史logging副本)。

我知道我希望成为新版本库的提交者。 我不能,但是,找出正确的git mojo截断回购开始与提交。 我猜猜的一些变种

git filter-branch 

涉及移植物将是必要的; 可能还需要对待我们要分开保存的200多个分支中的每一个,然后将回购补回(我知道该怎么做)。

有没有人做过这样的事情? 如果这个问题我有git 1.7.2.3。

只要创build一个新的根提交的父母移植到没有父(或空的提交,例如您的存储库的真正的根提交)。 例如echo "<NEW-ROOT-SHA1>" > .git/info/grafts

创build嫁接后,立即生效; 你应该可以看看git log ,看到不需要的旧提交已经消失:

 $ echo 4a46bc886318679d8b15e05aea40b83ff6c3bd47 > .git/info/grafts $ git log --decorate | tail --lines=11 commit cb3da2d4d8c3378919844b29e815bfd5fdc0210c Author: Your Name <your.email@example.com> Date: Fri May 24 14:04:10 2013 +0200 Another message commit 4a46bc886318679d8b15e05aea40b83ff6c3bd47 (grafted) Author: Your Name <your.email@example.com> Date: Thu May 23 22:27:48 2013 +0200 Some message 

如果所有看起来像预期的,你可以做一个简单的git filter-branch -- --all使它永久。

注意:在执行过滤分支步骤之后,所有提交标识符都将发生更改,因此使用旧回购的任何人都不得与使用新回购的任何人合并。

这种方法很容易理解,工作正常。 脚本的参数( $1 )是一个引用(标记,哈希,…),从您想要保留您的历史开始提交。

 #!/bin/bash git checkout --orphan temp $1 # create a new branch without parent history git commit -m "Truncated history" # create a first commit on this branch git rebase --onto temp $1 master # now rebase the part of master branch that we want to keep onto this branch git branch -D temp # delete the temp branch # The following 2 commands are optional - they keep your git repo in good shape. git prune --progress # delete all the objects w/o references git gc --aggressive # aggressively collect garbage; may take a lot of time on large repos 

请注意 ,旧标签仍然存在; 所以你可能需要手动删除它们

评论:我知道这几乎和@yoyodin一样,但是这里有一些重要的额外命令和信息。 我试图编辑答案,但由于这是@ yoyodin的答案的重大变化,我的编辑被拒绝,所以这里的信息!

试试这个方法如何截断git历史 :

 #!/bin/bash git checkout --orphan temp $1 git commit -m "Truncated history" git rebase --onto temp $1 master git branch -D temp 

这里$1是您要保留的提交的SHA-1,脚本将创build一个新的分支,其中包含$1master之间的所有提交,并删除所有较旧的历史logging。 请注意,这个简单的脚本假定您没有现有的分支叫做temp 。 另外请注意,这个脚本不会清除旧的历史logging的git数据。 运行git gc --prune=all && git repack -a -f -F -d确认您确实想要丢失所有历史logging后。 您可能还需要重新rebase --preserve-merges但要注意,该function的git实现并不完美。 如果你使用的话,手动检查结果。

也许发表回复已经太迟了,但是由于这个页面是Google的第一个结果,它可能仍然有帮助。

如果你想在你的git仓库中释放一些空间,但不想重build所有的提交(rebase或者移植),并且仍然能够从完全回购的人推/拉/合并,你可以使用git克隆 浅度克隆( –depth参数)。

 ; Clone the original repo into limitedRepo git clone file:///path_to/originalRepo limitedRepo --depth=10 ; Remove the original repo, to free up some space rm -rf originalRepo cd originalRepo git remote rm origin 

您可以通过执行以下步骤来简化现有的回购:

 ; Shallow to last 5 commits git rev-parse HEAD~5 > .git/shallow ; Manually remove all other branches, tags and remotes that refers to old commits ; Prune unreachable objects git fsck --unreachable ; Will show you the list of what will be deleted git gc --prune=now ; Will actually delete your data 

Ps:老版本的git不支持从/到浅回购的克隆/推/拉。

作为重写历史的替代方法,可以考虑使用Pro Git书中的本文中的 git replace 。 讨论的例子涉及replace父提交来模拟树的开始,同时仍然保持完整的历史作为单独的分支来保pipe。

如果你想保持 上游存储库的完整的历史 ,但本地较小的签出,使用git clone --depth=1 [repo]做一个浅层克隆。

推后,你可以做

  1. git fetch --depth=1来修剪旧的提交。 这使旧的提交和他们的对象无法访问。
  2. git reflog expire --expire-unreachable=now --all 。 过期所有旧的提交及其对象
  3. git gc --aggressive --prune=all删除旧的对象

参见如何在提交后删除本地git历史logging? 。

请注意,您无法将此“浅”存储库推送到其他位置:“浅层更新不允许”。 更改Git远程URL后,请参阅远程拒绝(不允许浅层更新) 。 如果你想这样做,你必须坚持嫁接。

我需要阅读几个答案和其他一些信息,以了解我在做什么。

1.忽略比某个提交更早的事情

文件.git/info/grafts可以定义一个提交的假父母。 一个只有一个提交ID的行说,提交没有父母。 如果我们想说我们只关心最近的2000次提交,我们可以input:

 git rev-parse HEAD~2000 > .git/info/grafts 

git rev-parse给了我们当前提交的第2000个父代的提交ID。 上述命令将覆盖移植文件(如果存在)。 检查它是否在那里。

2.重写Git历史logging(可选)

如果你想使这个嫁接的假父母是一个真正的父母,然后运行:

 git filter-branch -- --all 

它会改变所有的提交id。 这个存储库的每个副本都需要被强制更新。

3.清理磁盘空间

我没有做第3步。我想我的副本保持与上游兼容。 我只是想节省一些磁盘空间。 为了忘记所有旧的提交:

 git prune git gc 

另类:浅拷贝

如果您有另一个存储库的浅拷贝,并且只想保存一些磁盘空间,则可以更新.git/shallow 。 但要小心,没有任何东西指向以前的承诺。 所以你可以运行这样的东西:

 git fetch --prune git rev-parse HEAD~2000 > .git/shallow git prune git gc 

浅层作品的入口像移植物一样。 但要小心不要同时使用移植物和浅层。 至less,在那里没有相同的条目,它会失败。

如果您还有一些旧的引用(标签,分支,远程头)指向较旧的提交,它们将不会被清理,并且不会节省更多的磁盘空间。

当发生重build推动 头/掌握这个错误可能发生

 remote: GitLab: You are not allowed to access some of the refs! To git@giturl:main/xyz.git ! [remote rejected] master -> master (pre-receive hook declined) error: failed to push some refs to 'git@giturl:main/xyz.git' 

要在git仪表板中解决这个问题,应该从“受保护的分支”中删除主分支

在这里输入图像说明

那么你可以运行这个命令

 git push -f origin master 

要么

 git rebase --onto temp $1 master 

你可以使用下面提到的jar [下载]和命令来删除目录,文件以及与目录或文件相关的整个历史logging

bfg.jar文件: https ://rtyley.github.io/bfg-repo-cleaner/

git clone –bare repo-url cd repo_dir java -jar bfg.jar –delete-folders folder_name git reflog expire –expire = now –all && git gc –prune = now –aggressive git push –mirror repo_url

  1. 删除git数据,rm .git
  2. git init
  3. 添加一个git远程
  4. 推力