Git 树包含重复的文件条目

Git 树包含重复的文件条目,git,object,duplicates,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% (184

在托管出现一些问题之后,我们决定将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'
当我使用坏SHA1运行ls tree时:

C:\repositories\appName [master]> git ls-tree 9eac1e639bbf890f4d1d52e04c32d72d5c29082e
160000 commit 5de114491070a2ccc58ae8c8ac4bef61522e0667  MenuBundle
040000 tree 9965718812098a5680e74d3abbfa26f527d4e1fb    MenuBundle

我尝试了所有已经给出的答案,但都没有成功。有什么方法可以防止这个存储库及其历史被毁灭吗?

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

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

方法1

首先执行git fsck的

$ git fsck --full
error in tree bb81a5af7e9203f36c3201f2736fca77ab7c8f29: contains duplicate file entries
如果这不能解决问题,你就有麻烦了。 您可以忽略该问题,从备份中恢复存储库,或者将文件移动到新的存储库中。如果您在将repo推入github时遇到问题,请尝试将存储库更改为其他存储库,或者选中:和


以下方法仅适用于高级git用户。请在开始之前进行备份。以下步骤并不能保证修复效果,而且可能会使情况变得更糟,因此,出于您自身的风险或教育目的,请进行修复


方法2

使用git ls树来识别重复的文件

$ 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
如您所见,它包含重复的文件条目(每个用户的商业优惠券)

$ 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
同样,您可以看到重复的文件条目(每个用户的商业优惠券)

您可以尝试对每个列出的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

当您知道哪个file/dir条目是重复的时,您可以尝试删除该文件并稍后重新创建它。例如:

$ 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子模块状态)

您可以从ls树中排除该无效对象,并通过以下方式重新创建没有该错误对象的树:

$ 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
如果您对stage有一些奇怪的更改,请通过以下方式重置存储库:

$ git reset HEAD --hard
如果出现以下错误:

HEAD is now at 5a4ed8e Some message at bb81a5af7e9203f36c3201f2736fca77ab7c8f29
执行重新基址并删除该提交(通过将
选择
更改为
编辑
):


方法5

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

$ git rebase -i HEAD~100 # 100 commits behind HEAD, increase if required.
阅读更多:和


方法6

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

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

  • 对于压缩对象

    $ 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.
    
    $find-name\*.idx-exec cat{}\|git显示索引| grep bb81a5af7e9203f36c3201f2736fca77ab7c8f29
    #然后您需要手动查找该文件。
    $git解包对象$FILE#展开特定文件。
    $git解包对象<.git/objects/pack/pack-*.pack#全部展开。
    
见:


相关的:

  • [南非]
  • [南非]
  • [南非]
  • [南非]
  • [南非]
  • [南非]
  • [南非]
  • [南非]

注意:Git 2.1将添加两个选项,在修改Git回购中损坏的条目时,这两个选项非常有用:

  • 在第二次重新打包中,使用相同的重命名为old sequence逐字覆盖现有包。此时,当前MIDX无效,因为它指的是现在丢失的包。因此,该代码希望在重新编写MIDX之后运行。但是(在此补丁之前)在新的包移动到位之前,无法编写新的MIDX。所以,我们有一个循环依赖

    这都是假设,因为目前没有代码在“()”期间安全地编写MIDX(GIT_TEST_MULTI_PACK_INDEX
”这样做是不安全的)。但是,抛开假设不谈:为什么我们需要将现有包重命名为前缀为“old-”

这种行为可以追溯到(“
git repack
:在更新与现有包相同的包时要小心。”,2006-06-25,git v1.4.1--)。主要关注的是一个新编写的包的结构与其索引不同的情况。当包名是一组对象的散列时,这通常是可能的。在此命名方案下,存储同一组对象的两个包可能在增量选择、对象定位或两者上有所不同。如果发生这种情况,则在复制新包和新索引之间的瞬间,任何此类包都将无法读取(即,根据复制顺序,索引或包将过时)

但由于(“
pack objects
:在拖车散列之后命名pack文件”,2013-12-05,Git v1.9-rc0-),这不再可能,因为pack文件不是以其逻辑内容(即对象集)命名的,而是以其内容的实际校验和命名的。
因此,这种
旧的-
行为可以安全地进行,这允许我们避免上面的循环依赖

除了避免循环依赖之外,此修补程序还使“”()简单得多,因为我们
$ git rebase -i HEAD~100 # 100 commits behind HEAD, increase if required.
$ 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.
--edit <object>
$ git repack -adb
$ git repack -adb --write-midx