我为树中的提交条目继承了一个带有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
查看历史记录,我发现SomeDirectory
最初是一个git子模块,而且似乎导致问题的提交是删除了.gitmodules
和{{1}的提交}。
现在,在罪魁祸首的完全相同的地方有一个名为SomeDirectory
的真实目录
我虽然我仍然可以尝试修复运行SomeDirectory
以查看我最终会发生什么,但它不起作用:
git filter-branch
接下来应该尝试一下,知道在提交之前我没有知道备份导致问题。
答案 0 :(得分:14)
您收到的消息表明只有一棵树有一个坏的子模块。在这种情况下,你很少需要清理。您可以创建一个没有此问题的新固定树:
$ 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 commit c571a3ec94e9f84471577bac41ac7375c729ef08
以文本形式打印有问题的提交对象。它将以tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9
开头,并继续提交其余的提交信息(父,作者,提交者,提交消息)。 sed
替换了新tree
行对旧树的引用。 git hash-object -t commit -w --stdin
从结果中创建一个新的提交对象,将其写入存储库,然后打印其ID。
进行固定提交后,您可以使用git replace
:
$ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (new commit SHA1 here)
这实际上并没有改变任何东西,但是告诉Git每当它读取commit c571a3ec94e9f84471577bac41ac7375c729ef08
时,它应该读取新的提交对象。
最后,使用git filter-branch
使其永久化。这将通过所有提交,读取它们并将它们写回。通常,没有任何修改提交的选项,这不会产生太大影响,但由于前面的git replace
,这会导致所有以c571a3ec94e9f84471577bac41ac7375c729ef08
作为父项的提交被重写以引用相反,新的提交,所有提交引用那些重写的提交等等。
答案 1 :(得分:0)
也许它可以与交互式rebase一起修改包含麻烦的SomeDirectory提交引用的提交,例如
$ 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
答案 2 :(得分:0)
对于仍然有问题的人,我使用 git-filter-repo 解决了这个问题:
git filter-repo --path <folder> --invert-paths
filter-repo 没有 filter-branch 与 null sha1 相同的问题,而且速度要快得多。