V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
codingKingKong
V2EX  ›  程序员

GIT 冲突的问题

  •  
  •   codingKingKong ·
    isCoding · 2018-09-17 15:54:06 +08:00 · 2722 次点击
    这是一个创建于 2250 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    20 条回复    2018-09-20 16:13:41 +08:00
    iSecret
        1
    iSecret  
       2018-09-17 16:35:59 +08:00
    B 分支是从 A 分支拉出来的吧?如果 A 分支有其他提交或者合并没有向 B 分支合并的话是可能会出现冲突的。
    PazuLee
        2
    PazuLee  
       2018-09-17 16:36:57 +08:00
    commit 顺序,也可能有影响
    codingKingKong
        3
    codingKingKong  
    OP
       2018-09-17 16:41:23 +08:00
    @iSecret A 是由 B 拉出来的, 在 A 开发的过程中, 队友向 B 做了 PR, 我 A 向 B 做 PR 的时候, 就冲突了, 但是我反向 BA 的时候, 就 success 了...
    codingKingKong
        4
    codingKingKong  
    OP
       2018-09-17 16:41:47 +08:00
    @PazuLee 有没有 commit 顺序对这个影响的文章可以研究一下?
    PazuLee
        5
    PazuLee  
       2018-09-17 16:46:50 +08:00
    @codingKingKong 这个还真没有,经验之谈~另外 A&B 之间有 master 分支么~如果没有的话,可以找找现在 git 比较流行的开发分支模型,应该能减少一些冲突概率吧
    msg7086
        6
    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
        7
    k19870203  
       2018-09-18 09:14:26 +08:00
    @msg7086 你说的是 rebase 吧,merge 是三方合并,解决冲突的提交也是一次提交,为啥没法追溯呢?
    msg7086
        8
    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
        9
    codingKingKong  
    OP
       2018-09-18 10:14:34 +08:00
    @PazuLee 啊, 感谢, 其实是我队友的问题, 我实际不是这样操作的~只是用 AB 做了模拟
    Eoston
        10
    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
        11
    codingKingKong  
    OP
       2018-09-18 10:20:26 +08:00
    @msg7086 啊, 我目前的做法是 feature merge into release, 产生冲突解决会写改动, 不过大部分服务是我一个人维护, 都还好, ABmerge 方向不同, 使用的算法不同这点, 会导致结果不同么? 另: 做 rebase 的时候, 你们是 feature onto release,然后再 merge 的这步, merge 方向是怎样的呢?

    PS:feature 是我自己的新功能分支, release 作为大家共同编辑的分支~
    codingKingKong
        12
    codingKingKong  
    OP
       2018-09-18 10:24:08 +08:00
    @Eoston 通过 checkout 某一个正确的提交恢复后, 强行 push 回去, 可以解决这个问题么? 如果之前的 commit 没有被覆盖的情况下.
    codingKingKong
        13
    codingKingKong  
    OP
       2018-09-18 10:26:18 +08:00
    @Eoston 啊, 成功可能是因为本地认为 dev 已经是最新的了, 队友做 A 向 dev merge 的时候, 当成了更改吧.或者如果队友使用了 source tree, 会有丢弃更改的功能, 踩过一次坑
    msg7086
        14
    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
        15
    sampeng  
       2018-09-18 16:11:15 +08:00 via iPhone
    @Eoston 版本控制…只要你们找到他 push 的点。全部给剔除掉后面的提交。就行了…重新写一遍代码?疯啦?
    codingKingKong
        16
    codingKingKong  
    OP
       2018-09-19 10:36:51 +08:00
    @msg7086 感谢回复. 我看了你的图, 你们的 tip 分支是作为什么样的角色存在的呢? 是每人在自己的 feature 开发, 然后 rebase 到 tip, tip 有更新后 rebase 完 merge tip 到自己的 feature 继续开发, 要发版时, 由 tip 创建 release 发版. 这样的一个流程么?
    msg7086
        17
    msg7086  
       2018-09-19 16:24:38 +08:00   ❤️ 1
    @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
        18
    codingKingKong  
    OP
       2018-09-20 14:24:11 +08:00
    @msg7086 我大概看懂了, 不知道你们有没有遇到这样的情况, 在 AB 都 merge 完之后, 由于排期更改, A 需求暂定不随着下次发版发出去了, 这个时候 B rebase 过来的 commit 会不会带上了 A 的 feature 呢? 如何保证的下次发版仅包含 B 的 feature 的呢?
    msg7086
        19
    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
        20
    codingKingKong  
    OP
       2018-09-20 16:13:41 +08:00
    @msg7086 啊, 好的, 谢谢~ 果然是很灵活, 了解了另外一种思路.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1292 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:01 · PVG 02:01 · LAX 10:01 · JFK 13:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.