【02】合并请求:Pull Request
提示
本教程仅对开发者下的 pull request 做介绍,即拥有在存储库下创建分支的权限,关于非开发者贡献代码的方式将在【03】Fork中进行介绍,不过在使用上与本教程类似。
1. 单独 master 分支
通过前面文章的知识可以知道,使用以下命令可以实现代码根提交
git add . # 将修改的内容暂存起来
git commit -m "commit message" # 将暂存的内容提交
git push origin master # 推送至远程库
效果如下
多次提交则会有多个 commit 节点
在大型项目的多人开发合作中,如果只有一个 public 下的 master 分支,对于代码库来说非常危险,极其容易因为错误删除某些重要文件、文件夹导致仓库崩溃。
2. 多分支结构
2.1 分支创建
因此使用是非常必要的,分支之间相互独立,因此在修改时并不会对其余分支造成影响。先假设上述的 third commit 节点所修改的代码如下:
int main(int argc, char *argv[])
{
cout << "master2" << endl;
return 0;
}
现创建分支 test1,使用以下命令即可创建一个新分支 test1:
git branch test1
git checkout test1
除此之外也可以使用如下命令完成创建:
git checkout -b test1
做出如下修改,并提交至分支 test1
int main(int argc, char *argv[])
{
cout << "master2" << endl;
cout << "test1" << endl;
return 0;
}
提交节点图如下:
2.2 分支合并
使用 git merge
可以实现分支间的代码合并
git checkout master # 切换至主分支
git merge test1 # 合并
节点图如下,此时 master 节点与 test1 节点重合,完成合并,但无法直接看出分支间的相互关系。
除此之外,merge 也无法实现代码审查的功能,若某分支删除了某些重要内容,并且该分支在时间线上领先于主分支,merge 时将会修改 master 的内容,与单 master 分支一样,很不安全。
3. Pull Request——合并请求
即:让别人拉取自己代码的请求
3.1 分支保护
若需要让 master 主分支不被任意删除、合并、推送,需要设置分支保护。不同的代码托管平台操作不一样,但都彼此相似:在设置中对 master 设置为保护分支,并且禁止推送
3.2 提交代码基本流程
由于直接推送本地 master 分支已经不可行,因此首先需要新建分支,并且在分支上进行完成开发、提交,这里继续以上文的 test1 为例,现已将 test1 推送至 origin/test1 远程库。
假设 test1 分支领先于 master 一次 commit,如下图。
若需要合并至 master 则需要。具体流程如下:
在仓库界面找到以下内容,并点击创建合并请求
选择需要拉取的分支以及合并的分支,点击创建合并请求
输入相关信息,创建Pull Request
可随时进行评论、等待评审人评审代码,部分代码托管平台具备
WIP
的标识,表示正在工作中,合并前需删除WIP
。。评审代码:
可以发布评论、、。通过后会显示批准合并
发布合并信息,最终确认合并
显示以下内容则说明成功合并,下方弹出的 可斟酌考虑是否删除(一般是要删除的)
3.3 冲突解决方案
首先准备不同于 master 的两个分支 test1、test2。其中三个分支的代码如下
master、origin/master:
int main(int argc, char *argv[])
{
cout << "test" << endl;
return 0;
}
test1、origin/test1:
int main(int argc, char *argv[])
{
cout << "test" << endl;
cout << "new test1" << endl;
return 0;
}
test2、origin/test2:
int main(int argc, char *argv[])
{
cout << "test" << endl;
cout << "new test2" << endl;
return 0;
}
Git Graph 显示如下
假设按照次序,先合并分支 test1 至 master。此时若再次合并 test2,则会有合并冲突
3.3.1 合并(merge)
此时的合并步骤如下:
仿照 3.2 的内容发起 Pull Request,提示有合并冲突
切换到 test2 分支,从远程库拉取 master 主分支的代码:
git pull origin master # 注意是在 test2 分支下,而不是 master,因为 master 修改后提交也不能推送
终端提示:此时Git Graph显示如下:
解决冲突,并推送至 origin/test2
git push origin test2
此时再看 origin/master 分支,提示:
合并请求,拉取远程主分支至本地库进行更新:
git checkout master git pull origin master # 此处更新只是为了在本地观察 master 与其他分支间的相对关系,对代码提交无作用
Git Graph 显示如下:
3.3.2 变基(rebase)
提示
在实际的单基础分支的开发中,更推荐使用变基的方式进行代码同步和冲突解决
对于 图3-8,先合并 test1 分支,有如下结果
此时 test2 分支的基,为 commit 记录为 "master"
的节点,而 test2 要合并进的 master 已经落后于现在最新的 master,因此会产生冲突,一般在开发中,会选择使用变基的方式进行分支的快进,即希望 test2 的基从 commit 记录为 "master"
的节点,快进到最新的 origin/master 节点,为此,我们可以使用以下命令
# 切换到 test2 分支
git checkout test2
# 变基至 origin/master
git rebase origin/master
提示冲突
在 VS Code 的合并编辑器中解决冲突,并点击☑️的按钮。可以得到以下节点图
此时 origin/test2 的基还是原先的基,而 test2 的基以及更新至了最新的 origin/master,因此此时进行 test2 的推送操作时,必须进行强制推送
git push origin test2 -f
可以得到以下节点图
继续完成 test2 的合并请求,最终节点图如下
注意
- 在每次 Pull Request 请求合并之后都可以在 master 分支拉取来自远程端的 origin/master,以查看当前最新代码,也可以使用
git fetch
命令来更新分支信息,此操作可直接显示远程端的信息; - 可使用 git 图形化插件显示 commit 节点,使用 vscode 编辑器的可使用 插件。