Git应用3way错误“存储库缺少必要的blob以回退3路合并”。 [英] Git apply 3way error "repository lacks the necessary blob to fall back on 3-way merge."

查看:535
本文介绍了Git应用3way错误“存储库缺少必要的blob以回退3路合并”。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用
$ b $

 创建的Git diff --git diff --full-index --ignore-submodules> mypatch.diff 

当试图将它应用到另一个git仓库时(相同的远程分支,更高级的修订版)我在标题中遇到错误

  git apply --3way mypatch.diff 
...
错误:修补程序失败:dir / file:189
错误:存储库缺少必要的blob以回退3路合并。
错误:dir / file:补丁不适用

这发生在多个文件中。 / p>

https:// git- scm.com/docs/git-apply state


当修补程序不能干净地应用时,回退到3路如果修补程序记录它应该应用的斑点的标识,则合并,并且我们有本地可用的斑点,可能会留下工作树中的文件中的冲突标记以供用户解决。


在我的例子中,有趣的是文件(Git术语中的blob)在目标库中(甚至没有重命名),所以它们必须通过git应用程序。



注意:命令的顺序已经在过去多次运行过。

解决方案

您可能需要运行 git fetch (您可能需要调整 fetch refspecs和/或使用 - unshallow )。



发生了什么



Git需要的blob是特定版本的文件(路径名在这一点上是不相关的)。



例如,考虑这一点的补丁:

  diff --git a / fmt.py b / fmt.py 
索引2069319。 .0c8a68f 100755
--- a / fmt.py
+++ b / fmt.py
@@ -207,7 +207,8 @@ def main():

让我们看一下commit 7124b135 ... 的版本 fmt.py ,然后是其父版:

  $ git rev-parse 7124b135:fmt.py 
0c8a68f9dc05a7399d06693c0b2761fb43ed0b58
$ git rev-parse 7124b135 ^:fmt.py
2069319dae4bd87cb6e1b7c18d86ebededeb00c8

现在回头看看 index ... 一行:

  index 2069319..0c8a68f 100755 

那些斑点ID。 Git正在比较blob 2069319 ... 与blob 0c8a68f ... ,这是父提交被显示,提交本身。



如果我将这个补丁发送给你,并且你要求你的Git应用它并且它不能很好地应用,那么Git的回退到三路合并要求它找到或构建三个版本的文件:当前版本,由 2069319 和我的版本标识的版本。 p>

显然你的Git有你当前的版本,所以这里没有问题。显然它没有我的版本,所以它必须构建它。它可以构建它的方式是找到版本 2069319



您看到的抱怨是因为您的Git不能在您的存储库中查找由索引< sha1>中的 .. 左边的SHA-1 ID标识的任何内容..< ; SHA1> < mode> line。



(如果您的Git可以找到该blob,它会将其提取到临时文件,将修补程序应用到该临时文件,并因此获得我的版本;然后它将有三个版本进行三向合并。)



Git在哪里得到blob?



如果补丁是针对当前存在于仓库中的提交,您可以 git fetch from,你应该可以运行 git fetch 并获得该提交,它将获得与该提交相关的所有树和blob。



这个 git fetch 需要提交该提交。通常情况下,提交 git fetch 的所有提交都是远程的 refs / heads / * 中的提交,由 fetch = 与该特定远端关联的线路,您还没有。 1



有可能远程中保留此blob的提交不在 refs / heads / * 之下(例如,如果它是只是现在藏匿起来,或附属于过期的标签或重新分类的分支)。在这种情况下, git fetch 可能不会带来必要的blob。如果您可以在远程登录,有一种方法可以获取它:只需创建一个分支或标记,指向导致该blob的提交。 (找到这样的提交可能很难,除非你的补丁具有提交ID,那么这很容易。)然后指示你的Git从另一个Git获取该分支或标记,并且你将得到必要的blob。 / p>




1 请注意,如果您制作了浅色克隆,Git不会超越您现有的提交。你的提交在某个分界点结束,这是你的克隆变得很浅的原因。如果丢失的blob毕竟在普通分支上,但是在cutoff的下面,则需要深化您的存储库,或者使用更深的 - depth = 参数,或者在你的fetch命令中加入 - unshallow ,以便一路加深。

在浅克隆方面计算正确的深度是不可能的。 (计数是:我必须从一个分支提示挖掘多少次提交,才能到达目标提交?在我们取得这么多之前,存储库中的内容会停止,因此我们不知道它有多远是的,我们可以计算你的分支走了多远,并选择一个比这更大的数字,这肯定会加深你的存储库 - 但我们不知道这是否是正确的数字。)



可以在其他存储库中使用,但是如果您可以直接访问该存储库,则不需要必须计数,您可以创建一个指向提交的分支或标记名称。



这到底意味着什么,最简单的事情就是使用 git fetch --unshallow


I have a Git diff created with

git diff --full-index --ignore-submodules > mypatch.diff

And when trying to apply it to another git repo (same remote branch, more advanced revision) I get the error in the title

git apply --3way mypatch.diff
...
error: patch failed: dir/file:189
error: repository lacks the necessary blob to fall back on 3-way merge.
error: dir/file: patch does not apply

This happens for several files.

The docs at https://git-scm.com/docs/git-apply state

When the patch does not apply cleanly, fall back on 3-way merge if the patch records the identity of blobs it is supposed to apply to, and we have those blobs available locally, possibly leaving the conflict markers in the files in the working tree for the user to resolve.

The interesting thing in my case is that the files (blobs in Git terminology) are in the destination repository (not even renamed), so they must be found by "git apply".

NOTE: The sequence of commands has worked several times in the past.

解决方案

You probably need to run git fetch (and you may need to tweak your fetch refspecs, and/or use --unshallow).

What's happening

The blob(s) that Git needs are specific versions of the files (pathnames are irrelevant at this point).

For instance, consider this bit of patch:

diff --git a/fmt.py b/fmt.py
index 2069319..0c8a68f 100755
--- a/fmt.py
+++ b/fmt.py
@@ -207,7 +207,8 @@ def main():

Let's take a look at commit 7124b135...'s version of fmt.py, and then its parent's version:

$ git rev-parse 7124b135:fmt.py
0c8a68f9dc05a7399d06693c0b2761fb43ed0b58
$ git rev-parse 7124b135^:fmt.py
2069319dae4bd87cb6e1b7c18d86ebededeb00c8

Now look back at that index ... line:

index 2069319..0c8a68f 100755

There are those blob IDs. Git is comparing blob 2069319... against blob 0c8a68f..., which are the versions in the parent of the commit being shown, and the commit itself.

If I were to send this patch to you, and you asked your Git to apply it and it did not apply cleanly, Git's "fall back to 3-way merge" requires that it find or construct three versions of the file: your current one, the one identified by 2069319, and my version.

Clearly your Git has your current version, so there's no problem there. Clearly it does not have my version, so it must construct it. The way it can construct it is to find version 2069319.

The complaint you are seeing is because your Git cannot find, in your repository, anything identified by the SHA-1 ID on the left of the .. in the index <sha1>..<sha1> <mode> line.

(If your Git could find that blob, it would extract it to a temporary file, apply the patch to that temporary file, and hence have my version; and then it would have the three versions it needs to do a 3-way merge.)

Where will Git get that blob?

If the patch is against a commit that is currently in a repository that you can git fetch from, you should be able to run git fetch and obtain that commit, which will obtain all the trees and blobs associated with that commit.

This git fetch needs to pick up that commit. The commits that git fetch normally picks up are all the ones in refs/heads/* on the remote, as controlled by the fetch = line(s) associated with that particular remote, that you don't already have.1

It's possible that the commit(s) in the remote that retain this blob there are not under refs/heads/* (e.g., if it's only in a stash now, or attached to an outdated tag or a branch that was rebased). In this case, git fetch probably won't bring over the necessary blob. There is a way to get it if you can log in on the remote: just make a branch or tag that points to a commit that leads to the blob in question. (Finding such a commit can be hard, unless your patch has the commit ID right in it, then it's easy.) Then direct your Git to fetch that branch or tag from the other Git, and you'll get the necessary blob.


1Note that if you've made a shallow clone, Git won't proceed past your existing commits. Your commits end at some cut-off point, which is what makes your clone shallow. If the missing blob is on an ordinary branch after all, but is "below" a cutoff, you will need to deepen your repository, either with a deeper --depth= argument, or by adding --unshallow to your fetch command, so as to deepen it "all the way".

Computing the correct depth is impossible on the shallow-clone side. (The count is: "How many commits down do I have to dig from a branch tip, to get to the target commit?" What you have in your repository stops before we get that far, so we don't know how far it is. We could count how far down all of your branches go, and pick a number bigger than that, which would definitely deepen your repository—but we don't know if that's the right number.)

It is possible on the other repository, but if you have direct access to that repository, you don't have to count, you can just make a branch or tag name pointing to the commit.

What this means in the end that the easiest thing, by far, is to just use git fetch --unshallow.

这篇关于Git应用3way错误“存储库缺少必要的blob以回退3路合并”。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆