Toggle navigation
首页
发现
Ask
User
登 录
注 册
merge
rebase
合并
无意义
rebase 还是 merge?
发布于 2021-09-18 11:01:05
大家在项目里合并代码是用 rebase 还是 merge ? 两个远程分支合并,用 merge 会产生一个无意义的提交,次数多了分支线就很乱。
Questioner
wiirhan
Viewed
22
76
个回答
dcalsky
2021-09-18 11:01:31
永远 rebase
dcalsky
21
2021-09-18 11:02:43
@dcalsky sub-branches rebase on master, master merges sub-branches. 差不多是这样。
lingxi27
2021-09-18 11:08:34
rebase +1
wiirhan
2021-09-18 11:19:20
@dcalsky 远程分支咋办?假如我有两个远程分支:master 、dev 。master 作为主分支,dev 作为开发分支。在项目迭代中,master 分支可能会存在 bug 修复,这个 bug 修复完成后需要同步到 dev 分支。一个迭代结束后,dev 的代码需要合并到 master 分支。我现在对个人分支合并到远程分支采用的 rebase,两个远程分支的合并采用的是 merge 。现在纠结的是两个远程分支的合并,每次合并都会产生不必要的提交,如果 bug 修复次数很多,那分支就会显得很乱😂😂😂。
bjfane
2021-09-18 11:19:33
教程都是用 merge 的多,一般都写不能真实的反映“历史”,小项目随意。大项目的话 2 楼基本上是正解。
“历史是什么” :
<img src = 'https://i.bmp.ovh/imgs/2021/09/13b50db1bb1ef78f.png' />
zjsxwc
1
2021-09-18 11:25:55
merge 稳一点,虽然会多一次提交记录
zjsxwc
2021-09-18 11:27:09
同意 4 楼说的,自己有把握的两个分支用 rebase,对不熟悉的分支 merge
konakona
2021-09-18 11:42:15
merge,因为 no-ff 后只带一条记录。
因为团队开发需要用一些 git 的 flow (任意),为了追述 MR 是 hotfix 还是 feature 、release 等,用 merge no-ff 。
peterswan
1
2021-09-18 11:46:22
个人开发和本地分支喜欢 rebase,涉及到远程多人开发的分支只能用 merge,rebase 会弄的协同困难。
Pipecraft
4
2021-09-18 11:48:39
一律采用 squash merge 。github PR 也只用 /允许 squash merge 。
太多的小的提交,或反复的修改后提交,会使历史记录很乱。合并成一个 squash merge,既简洁又能看到一个 feature merge commit 里的多次提交的记录。
尽可能在 Github 上面先创建 PR,再合并。
monkeyWie
2021-09-18 11:53:06
同意 2L
wellsc
2021-09-18 12:16:28
统一比选择难
weiwenhao
2021-09-18 12:18:53
说一次去年的线上的故障。
开发了 a 功能在 9 月 15 号(cimmit 在 9 月 15 号,测试了一周,9 月 22 号上线(合到 master)
修复了 b bug 在 9 月 17 号,当天上线。(合到 master)
9 月 22 号发版遇到 bug 需要回退。因此新的故障是 15 号提交的,所以此时需要回退到 15 号之前的 master 分支才能修复, 所以导致 17 号的修复分支没了( 15 号到 22 号其实不止 17 号一个功能没了,7,8 个 feature/或者 fix 都没了)。
dilu
2021-09-18 12:21:53
要 rebase 就全部 rebase,要 merge 就全部 merge
有人 rebase 有人 merge 才最伤
weiwenhao
2021-09-18 12:23:47
老大一开始就跟我说过要用 rebse 或者 git reset --soft,但是我没在乎,毕竟我看 廖雪峰阮一峰的教程都没说 rebase.. 出了故障才学会我可真是亏了。
plko345
2021-09-18 12:29:10
@weiwenhao rebase 能解决这个问题吗?只 reset 15 号的可行吗?
karott7
2021-09-18 12:34:05
@weiwenhao 你这种情况可以因检出一个分支,然后把主分支回退,再把 17 好发布的那些更改用 cherry-pick 命令放到主分支上,发布主分支
weiwenhao
2021-09-18 12:34:54
如果 master 已经这样了就无解了,最后解决方法就是一直故障,然后立刻定位问题解决,足足持续了 2 个小时才解决。。。
weiwenhao
2021-09-18 12:36:19
@karott7 我们当时发布工具比较垃圾,就是选择 master 上的 一个一个 commit 然后打包发布。 然后也没有打 tag 的习惯,如果有 tag 应该也是可以解决的,不确定。
karott7
2021-09-18 12:43:04
@weiwenhao #18 无解是因为乱用 merge 命令,应该所有的更改都从主分支检出新分支,每一个 commit 尽可能小,合并的时候照二楼说的先 rebase,再到主分支 merge(为什么要这样做?你可以在你的项目主分支和开源项目分别执行下 git log —oneline —graph 命令看看区别),最后发布完成给最新 commit 打版本 tag,更甚至建一个 changelog.md 文件记录每次版本号和更改内容
karott7
1
2021-09-18 12:43:50
楼里不知道 git flow 流程的赶紧去学习一下
xlsepiphone
2021-09-18 12:44:52
rebase,上一次 merge 应该是 2016 年了。
daolanfler
2021-09-18 13:34:16
rebase +1,rebase 的提交记录更好理解
icylogic
2021-09-18 13:55:45
https://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html
bingyiyu
2021-09-18 14:01:30
reabse+1
Kobayashi
28
2021-09-18 14:26:36
Merge 多出来的提交不是无意义,它记录了一种合并关系,显式表明这个提交来自于一个分支。这也是 Git 分支的一大特性:Git 历史非一条直线,其中可以有岔路,或者说一个提交可以有多个父节点。Rebase 后再 fast forward 合并的话丢失了这种关系记录。
一个好的分支名直接解释了这个分支在做什么,如修复某个 bug 、新增了某个功能。而分支内每个提交则记录了实现的步骤。从这个角度来看,分支也可以视作一个大的提交。
Merge 而不是 rebase + fast forward 。更不要随意 merge --squash,而是根据情况使用。保留多个提交的实现步骤,如果这个功能出了问题,方便以后细分,定位问题。
楼上很多人对 Git 的理解水平真的不大行,只是在把 Git 当 SVN 来用……
建议了解了解 git-flow,理解一下分支。多翻翻 pro git book.
https://nvie.com/posts/a-successful-git-branching-model/
https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
https://git-scm.com/book/zh/v2
yalin
2021-09-18 14:27:46
merge
vjnjc
1
2021-09-18 14:39:16
#10 +1 “一律采用 squash merge 。 ”
大型项目也要考虑 merge,为了追溯真实提交情况。
假设一个场景,你想找 6 个月前有人做的 feature1 涉及到哪些文件改动。
1. rebase,你需要翻很多 commit 。比如 03/14 ~ 03/18 之间 user1 的所有 commit
2. merge 的话你只要看一个 commit 。或者是 gitlab/github 上的 mr
bingyiyu
2021-09-18 14:47:25
我会先把本地分支 rebase 到远程 master 分支,然后再发起 merge request 合并到 master 分支。
acidsweet
2021-09-18 15:03:10
merge;
1. 超大项目合码时 rebase 处理冲突的难度你不想体验
2. rebase 本身破坏了真实 commit 之间的逻辑顺序,粗暴的采用时间序其实非常蛋疼不直观
2i2Re2PLMaDnghL
1
2021-09-18 15:16:41
历史可以分叉是很恶的(双关:恶心且邪恶),但是因为爱因斯坦的关系不得不这么干。
凡 git 的事想一想用邮件怎么玩。
1. 什么时候 rebase ?
你以别人的软件的 v1.0 为基础开始写一个 feature,还没写完的时候 v1.1 发布了,你把新代码 pull 下来并把你的修改全都 rebase 到 v1.1 上去。
2. 什么时候 merge ?
别人为你的软件写了一个 feature,然后 send-email 给了你。你拿到了他的 patch 并 merge 进你的代码。
chaleaoch
2021-09-18 15:19:35
rebase 只在本地操作.
要不然很容易出问题.
OliveGlaze
1
2021-09-18 15:20:29
2 楼的原则,加上 29 楼的具体实践说明,其实就是现在业界的标准玩法了。
工作那么多年的老油条了,各种 git flow 用下来,你最后总会发现必须得有 MR/PR 这个环节。这一类的 flow 才是更适合实际工作的 flow,而且所谓的 rebase 和 merge 也没法完全割裂开来单独用的。
kxuanobj
2021-09-18 15:23:52
@wiirhan master 比较稳定,更改较少的情况下,可以试试 cherry-pick 到 dev 分支。
index90
2021-09-18 15:24:25
特性分支 rebase 主干分支,然后再 merge 主干
2i2Re2PLMaDnghL
2021-09-18 15:26:18
@2i2Re2PLMaDnghL 话说起来顾名思义都行
变基,是指『变更』提交的『基础』
合并,是指将两个分支的提交进行『合并』(我知道,循环定义了)
也就是说,当且仅当这些提交是那些提交的『基础』时才进行变基。
@vjnjc 你可以 diff <merge 的主支>...<merge 的分支>
据说 fossil 合并后分支会变成 tag 永久保留,你也可以轻易地看到这个 branch 的历史。
squash 似乎不太适合在时域上进行 bisect,这对于大型项目还是挺重要的。
maplerecall
2021-09-18 15:31:05
微软这边的 git 项目合并 master 基本都 squash merge,保证 master 的记录是单线性的。至于合并前自己的分支爱怎么搞就怎么搞,PR 跑 build 和 test 能通过,不 conflict 就好了。
不过我基本都只用 rebase,只有极少数情况出现多人同时开发具有互相依赖性的东西才会 merge 。很多 mono repo 每天 master 要进几十上百个不同 team 做的东西,用 merge 会很糟心。
MrGoooo
2021-09-18 15:34:51
rebase 没有按时间排序,merge 按时间顺序
oneisall8955
1
2021-09-18 15:36:26
@weiwenhao #13 有两点疑问
1. 22 号的 bug,不能从 master 创建新分支修复吗?
2. 22 号的 bug 是 15 号提交的,那在 15 号的分支上修复也可以吧?先 pull master 到 15 号分支,处理冲突,修复完 bug 再 merge 到 master
Felldeadbird
2021-09-18 16:08:19
我是个人和团队也用 merge 。分支线是会显得乱,但是不会出问题。
charlie21
2021-09-18 16:08:54
为什么 ‘包含完整的提交历史记录’ 会是一个需要避免的问题? 你瞎搞之后丢记录了怎么办 行为艺术吗
mdyy777
2021-09-18 16:22:32
我选择 rebase
MinonHeart
2021-09-18 16:25:17
一般原则 public branch 用 merge,private branch 用 rebase 。
但是用 rebase 后要怎么 revert/reset 这次 rebase 呢?
cco
2021-09-18 16:30:49
我用的 merge,因为场景并不复杂,merge 和 rebase 都差不太多。
dyxLike
2021-09-18 16:40:27
两个远程分支用 rebase 反而会乱吧
securityCoding
2021-09-18 16:54:11
@libook 线上发版会基于 tag 来构建
libook
2021-09-18 16:59:25
@securityCoding #47 不是每个 feature 一个 tag 吧,总会有合并操作的,打 tag 也是在合并完的分支上打 tag 。
securityCoding
2021-09-18 17:02:10
@libook 我的意思是用 tag 作为版本号,这样就隔离了版本与代码合并操作过程
leafre
2021-09-18 17:06:40
"merge 会产生一个无意义的提交" rebase 只是重播一遍,并不能解决无意义提交 的问题
msg7086
1
2021-09-18 17:07:11
并入更改用 merge,散播更改用 rebase 。
人人都懂 Git 的小公司 merge 的时候可以用普通的 merge commit,不是人人都懂 Git 的公司(特别是参差不齐的大公司)或者合并非常频繁的大公司,可以善用 squash merge 。(我司一般都是 squash merge,因为合并太频繁了,经常 Rebase 不现实。)
↑ 理想的 timeline 应该是类似这样的。
↑ 大多数公司代码的 timeline 是这样的。
reactna1ve
1
2021-09-18 17:12:36
感觉 2#的说法是合理的
本地分支同步 dev 用 rebase 保证本地的提交和顺序是清楚的
dev 同步 hotfix 、合入 feature 用 merge,保证操作的节点顺序以及方便 revert
我之前也比较喜欢用 squash merge,后来发现对于一个开发周期比较长的 feature,squash 到一起太容易丢 context 了。比如某几行修改是为了解决需求中的某个 bug,这时候提单个 commit,后续再看知道这个修改是干啥的;几千行的大修改,squash 到一个 commit 里,过几个月完全不知道这几行为啥要这么改……
Biwood
2021-09-18 17:22:19
以前很少用 rebase,完全不知道有用 rebase 把提交历史记录整理一遍的说法,可能是每个人的习惯不同吧
不用 rebase 的好处是,每一个操作细节都清清楚楚的留下记录,提交记录重要的不是“简洁”、“好看”,而是可追溯性
wangbenjun5
2021-09-18 17:25:03
merge 简单易懂,rebase 不是人人都会,另外 merge 包含完整的提交历史,这样出问题容易找人负责,谁改的谁写的一目了然,99%的公司都是 merge
libook
2021-09-18 17:27:42
@securityCoding #49 这里讨论的问题是 merge 和 rebase,发生在打 tag 之前,似乎和 tag 关系不大。
weiwenhao
2021-09-18 17:28:38
@oneisall8955 可以从 master 创建新的分支修复呀,也就是这么做的,但是定位问题然后修复上线用了 2 个小时。此时线上已经故障了两个小时了呀。 是比较严重的故障,需要立刻版本回退那种。
Biwood
2021-09-18 17:29:07
由 2 楼的说法想到,这其实是一个思维模式问题,如果一直在主分支操作所有合并行为,包括解决冲突,那么可以一直用 merge 。如果操作主分支的人不希望承担解决冲突的责任,那么子分支用 rebase 的必要就来了。当然,直接把主分支往子分支合并也能解决一些问题,但这显然让分支流程变乱了,不管你坚持 merge 还是 rebase,都不推荐这么干。
wingtao
2021-09-18 17:29:21
@weiwenhao 这种直接把 9.22 号的 pr revert 掉不好使么
penghong
2021-09-18 17:33:22
主干开发+小批量提交+squash merge
weiwenhao
2021-09-18 17:34:08
@wingtao 应该是好使的,但是都没用过呀。。。当时 gitlab 的 revert 试了一下没成功就没试了,主要是不熟悉。
zhw2590582
2021-09-18 17:34:10
看过一篇老外教程说:永远不要在公共分支 rebase
oakland
2021-09-18 17:47:49
@zhw2590582 此 rebase 非彼 rebase
xiubin
2021-09-18 18:01:59
单人分支 rebase 公共分支;单人分支 merge into 公共分支
Kobayashi
2021-09-18 18:02:56
@Kobayashi 仔细想了一想,之前的长回复应该补充一点。主要是楼主的问题应该从两个角度回答,我只回答了其中一部分。
楼主问题提到“2 个远程分支合并”,是指原来两个分支都和主分支在一条线上,如果一个分支先合并,另一个与更新后的主分支分叉,合并时发生了 merge --no-ff. 按照楼主的理解,分支合并应该是
1. rebase 到主分支,保证分之合并前没有分叉
2. merge --ff,保证分支合并后没有额外 merge commit.
其实这就是 非 Git 版本控制工具 的分支使用逻辑:分支历史必须是一条线,分支起点必须是主分支最新提交。如 SVN.
这个问题实际要分为 2 个部分:
1. 合并分支前是否要 rebase?
2. merge 是否使用 --ff 快速推进,要不要不产生额外的“合并提价”?
我之前的回复其实只针对了 2,介绍了 Git 分支非一条支线的特性,推荐了 --no-ff 合并。
如果只针对 1,可以根据情况:
- 如果向主分支合并时发生冲突,可以合并时解决冲突。或者 rebase 解决冲突,再合并。
- 或者你想让提交历史图( timeline )更清晰一点,也可以先做 rebase 一下。如当前分支和合并前主分支时间隔的太久,直接合并后分支线头尾跨得太远,不好查看。或者是不想多个分支线合并后有交叉。(敲完才发现楼上 @msg7086 回复,参考其“理想的 timeline”一图,非常漂亮)
- 或者分支合并前不做 rebase,降低工作流使用门槛。如 Github PR 合并方式:直接给你在网页上整一个按钮,点击后 merge --no-ff.
不管哪种情况,推荐 merge --no-ff 优先。一些特殊情况,如分支上 只有 1 个新提交,可以 --ff 快速推进。
ospider
1
2021-09-18 18:22:38
都 2021 年了,竟然还有人在推荐 git flow
supereasy
2021-09-18 18:31:14
从 16 年到现在 一直 merge --no-ff 不会转为 rebase
celeron533
2021-09-18 20:11:53
我有时候先 interactive rebase,压掉不必要的 commit,最后 merge
Kobayashi
2021-09-18 20:36:14
@ospider git flow 是严格了点,实践中未必要严格遵守使用,但其中的分支使用思想经久不衰。鉴于楼主目前遵循的分支使用逻辑是分支合并结果要保留单一直线,我觉的推荐 git flow 正合适。
kaneg
2021-09-18 20:38:06
我看到过很多人把 git 的 commit 当成草稿箱,提交很多无意义的改动,每次 commit 基本在修改错别字或者反复 rollback 。针对这种情况,在 PR merge 到 master 之前,最好 squash 。否则如果日后做 trouble shooting 的时候,其中的每条 commit 就是对别人的折磨。
xuanbg
2021-09-18 20:51:35
项目比较复杂,多人同时维护。用 rebase 简直就是噩梦。
wukongkong
2021-09-18 21:08:36
@Pipecraft 我们用这个导致了半年的 commit 丢失,负责人不会用,瞎用,,,,
beichenhpy
2021-09-18 21:11:37
永远 merge
namelosw
2021-09-18 21:53:18
这其实本质和团队质量有关:
其实最理想的情况就是努力培养团队,素质都不错,需求拆分合理,自动化测试和持续集成也做得很好,所有人在同一个分支疯狂 rebase 效果是最好的。
如果有个总记不住拉代码,互相甩锅,功能拆分不完整,提代码就挂掉别人的功能,代码合进来也不知道对不对的团队,那只能先 merge…
devfeng
2021-09-19 03:20:40
这个可以灵活应对吧,能用 rebase 的情况下尽量 rebase 了
IvanLi127
2021-09-19 13:04:49
请求科代表做总结
24bit
2021-09-19 19:41:08
开发分支 rebase,合并 master fast forward merge
Jsonz
2021-09-19 22:33:04
@weiwenhao 我想了一下我们现在的流程
各个 feature 会从 master 拉取分支,比如 featureA 、featureB 、featureC
如果开发的过程中,master 上发现一个 bug,则会基于 master 拉取一个分支 hotfixA,改好合并到 master 自动发布
发布完触发各个 feature 分支会自动 merge master 。
假如这时候 featureA 测试完成,要发布的话,是 merge 到 master,发到线上发现有 bug,直接回滚上一个 merge 节点不就好了...
git reset HEAD^ --soft 然后再修改代码提交先回滚?
这样可以解决吗
热门帖子
1
成都购房选择
2
收一台电纸书
3
OD 面试
4
gopeed不支持win7
5
远程 #居家办公岗位 研发测试专员(2-3 位)WEEX 唯客中文交易所
6
iPhone13 相机很卡且杀后台
7
打算花 2599 买辆倍特电动车上下班通勤
8
成都被优化的大龄程序员希望可以整合一下各位的资源
9
请教一下大佬们索尼 A7C2 咋样
10
想收一个 2.5G 软路由
热门github
1
A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input
(翻译:适用于 OpenGL、OpenGL ES、Vulkan、窗口和输入的多平台库)
2
Dev tool that writes scalable apps from scratch while the developer oversees the implementation
(翻译:可扩展开发工具的 PoC,该工具从头开始编写整个应用程序,同时开发人员监督实施)
3
shadcn/ui, but for Svelte. ✨
(翻译:shadcn-svelte是shadcn/ui的非官方社区主导的Svelte端口。)
4
The Python Risk Identification Tool for generative AI (PyRIT) is an open access automation framework to empower security professionals and machine learning engineers to proactively find risks in their generative AI systems.
(翻译:用于生成式 AI 的 Python 风险识别工具 (PyRIT) 是一个开放式访问自动化框架,使安全专业人员和机器学习工程师能够主动发现其生成式 AI 系统中的风险。)
5
Performance-portable, length-agnostic SIMD with runtime dispatch
(翻译:Highway 是一个提供可移植 SIMD/向量内在函数的 C++ 库。)
6
ZK Credo
(翻译:ZK信条)
7
OpenCodeInterpreter: Integrating Code Generation with Execution and Refinement
(翻译:OpenCodeInterpreter:将代码生成与执行和优化集成)
8
Joplin - the secure note taking and to-do app with synchronisation capabilities for Windows, macOS, Linux, Android and iOS.
(翻译:Joplin - 一个开源的笔记和待办事项应用程序,具有Windows,macOS,Linux,Android和iOS的同步功能。)
9
Mamba is a new state space model architecture showing promising performance on information-dense data such as language modeling, where previous subquadratic models fall short of Transformers. It is based on the line of progress on structured state space models, with an efficient hardware-aware design and implementation in the spirit of FlashAttention.
(翻译:Mamba 是一种新的状态空间模型架构,在信息密集型数据(例如语言建模)上显示出良好的性能,而之前的二次模型在 Transformers 方面存在不足。它基于结构化状态空间模型的进展,并本着FlashAttention的精神进行高效的硬件感知设计和实现。)
10
This repository contains System Design resources which are useful while preparing for interviews and learning Distributed Systems
(翻译:该存储库包含系统设计资源,在准备面试和学习分布式系统时非常有用)
11
Curso para aprender el lenguaje de programación Python desde cero y para principiantes. 75 clases, 37 horas en vídeo, código, proyectos y grupo de chat. Fundamentos, frontend, backend, testing, IA...
(翻译:从零开始学习 Python 编程语言的课程,适合初学者)
12
🎓 Path to a free self-taught education in Computer Science!
(翻译:🎓计算机科学免费自学教程!)
13
1️⃣🐝🏎️ The One Billion Row Challenge -- A fun exploration of how quickly 1B rows from a text file can be aggregated with Java
(翻译:十亿行挑战 —— 使用 Java 对文本文件中的 10 亿行数据进行聚合的有趣探索)
14
A collective list of free APIs
(翻译:免费 API 的集合列表)
15
📚 Freely available programming books
(翻译:📚 免费提供的编程书籍)