Merge的进阶用法和冲突处理
# 一、进阶用法
# 1. squash
squash是压碎的意思。
在merge另一个分支X的时候,如果觉得其无用的提交太多,可以尝试使用squash,把那个分支历史提交压缩后再提交。
更直观一些,可以如下操作:
- 假如当前分支 master 的commitId是a。
- 从当前分支创建了另一个分支 dev
- 在dev上做了三次提交,commitId 分别是 b c d
- 此时切换到master分支
- 执行
git merge --squash dev
git 会把 dev 分支上所有的改动提取出来,并做了一次 git add
操作。但它不会自动提交,需要我们手动发起提交。
其实实际开发环境中,进行 merge --squash
的操作很少,这个适用于:
- 想丢弃某个分支的提交记录(可能提交太多且无用),另外新建一个分支替代它
- 想丢弃某个分支,又想留住其代码
# 2.Fast-Forward
看如下的操作步骤:
- 假如当前分支 master 的commitId是a。
- 从当前分支创建了另一个分支 dev
- 在dev上做了三次提交,commitId 分别是 b c d
- 此时切换到master分支(前4步都一样)
- 执行
git merge dev
的操作
这个时候master分支是什么样子?
- 默认情况下(ff模式),master的提交树会是一条线,看上去和dev的分支一样。
no-ff
模式下,会在master创建一个新的提交,明显可见的有其他分支合并进来。
因为fast-forward 模式只是更新了一下master的指针。而no-ff
模式下,是创建了一个新的提交。
Git默认是 ff 模式,然而并不是每次都能使用 fast-forward。
如果从 commitId-a 创建dev分支后,master又做了1次或多次提交,那再merge dev分支的时候,就无法使用 fast-forward ,只能新建一个提交了。
# 二、merge冲突处理
# 1.直接放弃
无论是执行 pull 还是 merge其他分支,如果merge遇到冲突,我们感觉肯定解决不了的,git提供了一个放弃 merge的指令:
git merge --abort
# 2.中途放弃
比放弃更痛苦的是花了很长时间,解决了很多冲突,才发现自己还是解决不了。这个时候 abort 可能已经不好用了。
这时候最好的办法就是,先提它一版,再reset
git add .
git commit -m xxx
git reset --hard HEAD~1
中间不要断,一气呵成,就回到最初的起点
# 3.手动解决冲突
如果下定决心解决冲突,有个比较传统的办法就是手动解决冲突,一共分三步:
- 看明白冲突
- 编辑代码解决冲突
- git add 解决完冲突的文件,然后git commit
# step1看明白冲突
<<<<<<< HEAD
aaa
=======
bbb
>>>>>>> a9ie876y654r43efgu876tghji87yhj
一般冲突都这个样子,中间一串等号是分隔符。往上的是当前我们分支的内容(HEAD),往下是我们要合并过来的分支的内容(一串commitId)
# step2手动解决冲突
要把不相干的内容都删掉,包括分隔符和 commitId 和 HEAD 标记位。
# step3 提交
如果确定冲突解决完了,就把解决完的文件执行一下 git add
。到最后执行一个 git commit
即可。
最后的commit 建议不要加-m参数。git会跳出一个界面,附带它自动生成的备注,包含了合并信息,在提交记录中很容易看出来。
如果我们添加了-m,自己指定了注释,往往不如自动的清除,它明确标出了从哪里merge到哪里。
不要觉得最后打开的注释面板很恐怖,其实就是打开了一个vim编辑器,而且提交的时候,以#开头的文本都不会记录到备注中。
# 4.一键解决冲突
这里一定要推荐 jetBrain 系列从2020 版开始推出的魔术棒,可以一键解决90%的冲突。
首先当合并出现冲突的时候,点击 Resolve,然后点击merge,进入合并界面
然后就可以看到弹出对话框上有一个魔术棒。点击一下,即可自动解决90%的冲突。
如果魔术棒不可用,或者点了之后还是有冲突,剩下的就只能手动解决了。