如何处理.gitmodules历史记录中的错误?

时间:2019-05-01 20:50:08

标签: git

当我尝试将一点回购推送到新服务器时出现错误:

$ git push -f research master
Enumerating objects: 13060, done.
Counting objects: 100% (13060/13060), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3397/3397), done.
Writing objects: 100% (13060/13060), 5.59 MiB | 364.00 KiB/s, done.
Total 13060 (delta 9516), reused 13060 (delta 9516)
remote: Resolving deltas: 100% (9516/9516), done.
remote: error: bad config line 14 in blob .gitmodules
remote: error: object 4f098d01fb9671a7f5ff5f617ef89b289a8ea9bb: gitmodulesParse: could not parse gitmodules blob
remote: fatal: fsck error in pack objects
error: remote unpack failed: index-pack abnormal exit
To gitlab.research.com:proj/repo.git
 ! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'git@gitlab.research.com:proj/repo.git'
$ 

奇怪的是,我在本地运行git fsck时遇到相同的错误:

$ git fsck
Checking object directories: 100% (256/256), done.
warning in blob 4f098d01fb9671a7f5ff5f617ef89b289a8ea9bb: gitmodulesParse: could not parse gitmodules blob
Checking objects: 100% (13060/13060), done.
$ 

事实证明,.gitmodules文件中的“第14行”不在文件的当前版本中,该版本只有11行。由于存在提交的.gitmodules版本存在冲突,因此导致了问题。

我可以删除Blob并将其推送到新的仓库中吗,还是有一个我无法轻易解决的深层问题?

编辑-新信息!

给出下面@torek的出色文章,并结合Which commit has this blob?中的脚本(第一个脚本有效,但第二个脚本无效),我能够找到有问题的提交:

$ ~/.bin/git-find-object 4f098d01fb9671a7f5ff5f617ef89b289a8ea9bb
06407fd merged changes from master and stats

我的git repo只有一个分支可见:

$ git branch -v
* master e8ff018 minor

我可以检查有问题的提交:

$ git checkout 06407fd
Checking out files: 100% (321/321), done.
fatal: bad config line 14 in file /home/xv32/gits/repo/.gitmodules

$

我直接编辑了.gitmodules文件,并删除了有问题的行:

<<<<<<< HEAD
        branch = ee
=======
>>>>>>> master

我做了一个git add .gitmodules

我做了一个:

$ git commit --amend -m 'fixed conflict in .gitmodules'

OMG改变了很多东西。

然后我做了一个git状态:

$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   submodule1 (new commits)
        modified:   submodule2 (new commits)
        modified:   submodule3(new commits)

no changes added to commit (use "git add" and/or "git commit -a")

$

git fsck不再报告问题:

$ git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (15206/15206), done.

但是我仍然无法推送到远程仓库:

$ git push -f research master
Counting objects: 13245, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3395/3395), done.
Writing objects: 100% (13245/13245), 5.68 MiB | 2.81 MiB/s, done.
Total 13245 (delta 9746), reused 13180 (delta 9702)
remote: error: bad config line 14 in blob .gitmodules
remote: error: object 4f098d01fb9671a7f5ff5f617ef89b289a8ea9bb: gitmodulesParse: could not parse gitmodules blob
remote: fatal: fsck error in packed object
error: remote unpack failed: index-pack abnormal exit
To https://gitlab.research.com/repo/repo.git
 ! [remote rejected] master -> master (unpacker error)
error: failed to push some refs to 'https://gitlab.research.com/censyn-sensitive/das_decennial.git'

$

此外,当我执行git --amend时,一堆重要的事情消失了,除了对象中的坏线。

老实说,我不明白为什么我甚至遇到错误,因为错误不在树的顶部。

1 个答案:

答案 0 :(得分:2)

  

我可以删除Blob吗...

否:有一个树对象 T ,上面写着“我应该有斑点4f098d01fb9671a7f5ff5f617ef89b289a8ea9bb”。因此,您必须找到 tree 并进行处理。树 T 由某些提交对象 C 引用。由于文件为.gitmodules,因此这可能是该提交的顶级树。您可能必须找到该提交,但是:

  

导致问题出现的原因是提交的.gitmodules版本存在冲突。

... 提交,或者可能只是几个提交中的第一个提交,其中有一个树,上面写着“我应该有斑点”。换句话说,您已经找到了相关的提交。

现在的诀窍是用新的和改进的版本重写提交。新版本应该与原始版本几乎相同,不同之处在于其提交的.gitmodules(斑点)应该是正确的,而不是错误的。

一旦替换了那个提交,就必须替换该提交的一个或多个子项,因为该子项通过其哈希ID引用了错误的提交,并且新的,更正后的替换具有不同的含义。哈希ID。当然,一旦替换了这些子项,就必须替换它们的子项,依此类推,一直到任何后代分支提示提交。

理想情况下,您只需使用git rebase即可解决此问题(如phd suggested)。不幸的是,你说:

  

...发生冲突

表示第一个错误的提交本身就是合并。您无法为合并设置基础:您必须构造一个新的,更正的合并。

这到底有多难或容易取决于许多因素,例如您对Git的内部运作有多熟悉,以及错误合并的“下游”有多少个提交。如果只有少数几个,则可能需要重复合并,这次没有错误,然后手动复制剩下的一两个提交。

假设错误合并是提交X,并且它的第一个父级是提交P

...--o--P--X--1--2   <-- master (HEAD)
          /
...---o--o   <-- otherbranch

这里只有两个后续提交,因此您可以:

git checkout <hash-of-P>
git merge otherbranch

与上次相同的冲突也会发生,但是这次您可以正确地解决它们,因此.gitmodules是正确的。然后:

git cherry-pick <hash-of-1>
git cherry-pick <hash-of-2>

将在此新的替换合并上方复制提交12

          ,-X'-1'-2'  <-- HEAD
         / /
...--o--P-/-X--1--2   <-- master
         | /
         |/
...---o--o   <-- otherbranch

其中X'1'2'是新的和改进的版本。 (当选择12固定的.gitmodules中的任意一个时,您可能必须采取更正的.gitmodules来解决合并冲突;或者Git可能会看到两者变化会导致同一件事,并确定没有冲突。)

然后,您可以强制名称master来标识提交1',此后您就可以忘记曾经提交过X12存在:

...--o--P--X'-1'-2'  <-- master (HEAD)
          /
...---o--o   <-- otherbranch

现在您可以git push -f research master

替代项

除此方法外,您还可以:

  • git checkout直接合并错误(git checkout hash-of-X);
  • 编辑.gitmodules文件以对其进行修复,并git add结果;
  • 运行git commit --amend:使X'

这可能至少要容易一些,因为您不必重复其余的合并。然后,您可以重复摘樱桃。

如果在错误合并之后有很多提交,那么可以一次使用git rebase --onto来大量复制它们,而不必一次选择一次。这只能确保在这一系列的提交中没有合并。也就是说,上述几种图形都可以正常工作,但是:

                   3--4--5
                  /       \
...--o--P--X--1--2------6--7--8   <-- master (HEAD)
          /
...---o--o   <-- otherbranch

可能不会,因为提交7是合并:git rebase将完全删除它,并尝试在X'或{{1 }}。 可以可以,取决于您的需求。

最新版本的Git具有1-2-3-4-5-6-8标志,它将重新执行合并(在复制其他提交时,则提交1-2-6-3-4-5-8)。您可以在这种情况下使用它。

或者,最后,您可以将--rebase-mergesgit cherry-pick结合使用。如果您在坏的一个和/或许多分支和合并操作的下游“下游”提交了成千上万的提交,那将是最合适的。否则,您不妨坚持修复错误的合并,然后重新定基或挑选剩余的提交。