华南虎视觉组主页华南虎视觉组主页
首页
项目
通用
教程
Gitea
首页
项目
通用
教程
Gitea
  • Git 教程

    • 【01】基本使用
    • 【02】合并请求:Pull Request
      • 1. 单独 master 分支
      • 2. 多分支结构
        • 2.1 分支创建
        • 2.2 分支合并
      • 3. Pull Request——合并请求
        • 3.1 分支保护
        • 3.2 提交代码基本流程
        • 3.3 冲突解决方案
    • 【03】Fork

【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 则需要。具体流程如下:

  1. 在仓库界面找到以下内容,并点击创建合并请求

  2. 选择需要拉取的分支以及合并的分支,点击创建合并请求

  3. 输入相关信息,创建Pull Request

  4. 可随时进行评论、等待评审人评审代码,部分代码托管平台具备 WIP 的标识,表示正在工作中,合并前需删除 WIP。。

  5. 评审代码:

    可以发布评论、、。通过后会显示批准合并

  6. 发布合并信息,最终确认合并

  7. 显示以下内容则说明成功合并,下方弹出的 可斟酌考虑是否删除(一般是要删除的)

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)

此时的合并步骤如下:

  1. 仿照 3.2 的内容发起 Pull Request,提示有合并冲突

  2. 切换到 test2 分支,从远程库拉取 master 主分支的代码:

    git pull origin master
    # 注意是在 test2 分支下,而不是 master,因为 master 修改后提交也不能推送
    

    终端提示:此时Git Graph显示如下:

  3. 解决冲突,并推送至 origin/test2

    git push origin test2
    
  4. 此时再看 origin/master 分支,提示:

  5. 合并请求,拉取远程主分支至本地库进行更新:

    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 的合并请求,最终节点图如下

注意

  1. 在每次 Pull Request 请求合并之后都可以在 master 分支拉取来自远程端的 origin/master,以查看当前最新代码,也可以使用 git fetch 命令来更新分支信息,此操作可直接显示远程端的信息;
  2. 可使用 git 图形化插件显示 commit 节点,使用 vscode 编辑器的可使用 插件。
Prev
【01】基本使用
Next
【03】Fork