方法一。
先执行git fsck。
$ git fsck --full
error in tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29: contains duplicate file entries
如果这不能解决问题,你就有麻烦了。
您可以忽略该问题,从备份中恢复存储库,或将文件移动到新存储库中。如果您无法将 repo 推送到 github,请尝试将存储库更改为其他存储库或检查:Can't push to GitHub error: pack-objects died of signal 13 和 Can't push new git repository to github。
以下方法仅适用于高级 git 用户。请在开始前做好备份。以下步骤无法保证修复,它可能会使情况变得更糟,因此出于您自己的风险或教育目的,请这样做。
方法二。
使用 git ls-tree 识别重复文件。
$ git read-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 # Just a hint.
$ git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 # Try also with: --full-tree -rt -l
160000 commit def08273a99cc8d965a20a8946f02f8b247eaa66 commerce_coupon_per_user
100644 blob 89a5293b512e28ffbaac1d66dfa1428d5ae65ce0 commerce_coupon_per_user
100644 blob 2f527480ce0009dda7766647e36f5e71dc48213b commerce_coupon_per_user
100644 blob dfdd2a0b740f8cd681a6e7aa0a65a0691d7e6059 commerce_coupon_per_user
100644 blob 45886c0eda2ef57f92f962670fad331e80658b16 commerce_coupon_per_user
100644 blob 9f81b5ca62ed86c1a2363a46e1e68da1c7b452ee commerce_coupon_per_user
如您所见,它包含重复的文件条目 (commerce_coupon_per_user)!
$ git show bb81a5af7e9203f36c3201f2736fca77ab7c8f29
tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29
commerce_coupon_per_user
commerce_coupon_per_user
commerce_coupon_per_user
commerce_coupon_per_user
commerce_coupon_per_user
commerce_coupon_per_user
再次,您可以看到重复的文件条目 (commerce_coupon_per_user)!
您可以尝试对每个列出的 blob 使用 git show 并检查每个文件的内容。
然后在不同的 git 克隆中继续为该无效 ls-tree 对象运行 ls-tree 以查看是否可以跟踪有效对象,或者是否所有对象都已损坏。
git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29
If you found the valid object containing non-duplicated file entries, save it into the file and re-create by using `git mktree` and `git replace`, e.g.
remote$ git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 > working_tree.txt
$ cat working_tree.txt | git mktree
NEWTREEbb81a5af7e9203f36c3201f2736fca77ab7c8f29
$ git replace bb81a5af7e9203f36c3201f2736fca77ab7c8f29 NEWTREE4b825dc642cb6eb9a060e54bf8d69288fbee4904
如果这没有帮助,您可以通过以下方式撤消更改:
$ git replace -d NEWTREE4b825dc642cb6eb9a060e54bf8d69288fbee4904
方法三。
当您知道哪个文件/目录条目重复时,您可以尝试删除该文件并稍后重新创建它。例如:
$ find . -name commerce_coupon_per_user # Find the duplicate entry.
$ git rm --cached `find . -name commerce_coupon_per_user` # Add -r for the dir.
$ git commit -m'Removing invalid git entry for now.' -a
$ git gc --aggressive --prune # Deletes loose objects! Please do the backup before just in case.
阅读更多:
方法四。
检查您的提交是否有无效条目。
让我们再次检查我们的树。
$ git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 --full-tree -rt -l
160000 commit def08273a99cc8d965a20a8946f02f8b247eaa66 commerce_coupon_per_user
100644 blob 89a5293b512e28ffbaac1d66dfa1428d5ae65ce0 270 commerce_coupon_per_user
....
$ git show def08273a99cc8d965a20a8946f02f8b247eaa66
fatal: bad object def08273a99cc8d965a20a8946f02f8b247eaa66
$ git cat-file commit def08273a99cc8d965a20a8946f02f8b247eaa66
fatal: git cat-file def08273a99cc8d965a20a8946f02f8b247eaa66: bad file
上面的提交似乎无效,让我们使用以下命令之一扫描我们的 git 日志以检查发生了什么:
$ git log -C3 --patch | less +/def08273a99cc8d965a20a8946f02f8b247eaa66
$ git log -C3 --patch | grep -C10 def08273a99cc8d965a20a8946f02f8b247eaa66
commit 505446e02c68fe306aec5b0dc2ccb75b274c75a9
Date: Thu Jul 3 16:06:25 2014 +0100
Added dir.
new file mode 160000
index 0000000..def0827
--- /dev/null
+++ b/sandbox/commerce_coupon_per_user
@@ -0,0 +1 @@
+Subproject commit def08273a99cc8d965a20a8946f02f8b247eaa66
在这种特殊情况下,我们的提交指向了错误的对象,因为它是作为 git 子项目的一部分提交的,该子项目不再存在(检查 git submodule status)。
您可以从 ls-tree 中排除该无效对象并重新创建没有此坏对象的树,例如:
$ git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 | grep -v def08273a99cc8d965a20a8946f02f8b247eaa66 | git mktree
b964946faf34468cb2ee8e2f24794ae1da1ebe20
$ git replace bb81a5af7e9203f36c3201f2736fca77ab7c8f29 b964946faf34468cb2ee8e2f24794ae1da1ebe20
$ git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 # Re-test.
$ git fsck -full
注意:旧对象仍应抛出重复的文件条目,但如果您现在在新树中重复,则需要从该树中删除更多内容。所以:
$ git replace # List replace objects.
bb81a5af7e9203f36c3201f2736fca77ab7c8f29
$ git replace -d bb81a5af7e9203f36c3201f2736fca77ab7c8f29 # Remove previously replaced object.
现在让我们尝试从该树中删除所有提交和 blob,并再次替换:
$ git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 | grep -ve commit -e blob | git mktree
4b825dc642cb6eb9a060e54bf8d69288fbee4904
$ git replace bb81a5af7e9203f36c3201f2736fca77ab7c8f29 4b825dc642cb6eb9a060e54bf8d69288fbee4904
现在你有那个无效条目的空树。
$ git status # Check if everything is fine.
$ git show 4b825dc642cb6eb9a060e54bf8d69288fbee4904 # Re-check
$ git ls-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 --full-tree # Re-check
如果您对阶段有一些奇怪的更改,请通过以下方式重置您的存储库:
$ git reset HEAD --hard
如果出现以下错误:
HEAD is now at 5a4ed8e Some message at bb81a5af7e9203f36c3201f2736fca77ab7c8f29
执行变基并删除该提交(通过将 pick 更改为 edit):
$ git rebase -i
$ git commit -m'Fixed invalid commit.' -a
rebase in progress; onto 691f725
You are currently editing a commit while rebasing branch 'dev' on '691f725'.
$ git rebase --continue
$ git reset --hard
$ git reset HEAD --hard
$ git reset origin/master --hard
方法5。
尝试删除和压缩包含无效对象的无效提交。
$ git rebase -i HEAD~100 # 100 commits behind HEAD, increase if required.
阅读更多:Git Tools - Rewriting History 和 How do I rebase while skipping a particular commit?
方法6。
通过以下方法识别无效的git对象进行手动删除:
-
对于未压缩的对象(*请删除前两个字符,因为 git 使用它作为目录名称):
$ find . -name 81a5af7e9203f36c3201f2736fca77ab7c8f29
-
对于压缩对象
$ find . -name \*.idx -exec cat {} \; | git show-index | grep bb81a5af7e9203f36c3201f2736fca77ab7c8f29
# Then you need to find the file manually.
$ git unpack-objects $FILE # Expand the particular file.
$ git unpack-objects < .git/objects/pack/pack-*.pack # Expand all.
见:How to unpack all objects of a git repository?
相关: