git fsck:duplicateEntries:包含重复的文件条目-无法推送到gitlab

Tim*_*Tim 7 git gitlab

我们有一个很大的git存储库,我想将其推送到一个自托管的gitlab实例。

问题是gitlab遥控器不允许我推送我的仓库:

git push --mirror https://mygitlab/xy/myrepo.git
Run Code Online (Sandbox Code Playgroud)

这会给我这个错误:

Enumerating objects: 1383567, done.
Counting objects: 100% (1383567/1383567), done.
Delta compression using up to 8 threads
Compressing objects: 100% (207614/207614), done.
remote: error: object c05ac7f76dcd3e8fb3b7faf7aab9b7a855647867: 
duplicateEntries: contains duplicate file entries
remote: fatal: fsck error in packed object    
Run Code Online (Sandbox Code Playgroud)

所以我做了一个git fsck:

error in tree c05ac7f76dcd3e8fb3b7faf7aab9b7a855647867: duplicateEntries: contains duplicate file entries
error in tree 0d7286cedf43c65e1ce9f69b74baaf0ca2b73e2b: duplicateEntries: contains duplicate file entries
error in tree 7f14e6474400417d11dfd5eba89b8370c67aad3a: duplicateEntries: contains duplicate file entries
Run Code Online (Sandbox Code Playgroud)

我要做的下一件事是检查git ls-tree c05ac7f76dcd3e8fb3b7faf7aab9b7a855647867

100644 blob c233c88b192acfc20548d9d9f0c81c48c6a05a66    fileA.cs
100644 blob 5d6096cb75d27780cdf6da8a3b4d357515f004e0    fileB.cs
100644 blob 5d6096cb75d27780cdf6da8a3b4d357515f004e0    fileB.cs
100644 blob d2a4248bcda39c0dc3827b495f7751b7cc06c816    fileC.xaml
Run Code Online (Sandbox Code Playgroud)

注意,fileB.cs它显示了两次,并且具有相同的哈希值。我认为这是问题所在,因为为什么文件在同一树中被两次使用相同的文件名和Blob哈希?

现在,我用谷歌搜索了问题,但是找不到解决该问题的方法。我发现一个看似不错的资源是:树包含重复的文件条目

但是,基本上可以归结为使用git replace并不能真正解决问题,因此git fsck仍会打印错误并阻止我将其推送到远程。

然后有一个似乎完全删除了文件的文件(但我仍然需要文件,但只需要一次,在树中不是两次):https : //stackoverflow.com/a/44672692/826244

还有其他解决方法吗?我的意思是说真的应该可以修复,以便git fsck不会抛出任何错误,对吗?我知道在损坏的提交之后,我将需要重写整个历史记录。我什至找不到找到指向特定树的提交的方法,否则我也许可以使用rebase并修补损坏的提交或其他内容。任何帮助将不胜感激!

更新:可以肯定的是我知道该怎么做,但还不知道怎么做:

  1. 从旧树创建新树对象,但用git mktree<-完成纠正
  2. 创建一个新提交,该提交与引用坏树的旧提交相同,但是使用新固定的树<-困难,我无法轻松地将提交提交给该树,我当前的解决方案运行了一个小时或更长时间,我不知道一旦找到它,如何创建修改后的提交
  3. 运行git filter-branch -- --all<-应该坚持提交的替换

可悲的是,我不能只git replace --edit在坏树上使用然后运行,git filter-branch -- --all因为它filter-branch似乎只在提交时起作用,而忽略树替换...

Tim*_*Tim 1

最终的解决方案是编写一个工具来解决这个问题。

第一步是 git unpack-objects 所有包文件。然后,我必须通过读取所有引用来识别指向具有重复项的树条目的提交,然后返回历史记录检查所有树。在我拥有了相应的工具之后,现在重写这些提交的树,然后重写之后的所有提交并不是那么困难。之后我必须更新更改的参考。这是我彻底测试结果的时刻,因为还没有丢失任何东西。最后git reflog expire --expire=now --all && git gc --prune=now --aggressive重写了包并删除了所有无法再访问的松散对象。

当我有时间时,我会将源代码上传到 github,因为它的性能非常好,并且可以作为类似问题的模板。它在 3.7GB 的存储库(解压后约 20GB)上只运行了几分钟。到目前为止,我还实现了从包文件中读取,因此无需再解压任何内容(这需要大量时间和空间)。

更新:我在源代码上做了更多工作,现在它的性能非常好,甚至比删除单个文件的 bfg 还要好(还没有选项切换)。源代码可在此处获取:https://github.com/TimHeinrich/GitRewrite 请注意,这仅针对单个存储库进行了测试,并且仅在 core i7 上的 Windows 下进行了测试。它不太可能在 Linux 或任何其他处理器架构上工作