共计 2147 个字符,预计需要花费 6 分钟才能阅读完成。
给你一个真实工作协同开发场景:在 git 中创建新仓库 默认会有一个 main 分支。你在开发一个系统中的某一个小部分时,【就如同我们现在专注于开发一个页面的其中一个组件,我们会单单创建一个文件用来开发这个组件 一样】。我们会为这一小部分开发过程创建一个分支 branch
你可以将该情况想象为一个 树级结构

我们一般将 main 视为主线,在分支 feature/ A 开发完毕的代码会最终 merge 合并到 main 分支上
其实所有的分支都是 平级 的。不存在哪个分支比另一个分支级别高的情况
Feature branch 工作流
这就是 Feature Branch 工作流。多个开发者,在开发不同功能时,会单独创建一个分支来进行开发,当开发完毕后,一般也不会直接合并到本地的 main 分支,而是我们需要提交到远程仓库,在这种情况下,因为要对代码质量等进行评测,我们推送到远程仓库的对应分支下后,比如:
// 当前在 feature/A 分支
git add . // 将当前工作区修改过的部分都保存到暂存区
git commit -m "feat: xxx" 将暂存区代码提交到本地仓库
git push -u origin feature/A 在远程先创建对应的分支 feature/A 与本地仓库的 feature/A 分支建立追踪关系 然后将本地代码推送到远程仓库的 feature/A 分支
接着我们便可以在远程仓库 比如 github、gitee 等 对这个分支提出 pr 等待管理者审核完毕后,会选择 merge,这样就把我们开发的分支代码合并到远程仓库的 main 主线分支中。我们就算是成功的贡献了代码。
Merge 的本质
merge 的工作过程是这样的:
从目标 commit 和当前 commit(即 HEAD 所指向的 commit)分叉的位置起,把目标 commit 的路径上的所有 commit 的内容一并应用到当前 commit,然后自动生成一个新的 commit。
一般情况下,我们需要
git checkout main // 切换到 main 分支
git pull // 首先同步一下 确保是最新状态
git merge feature/A // 将 feature/ A 分支代码合并到 main 分支
一般来说 feature/A 分支的最新一个 commit 是该分支串的 所有代码记录的集合体。
如此以来,git merge 就会把 feature/A 分支的最新记录 合并到 当前分支 main 对应位置
在使用 merge 时 会遇到的一些问题
1. 冲突解决
当前分支和要合并过来的那个分支中 都同时修改了某个文件的同一行代码,这时候 git 的算法无法得知保留哪个代码记录,所以当你执行 git merge Feature/A 时 会报出一个错误 等待你处理。
但它对文件还是做了一些工作:它把两个分支冲突的内容放在了一起,并用符号标记出了它们的边界以及它们的出处。上面图中表示,HEAD 中的内容是 移动硬盘(已买),而 feature1 中的内容则是 移动硬盘(不买了)。这两个改动 Git 不知道应该怎样合并,于是把它们放在一起,由你来决定。假设你决定保留 HEAD 的修改,那么只要删除掉 feature1 的修改,再把 Git 添加的那三行 <<< === >>> 辅助文字也删掉,保存文件退出,所谓的「解决掉冲突」就完成了。
当然。你可能不想解决冲突,而是放弃这次 merge。那么执行
git merge --abort
这样,git 仓库 会回到 merge 之前的状态。
2. HEAD 落后于目标 commit fast-forward
这时候在本地执行 git pull,由于本地 commit 落后远程的最新 commit。
origin/master 和 origin/HEAD 是什么鬼:它们是对远端仓库的 master 和 HEAD 的本地镜像在 git pull 的「两步走」中的第一步——git fetch 下载远端仓库内容时,这两个镜像引用得到了更新,origin/master 和 origin/HEAD 移动到了最新的 commit。
而 git pull 的第二步操作 merge 的目标 commit,是远端仓库的 HEAD,也就是 origin/HEAD,所以 git pull 的第二步的完整内容是:
git merge origin/HEAD
因此 HEAD 就会带着 master 一起,也指向图中绿色的最新 commit 了。
3. HEAD 领先于目标 commit 什么也不会做
如果 merge 时的目标 commit 和 HEAD 处的 commit 并不存在分叉,而是 HEAD 领先于目标 commit。
merge 就没必要再创建一个新的 commit 来进行合并操作,因为并没有什么需要合并的。在这种情况下,Git 什么也不会做,merge 是一个空操作。
总结
本节对 merge 进行了介绍,内容大概有这么几点:
merge的含义:从两个commit「分叉」的位置起,把目标commit的内容应用到当前commit(HEAD所指向的commit),并生成一个新的commit;merge的适用场景:- 单独开发的
branch用完了以后,合并回原先的branch; git pull的内部自动操作。
- 单独开发的
merge的三种特殊情况:- 冲突
- 原因:当前分支和目标分支修改了同一部分内容,Git 无法确定应该怎样合并;
- 应对方法:解决冲突后手动
commit。
HEAD领先于目标commit:Git 什么也不做,空操作;HEAD落后于目标commit:fast-forward。
- 冲突