如何在Git树中删除空sha1的条目 [英] How to remove an entry with null sha1 in a Git tree
问题描述
<$ c我已经继承了一个git仓库,其中一个空sha1用于树中的一个提交条目,防止FishEye索引仓库。 $ c> $ git fsck
检查对象导向:100%(256/256),完成。
树中的警告db22a67df70dc4ff90ec4cd666da91e9c2cb0d9:
包含指向空的条目sha1
检查对象:100%(416532/416532),完成。
检查连接:416532,完成。
寻找给定的树给我以下结果:
$ 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
和 SomeDirectory
。
现在,有一个名为 SomeDirectory
的实际目录与罪魁祸首完全相同的地方。
尽管我仍然可以尝试修复运行一个 git filter-branch
来看看我会结束,但它不起作用:
$ git filter-branch --force --index-filter \
$'git rm --cached --ignore -unmatch SomeDirectory'\
$ - 修剪空白--tag-name-filter cat - --all
[...为清晰起见划出]
重写c571a3ec94e9f84471577bac41ac7375c729ef08(76/18522)错误:
cache enttry has null sha1:SomeDirectory
致命错误:无法写入新的索引文件
无法初始化索引
[...为了清晰起见而清除]
接下来我应该怎么做,知道在导致问题的提交之前没有备份。
你得到的信息表明,只有一棵树有坏子模块。在这种情况下,你很少需要清理。您可以创建一个不存在此问题的新固定树:
$ git ls-tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 |
> sed -e'/ 0 \ {40 \} / d'|
> git mktree
(新建树SHA1)
你的问题显示 git已经有ls-tree
输出。 sed
删除包含坏子模块的行, git mktree
从结果中创建一个新的树对象。
一旦拥有固定树,您可以使用此树创建固定提交:
$ git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08 |
> sed's / db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 /(新树SHA1 here)/'|
> git hash-object -t commit -w --stdin
(新的提交SHA1在这里)
一旦你有了固定的提交,你可以使用 这实际上并没有改变任何东西,但告诉Git,每当它读取commit 最后,使用 I have inherited of a git repository with a null sha1 for a commit entry in a tree, preventing FishEye to index the repository. Looking for the given tree give me the following result: Looking in the history, I've found that What am I supposed to try next, knowing that there is no backup that I'm aware of prior to the commit that causes the issue. The message you get suggests that there was only a single tree with a bad submodule. In that case, there is very little you have to clean up. You can create a new fixed tree that doesn't have this problem: Your question shows the Once you have the fixed tree, you can create a fixed commit using this tree: Once you have the fixed commit, you can use This doesn't actually change anything yet, but tells Git that whenever it would read commit And finally, use 这篇关于如何在Git树中删除空sha1的条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! git cat-file commit c571a3ec94e9f84471577bac41ac7375c729ef08
以文本形式打印有问题的提交对象。它将以>树db22a67df70dc4ff90ec4cd666da91e9c2cb0d9
开头,并继续执行其余的提交信息(父,作者,提交者,提交信息)。 sed
用新树替换旧树的树行的引用。
git hash-object -t commit -w --stdin
从结果创建一个新的提交对象,将其写入存储库并打印其ID。 b
$ b git replace
:
$ git替换c571a3ec94e9f84471577bac41ac7375c729ef08(新的提交SHA1在这里)
c571a3ec94e9f84471577bac41ac7375c729ef08
时,它应该读取新的提交对象。
git filter-branch
使其成为永久的。这通过所有提交,读取它们,并将它们写回。通常,没有任何修改提交的选项,这不会有太大影响,但是由于前面的 git replace
,这会导致所有提交 c571a3ec94e9f84471577bac41ac7375c729ef08
作为父母被重新写入来引用新的提交,而所有提交这些提交的提交也是这样。$ 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
was initially a git submodule and that the commit that seems to cause the issue is the one that removed both the .gitmodules
and SomeDirectory
.
Now, there is a real directory called SomeDirectory
at the exact same place where the culprit was.
I though I could still try to fix run a git filter-branch
to see what I would end up, but it does not work:$ 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
output already. The sed
removes the line with the bad submodule, and git mktree
creates a new tree object from the result.
$ 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
prints the problematic commit object in a textual form. It will start with tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9
, and continues with the rest of the commit info (parent, author, committer, commit message). The sed
replaces the tree
line's reference to the old tree by the new one. git hash-object -t commit -w --stdin
creates a new commit object from the result, writes it to the repository, and prints its ID.git replace
:
$ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (new commit SHA1 here)
c571a3ec94e9f84471577bac41ac7375c729ef08
, it should read the new commit object instead.git filter-branch
to make it permanent. This goes through all commits, reads them, and writes them back. Ordinarily, without any options to modify the commits, this wouldn't have much effect, but because of the earlier git replace
, this causes all commits with c571a3ec94e9f84471577bac41ac7375c729ef08
as a parent to be re-written to refer to the new commit instead, all commits which refer to those re-written as well, etc.