合并方法

您为项目选择的合并方法决定了合并请求中的更改如何合并到现有分支中。

本文的示例假设有一个包含提交 A、C 和 E 的 main 分支,以及一个包含提交 B 和 D 的 feature 分支:

gitGraph commit id: "A" branch feature commit id: "B" commit id: "D" checkout main commit id: "C" commit id: "E"

配置项目的合并方法

  1. 在左侧边栏中,选择 搜索或转到 并找到您的项目。
  2. 选择 设置 > 合并请求
  3. 从以下选项中选择您所需的 合并方法
    • 合并提交
    • 带有半线性历史的合并提交
    • 快进式(Fast-forward)合并
  4. 合并时压缩提交 中,选择处理提交的默认行为:
    • 不允许:从不执行压缩,用户无法更改行为。
    • 允许:默认情况下压缩处于关闭状态,用户可以更改行为。
    • 鼓励:默认情况下压缩处于启用状态,用户可以更改行为。
    • 必须:始终执行压缩,用户无法更改行为。
  5. 选择 保存更改

合并提交

默认情况下,当分支合并到 main 时,极狐GitLab 会创建合并提交。无论提交合并时是否被压缩,都会创建单独的合并提交。此方法可能会导致压缩提交和合并提交都添加到您的 main 分支中。

下图显示了如果您使用合并提交方法,feature 分支如何合并到 main 中,相当于使用命令 git merge --no-ff <feature>,并在 UI 中选择 Merge commit 作为合并方法

合并方法:

%%{init: { 'gitGraph': {'logLevel': 'debug', 'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'main'}} }%% gitGraph commit id: "A" branch feature commit id: "B" commit id: "D" checkout main commit id: "C" commit id: "E" merge feature
  • 相比之下,压缩合并会构建一个压缩提交,这是来自 feature 分支的所有提交的虚拟副本。原始提交(B 和 D)在 feature 分支上保持不变,然后在 main 分支上创建一个合并提交,将压缩后的分支合并进来:

    %%{init: { 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'main', 'fontFamily': 'GitLab Sans'}} }%% gitGraph accTitle: 压缩合并的示意图 accDescr: 展示压缩提交添加到主分支后,仓库和分支结构的 Git 图表。 commit id:"A" branch feature checkout main commit id:"C" checkout feature commit id:"B" commit id:"D" checkout main commit id:"E" branch "B+D" commit id: "B+D" checkout main merge "B+D"

压缩合并图表与 GitLab UI 中的以下设置等效:

  • 合并方法:合并提交。
  • 合并时压缩提交 应设置为以下之一:
    • 必需。
    • 允许或鼓励,且在合并请求中必须选择压缩。

压缩合并图表也与以下命令等效:

  git checkout `git merge-base feature main`
  git merge --squash feature
  git commit --no-edit
  SOURCE_SHA=`git rev-parse HEAD`
  git checkout main
  git merge --no-ff $SOURCE_SHA

使用半线性历史的合并提交

每次合并时都会创建一个合并提交,但只有在可以执行快进合并时,分支才会被合并。这确保了如果合并请求构建成功,那么合并后的目标分支构建也会成功。以下是使用这种合并方法生成的示例提交图:

%%{init: { "fontFamily": "GitLab Sans" }}%% gitGraph accTitle: 合并提交的示意图 accDescr: 显示当一个分支与合并提交进行合并时的提交流向。 commit id: "Init" branch mr-branch-1 commit commit checkout main merge mr-branch-1 branch mr-branch-2 commit commit checkout main merge mr-branch-2 commit branch squash-mr commit id: "压缩提交" checkout main merge squash-mr

当您访问选中了 半线性历史的合并提交 方法的合并请求页面时,只有在可以进行快进合并的情况下,才能接受合并请求。 当无法进行快进合并时,用户会被提示进行变基,参见 在(半)线性合并方法中的变基

这种方法等同于 合并提交 方法中的 Git 命令。然而,如果您的源分支是基于目标分支(如 main)的过时版本,您必须对源分支进行变基。 这种合并方法创建了一个看起来更干净的历史,同时仍然允许您查看每个分支的开始和合并位置。

快进合并

有时,工作流政策可能要求没有合并提交的干净提交历史。在这种情况下,快进合并是合适的。通过快进合并请求,您可以保留线性 Git 历史,并且可以接受合并请求而不创建合并提交。以下是使用这种合并方法生成的示例提交图:

%%{init: { "fontFamily": "GitLab Sans" }}%% gitGraph accTitle: 快进合并的示意图 accDescr: 展示了快进合并请求如何保持线性 Git 历史,但不添加合并提交。 commit id: "初始化" commit id: "合并 mr-branch-1" commit id: "合并 mr-branch-2" commit id: "在 main 上提交" commit id: "合并 squash-mr"

此方法等价于:

  • git merge --ff <source-branch> 用于常规合并。
  • git merge --squash <source-branch> 后跟 git commit 用于 squash 合并。

当启用快进合并(--ff-only)设置时,不会创建合并提交,所有合并都将快进合并。只有当分支可以进行快进合并时,才允许合并。如果无法进行快进合并,用户将获得重新基准(rebase)的选项,请参阅 在(半)线性合并方法中的变基

当您访问已选择 快进合并 方法的合并请求页面时,您只能接受当快进合并可行时

在(半)线性合并方法中的变基

在这些合并方法中,只有当您的源分支与目标分支保持同步时,才能进行合并:

  • 使用合并提交的半线性历史。
  • 快进合并。

如果无法进行快进合并,但可以进行无冲突的变基,GitLab 提供:

如果以下两个条件都成立,您必须在进行快进合并之前本地变基源分支:

  • 目标分支领先于源分支。
  • 无冲突的变基无法完成。

即使 squashing 本身也可以视为变基,进行合并时可能仍然需要先执行变基。

无 CI/CD 管道的变基

  • 在极狐GitLab 15.3 中更改为 普遍可用。特性标志 rebase_without_ci_ui 已移除。

要在不触发 CI/CD 管道的情况下变基合并请求的分支,请在合并请求的报告部分选择无管道变基

此选项:

  • 在无法进行快进合并但可以进行无冲突变基时可用。
  • 在启用 管道必须成功 选项时不可用。

在没有 CI/CD 管道的情况下进行变基可以节省资源,适用于需要频繁变基的半线性工作流项目。

相关主题