我想从一个存储库中挑选多个提交到另一个。我按照 this Stack Overflow post 提供的说明进行操作:
/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3
并且发生了冲突:
Applying: commit-name-xxx
fatal: sha1 information is lacking or useless (path/to/conflicted/file).
error: could not build fake ancestor
Patch failed at 0001 commit-name-xxx
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
我试图通过运行来解决冲突:
git mergetool --tool=DiffMerge
但得到的回应是:
No files need merging
我也跑了
git status
但回应是:On branch develop
You are in the middle of an am session.
(fix conflicts and then run "git am --continue")
(use "git am --skip" to skip this patch)
(use "git am --abort" to restore the original branch)
nothing to commit, working directory clean
我不确定这里发生了什么:我的第一个命令告诉我它们是一个冲突,并且它已移至
.git/rebase-apply/patch
但git mergetool
或 git status
正在发现这个冲突。
最佳答案
TL; 博士
您的 Git 没有足够的信息将补丁转换为三向 merge 。如果您的索引中没有不完整的三向 merge ,您的 git mergetool
就没有任何内容。咬进去。您可能需要手动应用补丁。
(记住,这里的索引也叫暂存区和缓存,用来解决三路 merge 时的冲突。在不涉及三路 merge 的情况下,索引只存储你正在为下一个 git commit
建立。在冲突 merge 期间,索引存储更多文件。)
如果您 git fetch
从一个存储库(在 1
中的一个)到另一个( 2
),您可能能够 git cherry-pick
有问题的提交,如 max630 suggested in a comment .也就是说,在存储库 2 中,您可以将存储库 1 添加为远程:
git remote add <name> <path-to-repo-1>
然后
git fetch
从它就像从任何其他 Remote 一样,或者您可以使用旧的(Git 1.5 样式)git fetch <path>
从 repo-1 临时获取所有可访问对象的语法,然后通过哈希 ID 进行挑选。如果这仍然不起作用(但它会起作用),或者由于某些其他原因不方便,您将不得不手动应用补丁。考虑使用
git apply --reject
然后是手动清理。长
这个错误信息告诉我们——好吧,告诉我——发生了什么:
fatal: sha1 information is lacking or useless (path/to/conflicted/file).
您正在使用
git format-patch
和 git am
将一个补丁 1 从一个 Git 存储库传输到另一个,与人们通常使用(或过去使用)相同的方式 git format-patch
在没有其他网络连接的站点之间通过电子邮件发送补丁。当 Git 制作这样的补丁时,它会在提交本身的变更集中包含一个 index
每个文件补丁上方的行:diff --git a/Documentation/RelNotes/2.17.0.txt b/Documentation/RelNotes/2.17.0.txt
index 7001dbbf8..c828d3734 100644
如果可能的话,这条索引行提供了——至少可能是——Git 构建完整三向 merge 所需的信息。添加
--full-index
格式补丁选项使 index
线路更长:index 7001dbbf88b7ea5822eb0b798ac983505c57b3dc..c828d37345224550540a1665aaed2566d5bcb40e 100644
现在这两个哈希值明显更强大;这在某些情况下会有所帮助。但它们是什么?
这两个哈希 ID 是存储在存储库中的文件的 blob 哈希 ID——“之前”和“之后”文件的实际内容。此行后面的 diff 大块给出说明:如果您更改原始 blob(文件)中的这些行,使用这些替换行,您会将原始 blob(带有左侧哈希的内容)转换为其内容的新 blob由右侧哈希命名。
当您将此差异提供给
git apply
时,2 可能是 HEAD
中的文件不再匹配,甚至在某些部分与补丁中的“原始 blob”非常相似。在这种情况下,上下文行将不匹配和/或“before”部分不会出现在文件中的任何位置。直接应用补丁变得不可能。如果您提供了
--3way
或 -3
标志到 git apply
——和 git am
这样做——Git 现在可以使用 index
中的信息线。由于第一个散列是生成更改集的存储库中实际文件内容的 blob 散列,您自己的 Git 可以在您自己的存储库中查看是否有具有该散列 ID 的 blob。如果是这样,您已经拥有原始文件。3 Git 可以提取该文件并对其进行修补,以生成“修补后”版本。Git 现在拥有该文件的所有三个版本:基本版本,通过“之前”哈希 ID 获得,并且偶然地在您的存储库中找到; “他们的”版本,通过将补丁应用于基本版本而获得;和“我们的”版本,即当前或
HEAD
中的文件犯罪。因此,Git 现在可以将所有三个版本都填充到您的索引中,并且现在可以进行三向 merge 。另一方面,可能是
index
中的 blob 哈希 ID。行不匹配您的存储库中的任何对象。在这种情况下,您没有该文件的“之前”版本。不可能进行三向 merge 。或者,您可能有一个缩短的 blob 散列与存储库中的多个 blob 相匹配,但这种情况不太可能 4。在这种情况下,您可能拥有该文件的“之前”版本,但 Git 不确定并且不会尝试确定这些 blob 中的任何一个是否正确。在任何情况下,因为您的 Git 没有足够的信息来尝试三向 merge ,所以它不会打扰尝试,让您处于这种情况。使用
git fetch
和 git cherry-pick
毕竟,您可以获得真正的三向 merge 。历史甚至不需要相关,因为cherry-pick 强制 merge 基础成为被选择提交的父级。1这也适用于一组补丁,但 format-patch 指令表明它只是一个补丁。
2注意
git am
本质上只是一个运行 git apply
的包装器在每个补丁上,后跟 git commit
结果的。3请记住,Git 的运行假设是因为您正在向
git am
提供补丁。 ,您没有其他存储库的副本。其他人已通过电子邮件向您发送补丁。只有他们有那个存储库;你只有你的存储库。这在这里不是真的——你有两个存储库——但 Git 不知道!4机会取决于存储库中 blob 对象的数量以及缩短的哈希长度。 Git 现在有代码可以自动选择适当的缩写哈希长度,但这取决于生成差异的存储库中的对象数量,而不是接收存储库中的对象数量。如果接收存储库明显更大,则发送方可能无法提供足够长的散列。旧版本的 Git 也没有这种自动计算,默认情况下只无条件地使用 28 位散列;那可能太短了。
关于git - 解决来自 am session 的冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49689936/