Visual Studio 2015 GIT 是不是使用 3 路合并?

Posted

技术标签:

【中文标题】Visual Studio 2015 GIT 是不是使用 3 路合并?【英文标题】:Does Visual Studio 2015 GIT use 3-way merge?Visual Studio 2015 GIT 是否使用 3 路合并? 【发布时间】:2021-03-29 00:56:31 【问题描述】:

当我使用 Visual Studio 2015 的合并工具来修复冲突时,它的性能似乎比我在 GIT 的命令行中使用 P4Merge 时更差(几乎没有发现任何冲突)。

这是因为工具本身吗? Visual Studio 2015 的合并/差异工具是否为 GIT 提供 3 路合并?

【问题讨论】:

是的。提供一些背景信息,例如 P4Merge 正确处理时遇到的麻烦,可能会为您的问题提供一些说明。 (也许这是一个行尾问题。)或者也许 P4Merge 比 Visual Studio 的更好。 嗯,我真的只是在网络上的某个地方寻找可以证实我的假设的来源(使用 GIT 时 Visual Studio 会进行什么样的合并)。我还没找到。 这是一个三向合并...这确实是唯一的合并! 不,据我了解,TFS 将进行 2 路合并。尝试谷歌搜索它。这就是为什么 GIT 的冲突通常比 TFS 少得多。 您进一步讨论了当您发生冲突时启动的冲突解决工具(VS 或 P4Merge)。这些工具独立于创建它们的版本控制系统。 【参考方案1】:

TL;DR:Visual Studio 在合并 Git 存储库和尝试解决出现的冲突时进行三向合并。目前尚不清楚为什么 VS 在解决该冲突时会不如 P4Merge,但在不知道其他任何事情的情况下,我怀疑 P4Merge 比 inconsistent line ending configurations 更好。

合并过程有两个阶段:第一,执行合并并生成包含来自两个分支的新更改和(可能)冲突的组合树,第二,冲突解决阶段。

在 Visual Studio 中,第一阶段是常规的 git 合并,这确实是三路合并。找到“合并基础”,这是两个分支中都存在的最后一个提交;这是您的两个分支最后一次合并,或者是从另一个分支创建一个分支的点。

然后通过确定每个分支中哪些文件已更改,将它们与共同祖先进行比较,在树级别执行三路合并。如果 one 分支中的文件已更改,则该分支的更改将包含在新树中。如果一个文件在 both 分支中发生了变化,那么我们需要在 file 级别进行三路合并,这非常相似,并且将每个分支中的文件与它们的文件进行比较共同祖先。现在,如果文件的任何区域在 one 分支中相对于共同祖先发生了更改,那么我们将在合并文件中包含该更改的区域。但是如果两个分支都改变了同一个区域,那么就会产生冲突。

Git 会在工作目录中生成一个带有冲突标记的文件,但它也会记录这两个文件及其共同祖先,以便您可以使用合并工具(如 Visual Studio 或 P4Merge)。

(请注意,当您使用 Visual Studio 执行合并时,它使用 libgit2 库,尽管 it produces the same results 作为 Git 本身。)

一旦发生合并冲突,您的合并工具可以获取这三个文件并为您提供解决冲突的图形体验。通常,每个工具的第一步是尝试再次进行文件级合并,并将创建一个新的“结果”文件(通常显示在三个窗格的中间窗格中,两侧各有两个分支,或不太常见的高于或低于两个分支文件)。

此结果通常会包含自动合并的所有未重叠区域,并且 UI 通常会提示您解决无法自动合并的重叠区域。一般来说,我的经验是这里没有很多差异,但肯定会有变化。特别是:

一些工具可能更积极地将彼此靠近的小冲突连接在一起,这可能会产生更少但更大的冲突,可能更容易解决 - 例如,如果你有几个冲突是一个 -每条线最好将它们压缩成一个更大的冲突。

一些工具可能会进行编码翻译,这样您就可以正确地合并共同祖先中的 UTF-8、一个分支中的 UTF-16 和另一个分支中的 Latin1 的文件,并在一个分支中获得智能输出这些编码中的一种(甚至完全不同的编码)。

某些工具可能会忽略空格更改。我有一种预感,这可能是您看到 Visual Studio 和 P4Merge 之间差异的地方;众所周知,行尾配置很难在 Windows Git 客户端的整个团队中进行设置。一个简单地忽略行尾差异的合并工具可能会产生一个比没有的更好的体验。

可以甚至使用了解文档结构的工具:例如,合并两个 XML 文件通常不会尝试了解 XML 的结构,但 you could use a tool that understood XML 可以避免诸如空格更改之类的内容实际上与文件的含义无关。

【讨论】:

出于好奇,TFS 也使用 3-way merge 吗? @Mathias 它适用于可以直接合并的分支(例如,具有父/子关系的分支)。但是如果你尝试从一个孙分支合并,那么它不会记录一个合并基础,所以它会做一个“无基础”合并,这是一个与空基础的三路合并,基本上没有用。 当时 TFS 能产生比 GIT 更多的冲突真是太奇怪了。有什么想法吗? 您是否启用了自动合并?先前版本的 TFVC 甚至没有尝试自动合并,因此当显示冲突页面时,您必须单击“全部自动合并”按钮。 (较新的版本默认执行此操作。) 也有可能只是冲突不是很好。 :P

以上是关于Visual Studio 2015 GIT 是不是使用 3 路合并?的主要内容,如果未能解决你的问题,请参考以下文章

在 Visual Studio 2015 “从 git 提取数据时”出现错误

带有 Visual Studio 2015 的 Git 切换分支导致更改

Visual Studio 2015,使用 GIT 扩展和数据库项目 .dbmdl 文件

Visual Studio 2015 - Git Fetch 返回远程服务器返回错误:(401)未经授权

在 Visual Studio 2015 git repo 中切换分支时发生错误,无法 rmdir 访问被拒绝

Visual Studio 2015 Express for Desktop 是不是支持 JIT 调试?