我需要怎么做才能从.git文件夹中删除其余对象?

时间:2019-06-06 09:54:26

标签: git

首先,我在git中所做的事情:

  E:\zeus>git filter-branch -f --tree-filter "rm -rf ZeusSRC_Hardware_RPi_image_Raspberry Pi_außen_20.05.2019.zip" --prune-empty -- --all
  Rewrite fa2be75c64ca78a296c8f78fc363beebecbf92a1 (1526/1526) (2745 seconds passed, remaining 0 predicted)
  Ref 'refs/heads/Kunden' was rewritten
  Ref 'refs/heads/Sensor' was rewritten
  Ref 'refs/heads/Wetter' was rewritten
  Ref 'refs/heads/ZEUS-5' was rewritten
  Ref 'refs/heads/Zeus_Bug-13' was rewritten
  WARNING: Ref 'refs/heads/master' is unchanged
  Ref 'refs/remotes/origin/ADW' was rewritten
  WARNING: Ref 'refs/remotes/origin/master' is unchanged
  Ref 'refs/remotes/origin/Kunden' was rewritten
  Ref 'refs/remotes/origin/Metzger' was rewritten
  WARNING: Ref 'refs/remotes/origin/Mond' is unchanged
  Ref 'refs/remotes/origin/Sensor' was rewritten
  WARNING: Ref 'refs/remotes/origin/Sonne' is unchanged
  Ref 'refs/remotes/origin/Wetter' was rewritten
  WARNING: Ref 'refs/remotes/origin/ZEUS-2' is unchanged
  WARNING: Ref 'refs/remotes/origin/ZEUS-3' is unchanged
  Ref 'refs/remotes/origin/ZEUS-5' was rewritten
  Ref 'refs/remotes/origin/ZEUS_BUG-12' was rewritten
  WARNING: Ref 'refs/remotes/origin/ZEUS_BUG-4' is unchanged
  Ref 'refs/remotes/origin/ZEUS_BUG-6' was rewritten
  WARNING: Ref 'refs/remotes/origin/ZEUS_BUG-8' is unchanged
  Ref 'refs/remotes/origin/ZEUS_BUG-9' was rewritten
  Ref 'refs/remotes/origin/Zeus_Bug-13' was rewritten
  WARNING: Ref 'refs/remotes/origin/master' is unchanged
  WARNING: Ref 'refs/remotes/origin/metzger' is unchanged
  WARNING: Ref 'refs/remotes/origin/tempAddFirstCode' is unchanged
  Ref 'refs/stash' was rewritten

第二,应该执行以下操作: 我的存储库中有一些ISO,大约4GB。我删除了它,使用git add。然后提交并推送,但是回购大小当然没有改变,因为仍然有一些对象曾经与以前的提交相关联。所以我首先要知道:

根据上述git的输出,我可以假定受git命令影响的文件现在已从历史记录中删除了吗?

据我所知,从历史记录中删除文件是我接下来要做的必不可少的前提: 使用垃圾收集器“手动”从我的仓库中删除相关对象。

我已经在SO上偶然发现了几篇有关此问题的文章,例如,我发现了git这个颇受欢迎的脚本:

 git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc

可能需要先执行以下操作:

      git remote rm origin
      rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
      git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 -- 
      no-run-if-empty git update-ref -d

从这里:How to remove unreferenced blobs from my git repo 但是,这些命令对我没有真正的作用:/

1 个答案:

答案 0 :(得分:0)

潜在的缺失

  1. 如果有任何标签,则可能需要重做过滤器分支(从存储库的良好副本开始)并包括:

    --tag-name-filter cat
    

    git filter-branch选项中。

  2. 如果包装上有keep个文件,它们可能会阻止大型对象的移除。 (如果您有这些,您可能知道这一点。)

讨论

  

根据上述git的输出,我可以假定受git命令影响的文件现在已从历史记录中删除了吗?

更准确地说,是有一个 new 历史记录,其中从来没有添加文件,除了文件的现有历史记录之外,还存在该历史记录添加了 。每个was rewritten参考都指向 new 历史记录的最前面的一次提交。每个is unchanged都指向现有未更改历史记录尖端的提交,这是可以的,因为现有的未更改历史记录中从未包含文件。例如,想象下面的高度简化图(只有两个分支):

A--B--C   <-- master
       \
        D--E   <-- Kunden

文件ZeusSRC_Hardware_RPi_image_RaspberryPi_außen_20.05.2019.zip在提交D中存在的位置。因此git filter-branch提取了提交D,删除了两个文件,然后进行了一次新的提交,我们将其称为D',不再包含以下文件:

        D'-E'
       /
A--B--C   <-- master
       \
        D--E   <-- Kunden

这两个文件在E中可能存在也可能不存在,但是创建新的提交D'意味着Git 必须还创建一个新的E',当然新的E'也将其删除(如果它们存在于E中。

现在已经建立了新的历史记录,Git必须丢弃现有的refs/heads/Kunden并放入指向提交refs/heads/Kunden的{​​{1}}(Kunden分支)中。现有的E'可以,因此可以单独使用:

refs/heads/master

D'-E' <-- Kunden / A--B--C <-- master \ D--E [original Kunden] 留下的refs/original/refs/heads/Kunden名称保留了提交git filter-branch,但各种不可见的引用日志条目也是如此。第一个是E名称,它的含义是:

refs/original/*

因为它将删除每个这样的名称。

此:

git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d

旨在处理第二个问题-reflog,还包括 git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc 的最后一步。 the git filter-branch documentation中的建议改为使用两个单独的命令:

git gc

目前,我希望指定配置项的git reflog expire --expire=now --all git gc --prune=now 可以正常工作,但如果不行,请参阅分支机构文档。

一旦所有对提交git gc的引用都消失了,并且假设没有对提交E的引用,D将丢弃对象git gcD。如果打包了这些对象,Git将构建一个新的打包文件,将其忽略,然后将它们变成松散的对象。松散对象修剪将在对象修剪延迟后将其丢弃,并且除非将旧的打包文件与打包保持文件一起保存,否则将对其进行垃圾回收。

假设您有一个标签名,例如E。进一步假设标记名称指向提交v2.1

D

由于未重写 D'-E' <-- Kunden / A--B--C <-- master \ D--E . ...... <-- tag: v2.1 ,因此标签refs/tags/v2.1继续保留提交v2.1,该提交继续保留大文件。当您运行D时,它会建立一个映射,该映射包含以下事实:新提交git filter-branchD'的正确替代者。如果仍然有映射,则可以使用该映射来强制移动标签D,使其指向提交v2.1。不幸的是,D'完成后,在对各种名称执行了所有“重写”操作之后,它删除了并认为映射已完成。

(旁注:不需要git filter-branch。如您在上面看到的,许多远程跟踪名称都被重写,包括git rm origin。这确实< / em>表示如果不使用refs/remotes/origin/Kunden,将无法在origin上更新其他Git存储库,如果不更新,git push -f将带来大文件回来。)

最后,这个:

git fetch

表示您现有的保存的存储区可能已损坏,无法再应用。 (Filter-branch并没有意识到隐藏是故意有点怪异的,并且将它们视为正常合并,有时会破坏它们。)