git - 如何处理 .gitmodules 历史记录中的错误?
问题描述
当我尝试将一些 repo 推送到新服务器时出现错误:
$ 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.
$
原来文件中的“第 14 行”.gitmodules
不在文件的当前版本中,它只有 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'
天哪,它改变了很多东西。
然后我做了一个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
,一大堆重要的事情消失了,超出了对象中的坏线。
老实说,我不明白为什么我什至会收到错误,因为错误不在树的顶部。
解决方案
我可以只删除blob吗...
不:有一个树对象T说“我应该有 blob 4f098d01fb9671a7f5ff5f617ef89b289a8ea9bb
”。因此,您必须找到树并处理它。树T由某个提交对象C引用。由于文件是.gitmodules
,这可能是该提交的顶级树。您可能必须找到该提交,但是:
问题的结果是因为
.gitmodules
提交的版本存在冲突。
...这 是提交,或者可能只是几个提交中的第一个提交,它有一棵树,上面写着“我应该拥有 blob”。换句话说,您已经找到了有问题的提交。
现在的诀窍是用一个新的和改进的版本重写那个提交。新版本应该与原始版本几乎相同,只是它的提交.gitmodules
(一个 blob)应该是正确的,而不是不正确的。
替换该提交后,您必须替换该提交的一个或多个子项,因为子项/子项通过其哈希 ID 引用错误提交,而新的、更正的替换具有不同的哈希 ID。当然,一旦你替换了它们,你就必须替换它们的子节点,以此类推,直到任何后代分支提示提交。
理想情况下,您可以只使用git rebase
来解决此问题(如phd 建议的那样)。不幸的是,你说:
...发生了冲突
这意味着第一个错误提交本身就是一个合并。您不能对合并进行变基:您必须改为构造一个新的、更正的合并。
这究竟有多难或多容易取决于很多事情,例如您对 Git 内部工作的熟悉程度以及错误合并的“下游”有多少提交。如果只有几个,您可能只想重复合并,这次没有错误,然后手动复制一两个剩余的提交。
假设错误的合并是 commit X
,并且它的第一个父级是 commit 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>
将复制提交1
并2
在这个新的替换合并之上:
,-X'-1'-2' <-- HEAD
/ /
...--o--P-/-X--1--2 <-- master
| /
|/
...---o--o <-- otherbranch
其中X'
、1'
和2'
是新的和改进的版本。(您可能必须在挑选其中任何一个1
或2
fixed时修复合并冲突,方法.gitmodules
是采用更正的.gitmodules
;或者 Git 可能会看到这两个更改导致相同的事情,并决定不存在冲突。)
然后,您可以强制使用名称master
来标识提交1'
,之后您可以忘记 commits X
、1
和2
曾经存在过:
...--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
可能不会,因为 commit7
是一个合并:git rebase
将完全删除它并尝试在其顶部创建一个新X'
链1-2-3-4-5-6-8
or 1-2-6-3-4-5-8
。这可能没问题,具体取决于您的需求。
最新版本的 Git 有一个--rebase-merges
标志,它将重新执行合并(同时复制其他提交 a la git cherry-pick
)。您可以在这种情况下使用它。
或者,最后,您可以使用git replace
与 结合使用git filter-branch
。如果您有数以万计的“下游”提交和/或下游的许多分支和合并操作,这是最合适的。否则,您不妨坚持修复错误的合并,然后重新设置或挑选剩余的提交。
推荐阅读
- javascript - 如何在 JavaScript 中动态更改 setTimeout (AOP)?
- wordpress - WordPress 中的 Bigcommerce 插件产品同步问题
- javascript - 规范化对象数组中的数据 (JavaScript)
- applescript - 如何使用 AppleScript 和 Numbers 从我的联系人组名称制作弹出菜单?
- c# - 更新 Gridview 中的行不保存到我的数据库
- python - 在不加倍索引的情况下连接数据帧
- woocommerce - woocommerce_template_single_add_to_cart 不工作
- ionic-framework - 我们可以在 ionic4 中使用 queryParams 吗?
- angular - angular6应用程序中的tinyMCE没有使字体变粗
- wpf - 如何将绑定结果赋给DynamicResource的ResourceKey?