我正在尝试找出一种与团队其他成员共享合并冲突的方法。我们有一些非常大的分支,合并它们会产生很多冲突。我尝试了几种不同的方法,我当前的尝试涉及将处于冲突状态的文件推送到远程仓库(将合并标记保留在文件中),然后运行一个烦人的长别名来grep浏览文件并重新创建手动合并文件(LOCAL,BASE,REMOTE)。
我最近找到了
git checkout --conflict = merge - (file)
命令,在本地分支上运行良好,但只要它被推送到远程,该命令就不再能够恢复合并标志。
有没有办法强制git将文件重新标记为冲突,以便人们可以使用普通的合并工具来解决它们?
答案 0 :(得分:4)
有没有办法强制git将文件重新标记为冲突,以便人们可以使用普通的合并工具来解决它们?
不,不管怎么说都没有编写自己的代码。 (有人应该编写一些代码,也许应该是 - 现在是时候为此设置一个工具了。但是有很多极端情况很难实现。)
这里的问题是Git中的冲突合并由存储在Git&#39> 索引中的状态表示。
退一步,让我们定义索引,以及当前提交或HEAD
,以及工作树(或工作)树,工作树和一堆类似的变种):
当前提交(也称为HEAD或HEAD
)非常简单。 (我喜欢在这样的计算机文本布局中使用HEAD
来明确表示Git名称HEAD
。您还可以在Git 1.8.5或更高版本中使用@
。特殊名称是指当前分支,如果有当前分支,则当前分支随后找到该分支的 tip commit ,即当前提交。或者,在"分离的HEAD"模式下,HEAD
直接包含当前提交的哈希ID。无论哪种方式,都命名当前提交。)
工作树非常简单,就是您工作的地方。 Git的内部数据结构保存了提交和版本化的文件副本,不适用于任何其他内容,因此Git将版本提取到普通文件中,然后您可以照常阅读和操作。
工作树还可以保存您尚未提交但不想提交的文件。这些是未跟踪的文件。 (从技术上讲,未跟踪文件是工作树中尚未包含在索引中的任何文件,但我们还没有定义索引。:-))
Git倾向于抱怨未跟踪的文件未被跟踪;您可以通过在.gitignore
文件中列出文件或路径名称模式来关闭这些投诉。请注意,向.gitignore
添加文件名不会使文件无法跟踪。如果跟踪该文件,则会对其进行跟踪。 .gitignore
条目主要是关闭投诉,当您说"添加所有文件时,Git也不会自动添加这些未跟踪的文件。
索引位于这两者之间。通常,当您首次签出提交或分支时,索引内容与HEAD
提交内容匹配,Git也会将其提取到工作树中。然后,您可以随意修改工作树,但索引将继续匹配HEAD。您必须git add
个文件将它们从工作树复制回索引。
因此,索引基本上代表您将要进行的下一次提交。运行git commit
时,Git将索引转换为新的提交(自动成为新的HEAD提交)。只有您将复制回索引的内容才会被提交,这意味着您可以通过一次git add
一些文件将更改拆分为多个提交。 (并且,您可以使用git add -p
仅添加文件的部分,而不是整个文件,以便索引版本本身位于HEAD提交版本和工作树之间版本)。
如果您从未进行任何合并,或者从未发生任何合并冲突,我们可以在此处停止并完成索引。当然,你正在进行合并,他们正在发生冲突,所以我们需要仔细观察。
索引按工作树中的路径名记录文件。如果您修改其中一些文件,并且git add
它们已准备好进行下一次提交,则会更新文件的索引版本。但是如果在冲突合并期间运行git ls-files --stage
,则会出现一个秘密。没有其他时间这通常仅在冲突的合并期间显示出来。秘诀是每个文件可以在编号为 stage slots 的三次的索引中。 Slot zero是正常的日常插槽:
$ git ls-files --stage
[snip]
100644 d8d18736e74c7a5f61d794770a2dd94786501d12 0 Makefile
100644 046dcab7645305cbf4b94adef54a859234ac3caa 0 README
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 lib/__init__.py
全零值列表示每个文件都在插槽0中。
在冲突的合并期间,README
或其他名称之一在插槽1,2和3中最多可包含三个条目。在这种情况下,Git知道存在合并冲突。插槽1保存文件的合并基本版本。插槽2包含HEAD
或--ours
版本,插槽3包含同一文件的MERGE_HEAD
或--theirs
版本。 (根据定义,时隙零在此时未被占用。)
其中一些插槽可能为空。 (我曾经说过,最多其中一个可能是空的,但我错了:通过重命名/重命名或重命名/删除冲突,我们实际上可以看到多个空插槽。)空插槽或插槽表示< em> no 文件在合并的三个输入中的一个或多个中具有该名称。但是,任何更高编号的条目的存在表明存在冲突的合并。
正如您所见,您的工作就是解决这些冲突。命名文件的工作树版本通常包含Git在此时解决合并的最佳尝试,但由于Git无法解决冲突,因此工作树版本中包含冲突标记。解决冲突后,您应该像往常一样在路径上运行git add
(如果解决方案是删除文件,则git rm
)。这会清除较高级的插槽,同时还将工作树文件复制到插槽零,除非文件被真正删除。现在冲突得到了解决。
如果您正处于合并过程中,尚未提交结果,并且已编辑或甚至已解决文件但希望将其恢复到原始的未合并状态,则可以按照您的说明使用:
git checkout -m -- <path>
(或与--conflict
相同)。您可以添加=<style>
,以便您指定冲突样式:merge
或diff3
(我更喜欢diff3
,其中包含文件合并基础版本的文本) 。如果您创建了一个零阶段,则会删除阶段零条目,并恢复较高阶段的冲突条目。这种特殊形式的git checkout
,但要求原始未合并的条目在索引中可用。
在任何情况下,都无法进行新的提交,直到所有更高级别的索引条目都得到解决。也就是说,如果git ls-files --stage
显示不阶段为零的任何条目,则您可能不会进行新的提交。
...只要它被推送到远程,这个[
git checkout -m
]命令就不再能够恢复合并标志。
事实上,在此之前很久。一旦提交,恢复冲突的能力就会消失。这将永久清除所有较高阶段的索引条目。但是你无法推送索引,也无法推送文件:你只能推送提交。这意味着要推送部分合并(让其他人处理它),您必须解决合并和提交。现在它不再进行中,不能再进行中了。
我们需要的是一个可以保存完整索引状态,工作树文件,合并状态的工具,包括两个提交HEAD
和MERGE_HEAD
的ID - 这意味着ID合并基础 - 甚至可能是未跟踪和/或忽略的文件(la git stash
)到存储在非分支引用上的特殊提交或提交集合。然后,可以将此提交或这些提交从一个存储库传输到另一个存储库。同一工具的反向版本可以恢复合并状态,索引状态和工作树。存在构建此类工具所需的所有组件(因为git ls-files --stage
和git update-index
都存在)。但是编写这个工具对会很复杂,可能至少和git stash
脚本一样困难。