我最近发现了git checkout --conflict=merge -- (file) 命令,在本地分支上工作得很好,但是一旦它被推送到远程,这个命令就不能再恢复合并标志了。
有没有一种方法可以强制Git将文件重新标记为冲突,以便人们可以使用正常的合并工具来解决它们?
当前提交,也称为HEAD或HEAD
,非常简单。 (我喜欢在计算机文本布局中使用HEAD
来指代Git名称HEAD
。您还可以在Git版本1.8.5或更高版本中使用@
。此特殊名称引用当前分支(如果有当前分支),然后当前分支定位该分支的尖端提交,即当前提交。或者,在“分离的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
则会显示秘密。这通常只会在发生冲突的合并期间显示。秘密在于每个文件可以在索引中最多出现三次,在编号为阶段插槽的位置上。插槽零是正常的、日常的插槽:$ git ls-files --stage
[snip]
100644 d8d18736e74c7a5f61d794770a2dd94786501d12 0 Makefile
100644 046dcab7645305cbf4b94adef54a859234ac3caa 0 README
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 lib/__init__.py
所有零值列表示这些文件都在第零个槽位中。
然而,在冲突合并期间,README
或其他名称可能会出现在1、2和3号槽位中。在这种情况下,Git知道存在合并冲突。第1个槽位保存文件的合并基础版本,第2个槽位保存HEAD
或--ours
版本,第3个槽位保存MERGE_HEAD
或--theirs
版本,这些版本均属于相同的文件。(根据定义,此时槽位0为空。)
这些槽位中有几个可能是空的。(我曾说过最多只能有一个空槽位,但我错了:在重命名/重命名或重命名/删除冲突中,我们实际上可以看到多个空槽位。)空槽位表示在合并的三个输入之一或多个输入中没有任何文件使用该名称。然而,任何高编号条目的存在都表明存在合并冲突。
正如您所见,您的工作是解决这些冲突。命名文件的工作树版本通常包含Git在此时的最佳合并尝试,但由于Git无法解决冲突,工作树版本中有冲突标记。解决冲突后,您应像往常一样在路径上运行git add
(如果要删除文件,则运行git rm
)。这会清除高级别槽位,并将工作树文件复制到槽0中,除非该文件真的被删除。现在,冲突已经解决。
如果您正在进行合并,尚未提交结果,并且已编辑或甚至解决了某个文件,但希望将其恢复为原始未合并状态,则可以使用:
git checkout -m -- <path>
=<style>
来指定冲突风格:merge
或diff3
(我更喜欢diff3
,因为它包括文件的合并基础版本的文本)。这将移除阶段零的条目(如果你有的话),并恢复更高阶段的冲突条目。这种特殊形式的git checkout
需要在索引中保留原始未合并的条目。git ls-files --stage
显示任何不为零阶段的条目,则不能进行新的提交。
事实上,在那之前就已经失效了。提交后,恢复冲突的能力将永久清除所有高阶段的索引条目。但你无法推送索引,也无法推送文件,只能推送提交。这意味着要推送部分合并(让其他人来处理),你必须解决冲突并提交。现在它已经不在进展中,也无法再次进展了。... 一旦推送到远程仓库,此 [
git checkout -m
] 命令将不再有效。
HEAD
和MERGE_HEAD
两个提交的ID,这意味着合并基础的ID),甚至未跟踪和/或被忽略的文件(类似于git stash
)保存到特殊的提交或一组不属于分支引用的提交中。这个提交,或这些提交,然后可以从一个仓库转移到另一个仓库。构建这样一个工具所需的所有组件都已经存在(因为git ls-files --stage
和git update-index
都存在)。但编写这个工具对可能会像git stash
脚本一样复杂。
git checkout -m
]命令。即使在切换分支后,我也可以使用该命令来恢复冲突。只有在推送到远程存储库后,该命令才停止工作。 - Melangeaddictgit checkout -m
命令将一个提交与另一个提交合并。效果与运行git merge
命令大致相同,只是没有记录合并的信息...所以有点像git merge --squash
,但也不完全一样。最终类似于运行git read-tree -m
命令。(Git 就是这样有趣。 :-)) - torek