如何在Git树中删除空sha1的条目 [英] How to remove an entry with null sha1 in a Git tree

查看:614
本文介绍了如何在Git树中删除空sha1的条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



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

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

 
$ git替换c571a3ec94e9f84471577bac41ac7375c729ef08(新的提交SHA1在这里)

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



最后,使用 git filter-branch 使其成为永久的。这通过所有提交,读取它们,并将它们写回。通常,没有任何修改提交的选项,这不会有太大影响,但是由于前面的 git replace ,这会导致所有提交 c571a3ec94e9f84471577bac41ac7375c729ef08 作为父母被重新写入来引用新的提交,而所有提交这些提交的提交也是这样。


I have inherited of a git repository with a null sha1 for a commit entry in a tree, preventing FishEye to index the repository.

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

Looking for the given tree give me the following result:

$ 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

Looking in the history, I've found that 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]

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:

$ git ls-tree db22a67df70dc4ff90ec4cd666da91e9c2cb0d9 |
> sed -e '/0\{40\}/d' |
> git mktree
(new tree SHA1 here)

Your question shows the 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.

Once you have the fixed tree, you can create a fixed commit using this tree:

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

Once you have the fixed commit, you can use git replace:

$ git replace c571a3ec94e9f84471577bac41ac7375c729ef08 (new commit SHA1 here)

This doesn't actually change anything yet, but tells Git that whenever it would read commit c571a3ec94e9f84471577bac41ac7375c729ef08, it should read the new commit object instead.

And finally, use 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.

这篇关于如何在Git树中删除空sha1的条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆