在我们托管的一些问题之后,我们决定将我们的Git存储库移动到GitHub。所以我克隆了存储库并尝试将其推送到GitHub。但是,我偶然发现了一些我们以前从未遇到过的错误:
C:\repositories\appName [master]> git push -u origin master
Counting objects: 54483, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (18430/18430), done.
error: object 9eac1e639bbf890f4d1d52e04c32d72d5c29082e:contains duplicate file entries
fatal: Error in object
fatal: sha1 file '<stdout>' write error: Invalid arguments
error: failed to push some refs to 'ssh://git@github.com/User/Project.git'
当我运行fsck
时:
C:\repositories\appName [master]> git fsck --full
Checking object directories: 100% (256/256), done.
error in tree 0db4b3eb0e0b9e3ee41842229cdc058f01cd9c32: contains duplicate file entries
error in tree 9eac1e639bbf890f4d1d52e04c32d72d5c29082e: contains duplicate file entries
error in tree 4ff6e424d9dd2e3a004d62c56f99e798ac27e7bf: contains duplicate file entries
Checking objects: 100% (54581/54581), done.
当我使用错误的SHA1运行ls-tree
时:
C:\repositories\appName [master]> git ls-tree 9eac1e639bbf890f4d1d52e04c32d72d5c29082e
160000 commit 5de114491070a2ccc58ae8c8ac4bef61522e0667 MenuBundle
040000 tree 9965718812098a5680e74d3abbfa26f527d4e1fb MenuBundle
我尝试了StackOverflow question已经给出的所有答案,但没有取得任何成功。有什么方法可以阻止这个存储库及其历史注定失败吗?
答案 0 :(得分:8)
方法1。
首先执行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用户。请在开始之前进行备份。以下步骤无法保证解决方案,并且可能会使情况变得更糟,因此为了您自己的风险或教育目的而这样做。
方法2。
使用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
方法3。
当您知道哪个文件/目录条目重复时,您可以尝试删除该文件并在以后重新创建它。例如:
$ 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.
了解更多:
方法4。
检查您的提交是否有无效条目。
让我们再次检查我们的树。
$ 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
执行rebase并删除该提交(将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?
相关:
答案 1 :(得分:2)
注意:Git 2.1将为git replace
添加两个选项,这在修改git仓库中的损坏条目时非常有用:
commit 4e4b125 Christian Couder (chriscool
)
- 编辑
以交互方式编辑对象的内容。
<object>
的现有内容被打印到临时文件中,在文件上启动编辑器,并解析结果以创建与<object>
相同类型的新对象。
然后创建替换引用以用新创建的对象替换<object>
Seegit-var
有关如何选择编辑器的详细信息。
commit 2deda62 Jeff King (peff
):
“
git replace --edit
”的目的之一是帮助用户修复格式错误或损坏的对象。
通常我们用“ls-tree
”打印树,这比原始二进制数据更容易使用。
然而,某些形式的腐败破坏了树木行走者,在这种情况下,我们的漂亮打印失败,使“--edit
”对用户无用。
此补丁引入了“
--raw
”选项,可让您在这些实例中编辑二进制数据。
知道如何使用Jeff调试Git(如in this case),看到这个选项我并不感到惊讶。
答案 2 :(得分:1)
我遇到的唯一解决方案是使用git-replace和git-mktree。它不是世界上最简单的解决方案,但确实有效。
请参阅此链接以获取参考指南。