所以,我继承了一个删除了一个子模块的存储库,我得到了可怕的:
warning in tree 6eb01385fa82fdef80719ec4990bec2e0b591d47: nullSha1: contains entries pointing to null sha1
我尝试使用this answer解决此问题。但是,假设我知道哪个提交包含了该树,而我找不到它:
git log --pretty='%H %T' | grep 6eb01385fa82fdef80719ec4990bec2e0b591d47
...不会返回任何内容。此外,使用filter-branch
命令作为上述问题的OP引发了关于提交的抱怨,但这是一个不同的树,并且使用ls-tree
列出此树也显示一对空的SHA1条目。
所以,总结一下:
fsck
发现了一个,但似乎没有附加到任何提交fsck
也许我可以使用前面提到的答案修复属于提交的那个,但孤儿树怎么样?
编辑:
感谢此处的所有建议。在快速机器上的tmpfs上拥有repo的副本可以轻松地测试所有这些。最终找出问题的一部分:
filter-branch
抱怨(e884a3b0)包含树e057f815a 现在我想知道如何应用官方答案,因为麻烦的树不是提交的直接子。据我所知,我应该修理/更换 6eb01385f并重新插入e057f815a,然后重新生成e057f815a以将其插入提交e884a3b0。那就是:
fsck
修复底层树git ls-tree {badtree} | sed -e '/0\{40\}/d' | git mktree
使父树指向它好的,所以努力尝试:
git ls-tree {parenttree} | sed -e 's/badtree/fixedtree/' | git mktree
到目前为止一切顺利。但旧的承诺和树木仍在那里。如果我想用以下方法删除它们:
# Create new tree by removing empty SHA1s
git ls-tree 6eb01385fa82fdef80719ec4990bec2e0b591d47 | sed -e '/0\{40\}/d' | git mktree
0eabc1625026f92b2737e763a087f7c4000f0084
# Create new parent tree by replacing bad tree by fixed tree in parent tree
git ls-tree e057f815aec33a48981921289fc7ab25e9ea1a16 | sed -e 's/6eb01385fa82fdef80719ec4990bec2e0b591d47/0eabc1625026f92b2737e763a087f7c4000f0084/' | git mktree
df56fe08e90f1a30e6467ac2bba50a3d771c9de4
# Create new commit by replacing old parent tree by new parent tree
git cat-file commit e884a3b0040b3940d259cd72d82be20d5eb8d7c3 | sed 's/e057f815aec33a48981921289fc7ab25e9ea1a16/df56fe08e90f1a30e6467ac2bba50a3d771c9de4/' | git hash-object -t commit -w --stdin
b41674793c985ba63bc68b095024ebcb2fbf0370
# Replace old commit by new commit
git replace e884a3b0040b3940d259cd72d82be20d5eb8d7c3 b41674793c985ba63bc68b095024ebcb2fbf0370
它抱怨我应该使用“-r”,所以我使用:
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch Somedir1 Somedir2' --prune-empty --tag-name-filter cat -- --all
运行...但是子模块已经被同一位置具有相同名称的目录所取代,因此上面的内容也会丢失很多有用的文件。并且git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch Somedir1 Somedir2' --prune-empty --tag-name-filter cat -- --all
仍然找到了坏树,此外它还发现了许多“悬挂标签”。有没有办法只删除两个坏树和提交?
答案 0 :(得分:1)
蛮力可能会成功:
which-commits-use-tree ()
{
local REPLY;
git rev-list --all --reflog | while read; do
git ls-tree -dr $REPLY | grep -q $1 && echo $REPLY uses $1;
done
}
作为中等回收的一次性可以容忍,它在我的小系统上用大约五分钟的时间扫描了整个git的历史。如果你有更大的东西,你需要耐心或更重的职责。
git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects --buffer \
| awk '/commit|tree/{print $1}' | git cat-file --batch | your-scanner-here
是我能想到的最快的方式来转储批量扫描的整个历史结构,这在git历史上耗时6秒;在linux repo上花了大约2m30,这是相当令人鼓舞的。不过,我可能不打算为此编写扫描仪。