8

我继承了一个带有空 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 子模块,并且似乎导致问题的提交是同时删除了.gitmodulesSomeDirectory. 现在,有一个真正的目录被称为SomeDirectory与罪魁祸首完全相同的地方。
尽管我仍然可以尝试修复运行 agit filter-branch以查看最终结果,但它不起作用:

$ 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]

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

4

3 回答 3

15

您收到的消息表明只有一棵树的子模块不好。在这种情况下,您几乎不需要清理。您可以创建一个没有此问题的新固定树:

$ git ls-tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 |
> sed -e '/0\{40\}/d' |
> 混帐 mktree
(这里是新树 SHA1)

您的问题git ls-tree已经显示了输出。sed删除带有错误子模块的行,并从git mktree结果中创建一个新的树对象。

一旦你有了固定的树,你可以使用这个树创建一个固定的提交:

$ git cat-file 提交 c571a3ec94e9f84471577bac41ac7375c729ef08 |
> sed 's/db22a67df70dc4ff90ec4cd666da91e9c2cb0d9/(这里是新树 SHA1)/' |
> git 哈希对象 -t 提交 -w --stdin
(这里是新的提交 SHA1)

git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08以文本形式打印有问题的提交对象。它将以 开头tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9,并继续提交信息的其余部分(父、作者、提交者、提交消息)。用新的sed替换tree行对旧树的引用。git hash-object -t commit -w --stdin从结果中创建一个新的提交对象,将其写入存储库,并打印其 ID。

一旦你有固定的提交,你可以使用git replace

$ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (新提交 SHA1 在这里)

这实际上并没有改变任何东西,但告诉 Git 无论何时读取 commit c571a3ec94e9f84471577bac41ac7375c729ef08,它都应该读取新的提交对象。

最后,用于git filter-branch使其永久化。这会遍历所有提交,读取它们并将它们写回。通常,如果没有任何选项来修改提交,这不会有太大的影响,但由于较早的git replace,这会导致所有c571a3ec94e9f84471577bac41ac7375c729ef08作为父提交的提交被重写以引用新提交,所有提交引用那些也重写了,等等。

于 2014-06-15T09:50:36.007 回答
0

也许它将与交互式变基一起修改包含麻烦的 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
于 2014-06-12T13:27:48.253 回答
0

对于仍然遇到此问题的任何人,我使用 git-filter-repo 解决了这个问题:

git filter-repo --path <folder> --invert-paths

filter-repo 没有 filter-branch 与 null sha1 相同的问题,而且速度更快。

请参阅此答案/问题:https ://stackoverflow.com/a/61544937/1827771

于 2021-05-27T01:35:06.710 回答