GIT 冲突的问题

2018-09-17 15:54:06 +08:00
 codingKingKong

刚才发生了一个问题, 我有 2 个分支, 由 A 分支向 B 分支做 PR 的时候, 报了冲突, 而我反向由 B 向 A 做的时候, 就成功了, 为什么呢?

2555 次点击
所在节点    程序员
20 条回复
iSecret
2018-09-17 16:35:59 +08:00
B 分支是从 A 分支拉出来的吧?如果 A 分支有其他提交或者合并没有向 B 分支合并的话是可能会出现冲突的。
PazuLee
2018-09-17 16:36:57 +08:00
commit 顺序,也可能有影响
codingKingKong
2018-09-17 16:41:23 +08:00
@iSecret A 是由 B 拉出来的, 在 A 开发的过程中, 队友向 B 做了 PR, 我 A 向 B 做 PR 的时候, 就冲突了, 但是我反向 BA 的时候, 就 success 了...
codingKingKong
2018-09-17 16:41:47 +08:00
@PazuLee 有没有 commit 顺序对这个影响的文章可以研究一下?
PazuLee
2018-09-17 16:46:50 +08:00
@codingKingKong 这个还真没有,经验之谈~另外 A&B 之间有 master 分支么~如果没有的话,可以找找现在 git 比较流行的开发分支模型,应该能减少一些冲突概率吧
msg7086
2018-09-18 05:14:32 +08:00
Merge 的时候,A 向 B merge 是把分叉点到 A 的更改做成补丁打到 B 上。
B 向 A merge 是反过来,把 B 的更改做成补丁打到 A 上,具体的算法实现是不一样的。

另外我们的习惯是做 rebase 后再 merge 回去。
非 clean 的 merge 会导致 conflict resolving 产生的更改被隐藏在 merge commit 里,无法追溯。
我们实际遇到过这问题,feature commits 和 merge 后的 tree 内容不同,后来发现是 merge commit 里有人做了额外的修改。

Git 你要是闭着眼睛颠来倒去尝试,看哪个能跑通就用哪个跑,那这个 repo 没过多久就得乱成炸酱面了。
k19870203
2018-09-18 09:14:26 +08:00
@msg7086 你说的是 rebase 吧,merge 是三方合并,解决冲突的提交也是一次提交,为啥没法追溯呢?
msg7086
2018-09-18 09:42:50 +08:00
@k19870203 是 3-way merge,但是 apply diff 的顺序是不一样的吧。先 apply A-O 再 apply B-O,还是反过来,可能就会影响冲突判定了。

至于解决冲突,因为解决冲突本身是包含在 Merge commit 里,实际上一般不会有人特意去写这次 Merge conflict 到底改了哪些部分,甚至都不会说这个 Merge 做过了额外的修改,所以追溯的时候就会出现一个没有修改说明的修改。可能合并前测通了,合并后崩了,然后你发现是 Merge 的时候有人改错代码了。
codingKingKong
2018-09-18 10:14:34 +08:00
@PazuLee 啊, 感谢, 其实是我队友的问题, 我实际不是这样操作的~只是用 AB 做了模拟
Eoston
2018-09-18 10:17:23 +08:00
我们每个人自己的分支都是从远端 dev 分支拉出来的,然后正常情况应该是自己的分支修改后 commit-push 到自己的分支,然后需要把 dev 分支拉一下最新修改,再把 dev merge 到自己分支,然后自己分支再 merge 到 dev 分支。。。。结果有同事把 dev 拉到本地后,自己分支修改了,但自己分支的代码比较老了,就直接把本地 dev 分支 merge 到自己分支,然后又 merge 回了 dev 分支并且 push 了。。。。不知道是如何 push 成功的。。。结果把我们之前的所有修改全部冲掉了!!!!!害的我们废了老长时间重新修改了回去……
codingKingKong
2018-09-18 10:20:26 +08:00
@msg7086 啊, 我目前的做法是 feature merge into release, 产生冲突解决会写改动, 不过大部分服务是我一个人维护, 都还好, ABmerge 方向不同, 使用的算法不同这点, 会导致结果不同么? 另: 做 rebase 的时候, 你们是 feature onto release,然后再 merge 的这步, merge 方向是怎样的呢?

PS:feature 是我自己的新功能分支, release 作为大家共同编辑的分支~
codingKingKong
2018-09-18 10:24:08 +08:00
@Eoston 通过 checkout 某一个正确的提交恢复后, 强行 push 回去, 可以解决这个问题么? 如果之前的 commit 没有被覆盖的情况下.
codingKingKong
2018-09-18 10:26:18 +08:00
@Eoston 啊, 成功可能是因为本地认为 dev 已经是最新的了, 队友做 A 向 dev merge 的时候, 当成了更改吧.或者如果队友使用了 source tree, 会有丢弃更改的功能, 踩过一次坑
msg7086
2018-09-18 10:41:56 +08:00
@codingKingKong
AB merge 方向这个我也不是很清楚,但是如果本身没冲突的话 3-way merge 完的结果应该是一样的。有冲突的情况下,可能先合并的更改会改变后续更改的参考系,所以可能会产生结果不一致。

至于项目管理的话,我们一般是一个 feature 一个分支。一旦某个 feature 定稿合并以后,其他 feature 分支需要 rebase 到 tip 上然后才能 merge。

所以我们的分支图大致是这样的:



以及之前的反面教材:



(不知道你能不能看到图。)

另外 force-push 一般是不会丢 commit 的,只要之前那个正常 push 的人重建分支就行了,很简单的。
用 Git 这种多人协作工具,一定要保证每个人都会用 Git,然后才能放进来做贡献。之前我进公司以后看到公司里十来个完全不懂 Git 怎么用的人,真的是心态爆炸。
sampeng
2018-09-18 16:11:15 +08:00
@Eoston 版本控制…只要你们找到他 push 的点。全部给剔除掉后面的提交。就行了…重新写一遍代码?疯啦?
codingKingKong
2018-09-19 10:36:51 +08:00
@msg7086 感谢回复. 我看了你的图, 你们的 tip 分支是作为什么样的角色存在的呢? 是每人在自己的 feature 开发, 然后 rebase 到 tip, tip 有更新后 rebase 完 merge tip 到自己的 feature 继续开发, 要发版时, 由 tip 创建 release 发版. 这样的一个流程么?
msg7086
2018-09-19 16:24:38 +08:00
@codingKingKong 「 tip 」指的是每个分支的顶端(或者说末端)。
rebase 到 tip 上,也就是 rebase 到 master/dev 的最新提交,然后再做 feature->master/dev 的 merge。

比如 dev 是 9/1 提交的,9/1-9/20,两个人 A 和 B 分别开发了两个不同的 feature。
A 现在要合并 A 分支,当然是没问题的。
然后 B 要合并的时候,我们要求 B 需要先 rebase 到合并完 A 的主线的最新提交,然后才允许 B 合并。
codingKingKong
2018-09-20 14:24:11 +08:00
@msg7086 我大概看懂了, 不知道你们有没有遇到这样的情况, 在 AB 都 merge 完之后, 由于排期更改, A 需求暂定不随着下次发版发出去了, 这个时候 B rebase 过来的 commit 会不会带上了 A 的 feature 呢? 如何保证的下次发版仅包含 B 的 feature 的呢?
msg7086
2018-09-20 15:26:36 +08:00
@codingKingKong 原则上我们只有决定要上线的功能才 Merge。
你想呀,因为 A 和 B 随时都跟随着 tip,所以 AB 自己的 tip 就是 dev+feature 的,只要跑通测试,任何时候都可以 Merge 进 dev。如果研究决定新版本只留 B 不留 A,那 A 就留到发布以后再 Merge 就行了。

就算 A 和 B 已经 Merge 了,想要剔出 A 当然也是可以的,两种做法。

1. 非处 x 女座:把 A 分支整个 Revert 掉,作为单个提交放在 tip 上。
Old -> Merge A -> Merge B -> Revert Merge A <- release-x.x

2. 处 x 女座:把历史记录重写掉
Old -> Merge A -> Merge B <- dev tip
首先把 dev reset hard 回 Old,然后把 B 重新 rebase 回 Old,再 Merge 回 dev,变成
Old -> Merge B <- dev tip
...\--->a1->a2->a3 <- A
然后把 A 和 dev 强推回仓库,再让每个人 fetch 一下就行了。

第二种做法要求大家都懂 Git,如果有人不会,还是用方法 1 好了。

如果用的是推荐的 Git flow 流程,也就是 master 部署,而 dev 开发的话,最差也就是重建 dev 分支,Rebase feature branch 然后重新 Merge 而已。Git 本身是很灵活的,怎么玩都行……
codingKingKong
2018-09-20 16:13:41 +08:00
@msg7086 啊, 好的, 谢谢~ 果然是很灵活, 了解了另外一种思路.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/490109

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX