为什么在合并第 2 级后将第 3 级分支合并到 master 时会发生冲突
Why I'm getting conflicts when I merge the 3rd level branch to master after merging the 2 second level
当我在工作中遇到这种情况时,我总是遇到问题
0 <- 1 <- 2 <----------- 9 <--- master
\ /
3 <- 4 <- 5 <------ Feature/A
\
6 <- 7 <- 8 <-- HEAD=Feature/B
所以我们有一个 master,我们从 master 创建了新的 feature/A
后来我们从 feature/A
创建了另一个特征 feature/B
现在 Feature/A 在 5
合并到 master
我们也需要合并 Feature/B 来掌握,但是我们无缘无故地遇到了很多冲突。
请问是什么原因造成的,我该如何避免?
编辑
将B合并到master I中运行
git merge master
从 Feature B
我 运行 git merge-base --all HEAD master
结果是 2
这是 releae/1.14.1,您可以在下一张图表中更详细地看到它
我的图形日志命令:
git log --graph --oneline master feature/member feature/fund-test
因为feature/member是特征A
feature/fund-test 是特征 B
releae/1.14.1 是 feature/A 开始的地方,即 2
7640e46aa 是 9
|\
| * c354b9142 update claims upon registering.
|/
* 7640e46aa Merge branch 'feature/members' into 'master'
|\
| * 43ea27cb2 Feature/Members
|/
| * ef276ed89 (HEAD -> fund-test, origin/fund-test) Merge branch 'minor-changes-fundraising-v3.1' into 'feature/fundraising-3.1'
| |\
| | * 952cfe3a9 (origin/add-missing-changes) Add changes resolve by git.
| |/
| * e924e1fc3 fixed changelog
| * 1d6eadffe Merge remote-tracking branch 'origin/feature/members' into feature/fundraising-3.1
| |\
| | * 76d3f1aa4 (origin/feature/members, feature/members) Update data service comments
| | * 5b8cdf931 Update NuGet packages
| | * cf978c86b Merge branch 'master' into feature/members
| | |\
| |_|/
|/| |
* | | 2754d5127 Merge branch 'releae/1.14.1' into 'master'
|\ \ \
| * | | d67a38076 Update changelogs
|/ / /
| | * aa16154e4 Merge branch 'remove/context' into 'feature/members'
编辑:鉴于哈希 ID 7640e46aa
是您绘制为 9
的提交,我们查看 7640e46aa
的两个父项。他们是:
43ea27cb2 Feature/Members
(这是 第二个 父级,因为 git log --graph
总是把那个画在右边)并且:
2754d5127 Merge branch 'releae/1.14.1' into 'master'
(这是 第一个 父级,就在您称为 2
的提交下方。所以图表的第一行是正确的。但是,提交 43ea27cb2 Feature/Members
不 对应于您称为 5
的提交:它是一个独立的提交,以 2754d5127
作为其(单个)父级。也就是说,而不是:
0 <- 1 <- 2 <----------- 9 <--- master
\ /
3 <- 4 <- 5 <------ Feature/A
\
6 <- 7 <- 8 <-- HEAD=Feature/B
我们得到的是这样的:
0--1--2------------9 <-- master
\___ /
\ `---345 <-- Feature/Members
\
3--4--5 <-- Feature/A
\
6--7--8 <-- Feature/B
其中提交 345
是 运行 宁 git checkout -b Feature/Members <hash-of-2> && git merge --squash Feature/A
而不是 git checkout master && git merge Feature/A
的结果。然后将压缩在一起的 345
与常规合并合并到 master
,并删除分支名称 Feature/Members
(注意大写)。因此,该分支与 feature/members
(注意小写)分支无关,并且提交 3
、4
和 5
与提交 345
.[= 冲突65=]
你现在的主要选择是合并(尽可能使用真正的合并!)和解决冲突,或者使用 git rebase --onto
将提交 6-7-8
复制到三个新提交.使用 rebase 的好处是工作会更容易。缺点是 6-7-8
的三个替换提交必须用作当前具有这三个提交的 每个克隆 中的替换。
(线下原答案)
假设您的绘图是准确的,提交 8
和 9
的合并基础是 5
。为了验证这一点,运行:
git merge-base --all HEAD master
这应该只打印那个提交的哈希 ID。
将出现冲突 if/when 从 5
到 8
的差异中出现的变化与从 5
到 8
的差异中出现的变化重叠或邻接9
。也就是说,已经获得合并基的哈希ID(单数),运行:
git diff --find-renames <hash-of-5> feature/B > /tmp/ours
git diff --find-renames <hash-of-5> master > /tmp/theirs
比较差异列表以查看可能发生冲突的位置。
由于 9
处的合并据说是由 git checkout master && git merge --no-ff feature/A
完成的,并且 之间没有提交 9
及其第一个父级 2
,此处显示的从 5
到 9
的更改应该正是沿 3-4-5
所做的更改小路。这意味着在 /tmp/theirs
中从 5
到 9
的差异应该是 空 。空 diff 不会产生冲突(非空 或 空 diff),因此:
git checkout master && git merge feature/B
或:
git checkout feature/B && git merge master
应该没有冲突。因此我得出结论,这里至少有一个假设是错误的。最有可能出错的是假设您的简化提交图绘制是正确的。考虑编辑您的问题以包含 git log --graph --oneline master feature/A feature/B
的输出(如有必要,可能会删除一些提交消息的主题行)。然而,另一种可能性是简化图形绘制 是 正确的,但是 9
处的合并是一个邪恶的合并:参见 Evil merges in git? 在这种情况下 /tmp/theirs
diff 将是非空的。
(我自己的猜测是提交 9
是一个 squash 合并 ,并且没有 link 回到提交 5
,所以合并基础实际上是提交 2
.)
当我在工作中遇到这种情况时,我总是遇到问题
0 <- 1 <- 2 <----------- 9 <--- master
\ /
3 <- 4 <- 5 <------ Feature/A
\
6 <- 7 <- 8 <-- HEAD=Feature/B
所以我们有一个 master,我们从 master 创建了新的 feature/A 后来我们从 feature/A
创建了另一个特征 feature/B现在 Feature/A 在 5
合并到 master我们也需要合并 Feature/B 来掌握,但是我们无缘无故地遇到了很多冲突。
请问是什么原因造成的,我该如何避免?
编辑
将B合并到master I中运行
git merge master
从 Feature B
我 运行 git merge-base --all HEAD master
结果是 2
这是 releae/1.14.1,您可以在下一张图表中更详细地看到它
我的图形日志命令:
git log --graph --oneline master feature/member feature/fund-test
因为feature/member是特征A
feature/fund-test 是特征 B
releae/1.14.1 是 feature/A 开始的地方,即 2
7640e46aa 是 9
|\
| * c354b9142 update claims upon registering.
|/
* 7640e46aa Merge branch 'feature/members' into 'master'
|\
| * 43ea27cb2 Feature/Members
|/
| * ef276ed89 (HEAD -> fund-test, origin/fund-test) Merge branch 'minor-changes-fundraising-v3.1' into 'feature/fundraising-3.1'
| |\
| | * 952cfe3a9 (origin/add-missing-changes) Add changes resolve by git.
| |/
| * e924e1fc3 fixed changelog
| * 1d6eadffe Merge remote-tracking branch 'origin/feature/members' into feature/fundraising-3.1
| |\
| | * 76d3f1aa4 (origin/feature/members, feature/members) Update data service comments
| | * 5b8cdf931 Update NuGet packages
| | * cf978c86b Merge branch 'master' into feature/members
| | |\
| |_|/
|/| |
* | | 2754d5127 Merge branch 'releae/1.14.1' into 'master'
|\ \ \
| * | | d67a38076 Update changelogs
|/ / /
| | * aa16154e4 Merge branch 'remove/context' into 'feature/members'
编辑:鉴于哈希 ID 7640e46aa
是您绘制为 9
的提交,我们查看 7640e46aa
的两个父项。他们是:
43ea27cb2 Feature/Members
(这是 第二个 父级,因为 git log --graph
总是把那个画在右边)并且:
2754d5127 Merge branch 'releae/1.14.1' into 'master'
(这是 第一个 父级,就在您称为 2
的提交下方。所以图表的第一行是正确的。但是,提交 43ea27cb2 Feature/Members
不 对应于您称为 5
的提交:它是一个独立的提交,以 2754d5127
作为其(单个)父级。也就是说,而不是:
0 <- 1 <- 2 <----------- 9 <--- master \ / 3 <- 4 <- 5 <------ Feature/A \ 6 <- 7 <- 8 <-- HEAD=Feature/B
我们得到的是这样的:
0--1--2------------9 <-- master
\___ /
\ `---345 <-- Feature/Members
\
3--4--5 <-- Feature/A
\
6--7--8 <-- Feature/B
其中提交 345
是 运行 宁 git checkout -b Feature/Members <hash-of-2> && git merge --squash Feature/A
而不是 git checkout master && git merge Feature/A
的结果。然后将压缩在一起的 345
与常规合并合并到 master
,并删除分支名称 Feature/Members
(注意大写)。因此,该分支与 feature/members
(注意小写)分支无关,并且提交 3
、4
和 5
与提交 345
.[= 冲突65=]
你现在的主要选择是合并(尽可能使用真正的合并!)和解决冲突,或者使用 git rebase --onto
将提交 6-7-8
复制到三个新提交.使用 rebase 的好处是工作会更容易。缺点是 6-7-8
的三个替换提交必须用作当前具有这三个提交的 每个克隆 中的替换。
(线下原答案)
假设您的绘图是准确的,提交 8
和 9
的合并基础是 5
。为了验证这一点,运行:
git merge-base --all HEAD master
这应该只打印那个提交的哈希 ID。
将出现冲突 if/when 从 5
到 8
的差异中出现的变化与从 5
到 8
的差异中出现的变化重叠或邻接9
。也就是说,已经获得合并基的哈希ID(单数),运行:
git diff --find-renames <hash-of-5> feature/B > /tmp/ours
git diff --find-renames <hash-of-5> master > /tmp/theirs
比较差异列表以查看可能发生冲突的位置。
由于 9
处的合并据说是由 git checkout master && git merge --no-ff feature/A
完成的,并且 之间没有提交 9
及其第一个父级 2
,此处显示的从 5
到 9
的更改应该正是沿 3-4-5
所做的更改小路。这意味着在 /tmp/theirs
中从 5
到 9
的差异应该是 空 。空 diff 不会产生冲突(非空 或 空 diff),因此:
git checkout master && git merge feature/B
或:
git checkout feature/B && git merge master
应该没有冲突。因此我得出结论,这里至少有一个假设是错误的。最有可能出错的是假设您的简化提交图绘制是正确的。考虑编辑您的问题以包含 git log --graph --oneline master feature/A feature/B
的输出(如有必要,可能会删除一些提交消息的主题行)。然而,另一种可能性是简化图形绘制 是 正确的,但是 9
处的合并是一个邪恶的合并:参见 Evil merges in git? 在这种情况下 /tmp/theirs
diff 将是非空的。
(我自己的猜测是提交 9
是一个 squash 合并 ,并且没有 link 回到提交 5
,所以合并基础实际上是提交 2
.)