如何在Git树中删除null sha1的条目

时间:2014-06-12 12:00:18

标签: git git-filter-branch atlassian-fisheye

我为树中的提交条目继承了一个带有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

接下来应该尝试一下,知道在提交之前我没有知道备份导致问题。

3 个答案:

答案 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 相同的问题,而且速度要快得多。

看到这个答案/问题:https://stackoverflow.com/a/61544937/1827771