树包含重复的文件条目

use*_*257 28 git object duplicates

在我们托管的一些问题之后,我们决定将我们的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'
Run Code Online (Sandbox Code Playgroud)

当我跑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.
Run Code Online (Sandbox Code Playgroud)

当我ls-tree使用坏SHA1 运行时:

C:\repositories\appName [master]> git ls-tree 9eac1e639bbf890f4d1d52e04c32d72d5c29082e
160000 commit 5de114491070a2ccc58ae8c8ac4bef61522e0667  MenuBundle
040000 tree 9965718812098a5680e74d3abbfa26f527d4e1fb    MenuBundle
Run Code Online (Sandbox Code Playgroud)

我尝试了StackOverflow问题上已经给出的所有答案,但没有取得任何成功.有什么方法可以阻止这个存储库及其历史注定失败?

ken*_*orb 8

方法1.

做第git fsck一个.

$ git fsck --full
error in tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29: contains duplicate file entries
Run Code Online (Sandbox Code Playgroud)

如果这不能解决问题,那你就麻烦了.您可以忽略该问题,从备份还原存储库,或将文件移动到新存储库中.如果您在将repo推送到github时遇到问题,请尝试将存储库更改为不同的存储库或检查:无法推送到GitHub错误:pack-objects死于信号13并且无法将新的git存储库推送到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
Run Code Online (Sandbox Code Playgroud)

如您所见,它包含重复的文件条目(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
Run Code Online (Sandbox Code Playgroud)

同样,您可以看到重复的文件条目(commerce_coupon_per_user)!

您可以尝试使用git show每个列出的blob并检查每个文件的内容.

然后继续在不同的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
Run Code Online (Sandbox Code Playgroud)

如果这样做无效,您可以通过以下方式撤消更改:

$ git replace -d NEWTREE4b825dc642cb6eb9a060e54bf8d69288fbee4904
Run Code Online (Sandbox Code Playgroud)

方法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.
Run Code Online (Sandbox Code Playgroud)

阅读更多:


方法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
Run Code Online (Sandbox Code Playgroud)

似乎上面的提交无效,让我们使用以下命令之一扫描我们的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
Run Code Online (Sandbox Code Playgroud)

在这种特殊情况下,我们的提交指向坏对象,因为它是作为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
Run Code Online (Sandbox Code Playgroud)

注意:旧对象仍应抛出重复的文件条目,但如果您现在在新树中重复,则需要从该树中删除更多内容.所以:

$ git replace # List replace objects.
bb81a5af7e9203f36c3201f2736fca77ab7c8f29
$ git replace -d bb81a5af7e9203f36c3201f2736fca77ab7c8f29 # Remove previously replaced object.
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试从该树中删除所有提交和blob,然后再次替换:

$ git ls-tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29 | grep -ve commit -e blob | git mktree
4b825dc642cb6eb9a060e54bf8d69288fbee4904
$ git replace bb81a5af7e9203f36c3201f2736fca77ab7c8f29 4b825dc642cb6eb9a060e54bf8d69288fbee4904
Run Code Online (Sandbox Code Playgroud)

现在,您有无效条目的空树.

$ git status # Check if everything is fine.
$ git show 4b825dc642cb6eb9a060e54bf8d69288fbee4904 # Re-check
$ git ls-tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 --full-tree # Re-check
Run Code Online (Sandbox Code Playgroud)

如果您对舞台有一些奇怪的更改,请通过以下方式重置您的存储库:

$ git reset HEAD --hard
Run Code Online (Sandbox Code Playgroud)

如果您有以下错误:

HEAD is now at 5a4ed8e Some message at bb81a5af7e9203f36c3201f2736fca77ab7c8f29
Run Code Online (Sandbox Code Playgroud)

执行rebase并删除该提交(通过更改pickedit):

$ 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
Run Code Online (Sandbox Code Playgroud)

方法5.

尝试删除并压缩包含无效对象的无效提交.

$ git rebase -i HEAD~100 # 100 commits behind HEAD, increase if required.
Run Code Online (Sandbox Code Playgroud)

阅读更多:Git工具 - 重写历史记录以及如何在跳过特定提交时重新绑定?


方法6.

通过以下方法识别无效的git对象以进行手动删除:

  • 对于未压缩的对象(*请删除前两个字符,因为git将其用于目录名称):

    $ find . -name 81a5af7e9203f36c3201f2736fca77ab7c8f29
    
    Run Code Online (Sandbox Code Playgroud)
  • 用于压缩对象

    $ 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.
    
    Run Code Online (Sandbox Code Playgroud)

请参阅:如何解压缩git存储库的所有对象?


有关:


小智 2

我遇到的唯一解决方案是使用 git-replace 和 git-mktree。这不是世界上最简单的解决方案,但它确实有效。

查看此链接以获取参考指南。

git 树包含重复的文件条目


归档时间:

查看次数:

6363 次

最近记录:

11 年,3 月 前