浅谈git rebase/merge

2023年 8月 13日 39.1k 0

前言

本文默认你已经有了一定的git基础,并且对于分支等概念有了初步的认识

分支的合并

在实际的工作当中,由于git的特性,在仓库内会存在各种各样的分支,这些分支又是由不同的人在维护修改。这里就会涉及到分支合并的场景。

直到……

混乱的分支场景

火葬场的分支(心 肺 停 止)

当然,作为开发者的我们一定是要避免这种情况的发生的,因此我们要活用分支的合并操作。

merge

在git中,我们可以使用git merge命令来合并分支。

例如我们现在的commit树:

image-20230812224354627

我们此时的HEAD 在main分支上

此时我们使用git merge dev命令,此时commit树会变成这个样子

image-20230812224500298

让我们来简单理一下发生了什么。

在merge命令发送后,git会将C2 C3 C4 C5 C6做一个简单的合并操作,然后git会自动在main分支上commit一个提交C7,让C7的祖先指向C4与C6,merge结束。

你有没有观察到什么?

merge的冲突情况

假如我们此时dev分支和main分支做出的修改是针对同一个文件呢?

在这种情况下,我们刚刚提到的合并操作会由于不知道保留何种更改而暂停操作:

$ git merge dev
Auto-merging test-1.txt
CONFLICT (content): Merge conflict in test-1.txt
Automatic merge failed; fix conflicts and then commit the result.

上述就是一个有冲突环境下的merge提示

$ git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)
​
Unmerged paths:
  (use "git add ..." to mark resolution)
​
        both modified:   test-1.txt
​
no changes added to commit (use "git add" and/or "git commit -a")

当你使用status查看状态时,git会提示你有文件目前具有冲突并没有被合并,此时你需要自行处理冲突,并手动完成最后一步commit。

而冲突会映射回源文件中:

This is test-1.
update test-1.
add test-1.
> dev

这里 HEAD 表示所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 dev 分支所指示的版本在=======的下半部分。

你只需要解决在这些标记的地方完成合并即可,修改源文件为:

This is test-1.
update test-1.
add test-1.
test master.
test dev.

此时保存后手动提交便完成了冲突合并。

merge的好处是它将所有的commit信息完整的保留了下来,但当项目体量变得复杂且庞大时,面对很多分支和总分支合并时,你的commit树可能会变成……

rebase

另一个合并的途径便是rebase,又称变基,它和merge不同的是它会抛弃合并的一些信息,什么意思呢?

假如我们现在有着这样的commit树: image-20230812230608431

我们来对比一下merge和rebase

使用merge:

image-20230812230647206

使用rebase

image-20230812231024457

此时main分支上的C3提交消失了,取而代之的是main分支上的C3'

对于rebase来说,它会将当前分支上的提交一个个取消掉,同时将它们临时保存为补丁(patch),然后main分支更新到dev分支上,接下来在main分支上应用之前保存的所有补丁完成变基流程。

对比

我们不难发现,在merge和rebase产生的两种commit树中,merge无疑是保留信息最多的那一个,它不仅会保存原commit,同时也会记录合并流程

但rebase不同,rebase会将原分支合并的commit信息丢失掉,从而保证变基后分支只保留一个,合并后的commit也不是原来的commit。

使用情景

以下的言论偏主观化。

个人认为,如果要避免灾难般的commit树,无疑rebase是最佳选择,但另一方面,merge虽然庞大繁杂,但是一目了然,方便进行问题的追踪检查。

因此在合并分支时,使用merge是最佳选择。

当从远程分支拉取合并时,使用pull与rebase能保证本地分支的简洁直观。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论