我继承了一个带有null sha1的git存储库,用于树中的提交条目,防止FishEye索引存储库。
$ git fsck
Checking object directoriies: 100%(256/256), done.
warning in tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9:
contains entries pointing to null sha1
Checking objects: 100% (416532/416532), done.
Checking connectivity: 416532, done.
寻找给定的树给我以下结果:
$ git ls-tree db22a6
100644 blob e615f18b55a39f2719112ce209c2505dd92d8e75 .gitignore
100644 blob ac852f06c5a04420356c1d5efca44d9a864e78b0 .project
160000 commit 0000000000000000000000000000000000000000 SomeDirectory
100644 blob 631c17e28026261a2ccf6bc570842cf4af9f181c GoDeploy.bat
100644 blob 40e992ab5c3868af2910135c3ac4610c3646e7f8 pom.xml
纵观历史,我发现的某个目录
最初是一个git子模块,似乎导致问题的提交是删除了. gitmodule
和的某个目录
。现在,有一个真正的目录叫做的某个目录
在罪魁祸首所在的完全相同的地方。
我想我仍然可以尝试修复运行git filter-分支
以查看我最终会得到什么,但它不起作用:
$ git filter-branch --force --index-filter \
$ 'git rm --cached --ignore-unmatch SomeDirectory' \
$ --prune-empty --tag-name-filter cat -- --all
[... striped out for clarity]
Rewrite c571a3ec94e9f84471577bac41ac7375c729ef08 (76/18522)error:
cache enttry has null sha1: SomeDirectory
fatal: unable to write new index file
Could not initialize the index
[... striped out for clarity]
知道在导致问题的提交之前没有我知道的备份,我接下来应该尝试什么。
您收到的消息表明只有一棵树具有错误的子模块。在这种情况下,您只需清理很少。您可以创建一个没有此问题的新固定树:
$ git ls-tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 | > sed -e '/0\{40\}/d' | > git mktree (new tree SHA1 here)
您的问题已经显示了git ls-tree
输出。sed
删除了带有坏子模块的行,git mktree
从结果创建了一个新的树对象。
拥有固定树后,您可以使用此树创建固定提交:
$ git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08 | > sed 's/db22a67df70dc4ff90ec4cd666da91e9c2cb0d9/(new tree SHA1 here)/' | > git hash-object -t commit -w --stdin (new commit SHA1 here)
git cat-file提交c571a3ec94e9f84471577Bac41ac7375c729ef08
以文本形式打印有问题的提交对象。它将从tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9
开始,并继续其余的提交信息(父、作者、提交者、提交消息)。sed
将tree
行对旧树的引用替换为新树。git hash-object-t提交-w--stdin
从结果创建一个新的提交对象,将其写入存储库,并打印其ID。
一旦你有了固定的提交,你可以使用git替换
:
$ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (new commit SHA1 here)
这实际上还没有改变任何事情,但告诉Git,每当它读取提交c571a3ec94e9f84471577Bac41ac7375c729ef08
时,它应该读取新的提交对象。
最后,使用git filter-分支
使其永久化。这会遍历所有提交,读取它们并写回它们。通常,如果没有任何修改提交的选项,这不会有太大的影响,但由于早期的git替换
,这会导致所有以c571a3ec94e9f84471577Bac41ac7375c729ef08
作为父级的提交都被重写以引用新的提交,所有引用那些重写的提交等等。
对于任何仍然有问题的人,我使用git-filter-repo解决了这个问题:
git filter-repo --path <folder> --invert-paths
filter-repo与filter-分支空sha1没有相同的问题,并且速度要快得多。
看这个答案/问题:https://stackoverflow.com/a/61544937/1827771
也许它将与交互式rebase一起使用,以修改包含麻烦的某个目录提交引用的提交,例如。
$ git branch backup_branch # To be able to revert if not satisfied
$ git rebase -i db22a6^ # From parent to db22a6
...
# You then select Edit for commit db22a6 in the editor
...
$ git reset HEAD^ # Reset the commit db22a6 but not its changes
$ git status
...
# should list as modified: .gitignore .project SomeDirectory GoDeploy.bat pom.xml
...
$ git checkout SomeDirectory # Cancel the troublesome change
$ git add .gitignore .project GoDeploy.bat pom.xml
$ git commit -m "your commit message"
$ git rebase --continue