正常开发中,我们会从 main->new branch feature 分支,当我的 feature 开发完毕后,origin/main 可能已经更新了很多个 commit(从其他 feature 合并而来),很可能存在冲突,此时我有两种操作方式,哪种方式更好?
这两种方式各有什么优缺点?哪种更适合企业项目的团队合作?
1
imkerberos 2022-03-27 13:58:08 +08:00
远端不用重新 approve .
|
2
unco020511 OP @imkerberos approve 肯定都需要,我们是两个同事 review 后 approve,才能进行 mr
|
3
momocraft 2022-03-27 14:03:09 +08:00
1 才有机会解决冲突后运行和测试
除非你们有足够好的自动测试 不需要手工保证 |
4
unco020511 OP @momocraft 你的意思是 1 可以在 mr 之前基于 feature 进行测试是吗?我这里简化了,实际上肯定不是直接 mr 到 main 上,一般会有个 dev,2 的话也可以 mr 之后基于 dev 测试
|
5
imkerberos 2022-03-27 14:09:12 +08:00
我的意思是 重新 approve.
|
6
unco020511 OP @imkerberos 推荐 1 是吧
|
7
EastLord 2022-03-27 14:37:20 +08:00
1
|
8
lidlesseye11 2022-03-27 14:37:40 +08:00
1
|
9
cowcomic 2022-03-27 14:53:12 +08:00
1 提交代码要保证合并的正确性和正常运行
|
10
janus77 2022-03-27 14:59:19 +08:00
对于比较大的团队和比较严格的规范,应该是远程合并,因为普通开发不应该有 write main 分支的权限。
而对于简单项目和小团队,以及实际操作上来讲,本地合并的话,解决冲突更容易,因为远程合并一般都是命令行或者 web 界面,本地可以用一些 gui ,鼠标点点就能正确合并,操作更简单。 |
11
sue0917 2022-03-27 15:00:42 +08:00 via Android
楼上在说啥😂
|
12
Macolor21 2022-03-27 15:10:32 +08:00
|
13
GeruzoniAnsasu 2022-03-27 15:20:21 +08:00 6
其实没有「远端解决冲突」一说,所有的合并和冲突解决都是在叶子节点上或者说都在 git 的「客户端」进行的。
web 界面只是自动做了一些额外的事情而已,跟你在本地用一个 GUI git 工具是一回事。 > 当我的 feature 开发完毕后,origin/main 可能已经更新了很多个 commit(从其他 feature 合并而来),很可能存在冲突 此时你 **不应该进行任何 MERGE 尝试**。 1. 首先应该在本地切换到主分支( dev/main/master ),拉取远程的状态。由于你不可能直接在这些分支上修改,所以这一步不会产生任何冲突,仅仅是快进 2. 切回到你的开发分支,把它 rebase 到主分支上,此时产生冲突,resolve ,重新 commit 。 3. 由于到目前为止你还是只修改过你的独占分支(就算有远程也是可以随便 push -f 的那个),所以不会对其他人产生任何影响。 4. push 你 rebase 过后的分支,开启或刷新 MR 之所以采用不断 rebase 分岔点的方式是因为,如果你不进行 rebase ,merge 操作时是一个三路合并,而三路合并是一个**既复杂又存在危险性** 的操作 (!!) 其实我本来想简单解释一下为什么三路合并会出问题,但在我搜索看了近一个小时文章后,我选择放弃解释: https://www.waynerv.com/posts/git-merge-intro/ https://git-repo.info/zh_cn/2020/03/something-about-git-merge/ https://actake.github.io/2021/03/21/git%E5%BF%85%E7%9F%A5%E5%BF%85%E4%BC%9A-%E5%88%86%E6%94%AF%E5%90%88%E5%B9%B6%E9%82%A3%E4%BA%9B%E4%BA%8B/ (!!) 因为这已经是我至少第 4 次搜索这个问题然后仍然没有完全搞懂了 如果采用 rebase - merge FF 的方式,合并操作等同于在对方分支上把你做过的操作重放一次,心智负担和风险要小得多。只有一个麻烦,因为是重放,当你的 commit 序列一开始就与对方冲突时,这个冲突会有传递性(对方是 A ,你第一个提交把 A 改成了 B ,后面的提交全部在用 B ;发现冲突后你决定改成 C ,那么当你 rebase 重放的时候所有后面的提交都会不断发生 B 和 C 的冲突)。但这都可以通过减少 commit 修改量和 squash 改善,相比起三路合并能由(虽然存在疏忽的)正常操作产生 **无感知的** 丢修改相比,成本显然要低得多 |
14
rickll 2022-03-27 15:24:13 +08:00
如果在本地已经有冲突的代码,为什么还要提交到远端去? 别人把这个冲突代码拉下来不是骂娘。 所有冲突都应该在本地解决。
|
15
maninfog 2022-03-27 15:27:20 +08:00
一般这种情况是 1.git fetch 2.git rebase origin/master 3. git push -f (rebase 之后 feature 分叉了所以需要 force push)
|
16
rbe 2022-03-27 15:30:06 +08:00
这两个方式没有什么本质区别呀,核心都是自己 feature 分支随便玩,自己单独开发的话 rebase 都可以,保证合入不冲突,最后 mr 到 main 都只有一个 commit 。
区别就是你在本地 editor 解决冲突还是网页端可视化工具解决冲突。大概率复杂情况下你都需要在本地解决的,网页端都不好搜索代码 |
17
Chism 2022-03-27 15:40:20 +08:00 via Android
我倾向于本地解决冲突,还能顺便测试一下是否运行正常
|
18
cyang812 2022-03-27 16:53:24 +08:00
@GeruzoniAnsasu rebase 到 main 和 merge main 有什么区别呢?
|
19
ClericPy 2022-03-27 16:54:58 +08:00
不太复杂的小项目 git flow 感觉有点复杂, Github flow 就够用了
rebase 吧, 你的基被人往前推了, 那就变基到跟线上一致提个 PR, 主线分支光溜溜一根挺好的. |
20
jessun1990 2022-03-27 17:01:37 +08:00
git rebase ,本地解决冲突,再 push 上去。
|
21
GeruzoniAnsasu 2022-03-27 17:07:09 +08:00 1
@cyang812 rebase 后分岔点在基分支的最前端,merge 的分岔点是基分支上历史中的某个点。rebase 的历史永远是线性的,merge 会织出复杂的演化网。
rebase 目标分支和本分支不对等,你基本不可能搞错(不可能试图把 main 拼到 feature 上,只会把 feature 拼到 main ) 而 merge 就可 tm 难说了,feature merge main 和 main merge feature 观感上根本没什么区别,看起来也都很合法,但形成的历史网是不同的,出问题的时候根本没人有能力搞清楚发生了啥 |
22
FrankHB 2022-03-27 17:10:12 +08:00
正常都是开发者自己解决冲突,不限制解决冲突使用的工具,测过了再提交,而不是滥用 Web 编辑器让公共分支变成不可维护的临时 patch 火葬场。
Reviewer 只需要对 diff 和 merge 结果负责,不需要对具体操作负责。 即便要用统一的 flow ,Gerrit 之类也有事后诸葛亮。 实际上 merge 不见得应该是首选项。要 merge 还是 ff-only 还是 squash ,你作为分支的 owner 应该清楚。或者你就不管,活干完了找清楚怎么处理这些问题的专人负责。 |
23
msg7086 2022-03-27 18:49:04 +08:00
你说的两点都是错的。
2 不行因为 WebUI 功能太弱,建议本地合并完做好测试再推。 1 的话做法错了,主线往分支合并用 rebase 更好。以前 git 那个坑爹的命令行默认 pull 执行 merge ,然后不懂的小白就跟着 pull 了瞎 merge 。现在新版本的 git 命令行总算是去掉了默认 merge 的行为。 |
24
jsq2627 2022-03-27 19:57:12 +08:00
尝试在团队推行过 "Require branches to be up to date before merging"
最后发现 PR 合并效率太低,一次只能合并 1 个人 PR ,合并后其他人又要 rebase master ,然后重新等 CI 。。 |
25
unco020511 OP @GeruzoniAnsasu #13,我明白了,谢谢
|
26
alanhe421 2022-03-27 22:19:22 +08:00
根本上还是在于是在 feat 分之还是 main 分支上处理冲突,肯定都会是在非 main 分支处理的。
比如我所在的团队,均是 feat owner 拉取 main 分支的,解决冲突后,再 MR 到 main.且为了 Review 体验方便,一般是在本地,当然特别小的 diff 的话,上游 WEB 也 OK |
27
codeMore 2022-03-27 23:11:46 +08:00
1 、feat 要合并前,先 rebase master 分支,本地解决完冲突后,推送到 feat
|
28
levelworm 2022-03-27 23:34:26 +08:00 via Android
我之前恰好看过几篇文章,似乎是推荐先 rebase
|
29
levelworm 2022-03-27 23:45:54 +08:00
@jsq2627 求问一下这样是否可行?
假如某 feature 需要多人共同开发,于是事先约定大家新建、改动什么文件,保证不会互相干扰,于是从 main 分出 feature_branch ,并又分成多个个人的 feature_individual_branch ,最后开发完成之后合并进 feature_branch ,如何? 如果互相之间有干扰,比如说有个配置文件多人需要共同编辑,那看来只能指认其中一人为 feature reviewer ,把这些共同的文件承担下来了。 |
30
levelworm 2022-03-27 23:47:34 +08:00
@Macolor21 #12
新手求问,如果能够让每个 feature branch 在合并之前都自动进行 rebase ,是好是坏? |
32
815979670 2022-03-28 00:44:28 +08:00
看公司,如果这个项目是你单独维护,甚至可以直接 push main 分支,能解决冲突就好。
如果是多人协作 且你不是分支管理员 的情况下 通常使用 1. 但需要注意的是,无论哪种方案,冲突都是在本地解决的,不允许在线上( web )处理。 |
33
levelworm 2022-03-28 01:33:07 +08:00
@Macolor21 也是,看来还是冲突最麻烦。那么是否应该尽量从项目架构上去避免冲突?比如说尽量避免多人修改同一个文件的情况出现?虽然未必现实。。。
|
34
darknoll 2022-03-28 06:43:14 +08:00 via Android
把 main 分支更新下,然后重新 checkout 一个新分支,把修改加进去,然后用这个新分支发送 pr
|
35
wu67 2022-03-28 09:29:05 +08:00
当然是本地处理, 远程当成存档点来用. 我个人是倾向自己处理冲突合并的, 基本没 rebase 过.
|
36
nothingistrue 2022-03-28 09:58:02 +08:00
你说的 2 ,其实就是 1 ,只不过是把解决冲突的操作从本地搬到远程而已。2 发生冲突的时候,你并不是必须用远程仓库的工具,还可以本地在 feture 解决冲突并推送之后,再重新执行 MR/PR 的合并。MR/PR 开启之后,是可以继续提交的。
如果你执行的是全 merge ,并没有 rebase 的话,2 会更省事点。 如果是用 rebase 来搞准线性历史的话,要用 1 的方式。 |
37
zhaol 2022-03-28 10:20:17 +08:00
@GeruzoniAnsasu 想问下,如果 rebase 的话,这个时候我的分支会有别人的 feature 或者 bugfix 的代码了,但是如果别人的 feature 这个版本不上,我的分支要上,怎么把别人的那部分拆出来?
|
39
stimw 2022-03-28 11:43:08 +08:00 via iPhone
冲突要在 rebase 解决,不要在 merge 时候再去解决冲突。。我一直记得这句话
|
40
cgdddd 2022-03-28 11:53:15 +08:00
我们公司要求,所有冲突必须要求本地解决,一律 request 的冲突全部打回
|
41
GeruzoniAnsasu 2022-03-28 12:08:36 +08:00 1
@zhaol 在他的 feture 合并前,应该准备好 4 个分支:1 你的 feature ,2 他的 feature ,4 有他 feature 的版本分支,4 没有他 feature 的版本分支
我们之前的实践是,有一个接受所有 feature 的分支,比如 master ,然后给每个要发布的版本建 release 分支,他先写完后合并到 master ,你写完,rebase master ,合并。此时 master 上有两个 feature ( 0-2-1 ),而 release 上还什么都没有。 像 gitlab 有 自动 cherry-pick 的功能,web 界面上点一下可以把整个 MR (比如你合并 master 那个 MR )里的所有 commit 都 cherry-pick 到另一个分支上( release )。pick 完 release 看起来像是( 0-1 ),但 1 的那些 commit 不是原始 commit ,是 cherry-pick 重新生成的。 如果 web 界面没有这个功能,就只能在本地手动 pick 一堆 commit 。不过鉴于 release 分支一般也不需要保留修改历史( master 已经有了),所以可以把 feature 的所有 commit 都 squash 成一个 pick 给 release ,这样手动也不会很麻烦 |
42
hanleisky 2022-03-28 17:33:31 +08:00
理论上是 1,但是小公司菜逼多,都是让他们推上来发 PR ,我来解决冲突然后合并
|