git - 如果文件结构同时在单独的分支中更改,git如何处理合并时的内容更改?
问题描述
为简单起见,我将用这个例子来描述这种情况。
我在(第 1 天)为我的项目创建了一个 git 分支,结构如下:
我立即(仍在第 1 天)将结构更改为以下内容:
与此同时(第 2 天),文件 Class1.java 和 Class2.java 已在 master 分支中由其他 prople 更改(从其他分支合并到 master)。
我的问题是,当我将分支合并回 master 时(第 3 天)...... git 会保留 master 上其他人对 Class1.java 和 Class2.java 所做的更改,或者它将替换为我的分行里有那些?
解决方案
当你运行时git merge <thing>
,Git 必须找到三个提交。
三个提交之一是您当前的提交。(您的索引和工作树应该匹配它,并且前端命令通常会强制执行此操作。在“脏”情况下git merge
运行通常是不明智的,尽管一直这样做。我建议避免使用,部分原因是。)git merge
git stash apply
git stash
当然,三个提交之一是您使用<thing>
参数命名的提交:
git merge theirbranch
选择其分支顶端的提交作为要合并的两个提交中的第二个。
第三次提交是最神奇的地方。Git 会自动找到第三次提交。Git 将此称为合并基础,它源自提交图。在某些情况下,很容易看出这是从哪里来的。
假设您的分支及其分支具有非常简单的发散结构:
o--...--o <-- yourbranch (HEAD)
/
...--o--*
\
o--...--o <-- theirbranch
这个结构的合并基础就是 commit *
。
在复杂的设置中,Git 仍然会自行找到合并基础:合并基础是要合并的两个分支提示提交的最佳共同祖先。但是,您可以在合并之前进行调查:
git merge-base --all theirbranch
会告诉你哪些提交是合并基础。理想情况下只有一个;当有两个或更多时,Git 有一个问题——Git 会解决这个问题,但是 (a) 它非常罕见,并且 (b) 它与此描述的其余部分有点混乱,所以让我们暂时忽略这个问题。:-)
只找到一个合并基础后,Git 现在执行以下操作:
git diff --find-renames base your-commit
看看你改变了什么;git diff --find-renames base their-commit
看看他们改变了什么。
也就是说,Git 运行git diff
两次,使用相同的(通用的、共享的)基本提交。
鉴于您上面描述的情况,要么您重命名了一些文件,要么他们重命名了一些文件——或者,很可能,你们俩都重命名了一些文件。该--find-renames
选项指示git diff
发现这些重命名。(在这种情况下,是您重命名了文件。)
重命名查找并不完美,但在大多数情况下,它完全符合需要。Git 会发现你们中的哪些人重命名了哪些文件。这允许 Git识别合并基础文件(应该是)folder1/src/Class1.java
与重命名的文件folder2/src/Class1.java
。Git 记得也发生了重命名。
在他们更改的差异中,Git在最终提交中folder1/src/Class1.java
使用未重命名的原始文件标识原始文件。folder1/src/Class1.java
由于这些更改来自相同的源文件,Git 现在将您的更改与其更改结合起来。它尝试将相同的更改(包括重命名)应用到基本文件。因此,Git 获取基本提交的版本folder1/src/Class1.java
,将您的更改及其更改(可能会或可能不会冲突)结合起来,并将结果放在您的索引和工作树中folder2/src/Class1.java
,并采用(单个)重命名。
如果 Git 无法用重命名的文件识别原始的基本提交文件,那么所有这些组合都会失败。所以你可以运行相同的git diff --find-renames
,也许--name-status
跳过查看实际的差异,只看匹配的内容。如果正确的事情得到匹配,git merge
就会做正确的事情。
如果正确的事情没有得到匹配,您可以尝试调整 Git 的“重命名阈值”,指定为. 该数字是 Git 的相似性指数的限制。当 Git 比较两个提交时,例如合并基础和您当前的提交,如果合并基础有文件但您的提交没有,并且您的提交有基础没有,Git 会比较两个文件的内容。然后它计算相似度指数。粗略地说,这是未更改的文件数量;--find-renames=num
d1/d2/file.ext
d3/d4/other.ext
它的相似度最高为 100%,如果文件的任何部分都没有匹配,则相似度低至 0%。默认设置是配对至少 50% 相似的文件。如果一个源匹配五个目标,只要满足阈值,Git 就会采用相似度指数最高的配对。
该git merge
命令采用相同的参数,但拼写为。-X find-renames=number
如果有多个合并基地
如果git merge-base --all
为您提供了多个合并基础,以下是 Git 处理该问题的方式:
-s recursive
(默认):Git 首先通过在合并基础上运行git merge
或多或少地合并合并基础。结果提交成为合并基础。-s resolve
:Git(显然)随机选择一个合并基础,并使用它。
其余的都是一样的,但是请注意,如果递归合并遇到合并冲突,Git 只会自己提交合并冲突。这个冲突的合并结果然后成为输入基础,这通常会导致看起来很奇怪的冲突。
推荐阅读
- javascript - 如何在Javascript中获取输入检查项目
- reactjs - Firestore 延迟在用户集合中创建新文档
- go - 需要 uint64 编译以实现 32 位架构的 Golang 程序
- regex - 你能限制正则表达式中两个捕获组之间的单词吗
- asp.net-mvc - 使用 ASP.Net Core 从一对多关联表中检索数据
- javascript - 使用正则表达式从时间戳获取日期
- javascript - 为每个问题获取 pokemon API
- python - 如何配置 pylint 以获得更高的准确性
- python - zlib 压缩输出可以避免使用某些字节值吗?
- java - 如何在android studio中将关闭按钮设置为AlertDialog框