跳至主要内容

关于拉取请求合并

您可以合并拉取请求,方式包括保留特性分支中的所有提交、将所有提交压缩为单个提交,或将 head 分支中的各个提交重新基准(rebase)到 base 分支。

合并您的提交

当您点击拉取请求中的默认 Merge pull request(合并拉取请求)选项时,特性分支的所有提交都会通过一次合并提交(merge commit)添加到基准分支。此拉取请求使用 --no-ff 选项进行合并。

要合并拉取请求,您必须在仓库中拥有写入权限

Diagram of a standard merge and commit flow, where commits from a feature branch and an additional merge commit are both added to main.

压缩并合并您的提交

当您在拉取请求中选择 Squash and merge(压缩并合并)选项时,拉取请求的所有提交会被压缩为单个提交。与其看到贡献者在主题分支上逐个提交的记录,压缩后只保留一个提交并合并到默认分支。使用压缩合并的拉取请求会采用 快速前进(fast‑forward)选项进行合并。

要压缩并合并拉取请求,您必须在仓库中拥有写入权限,并且仓库必须允许压缩合并

Diagram of commit squashing, where multiple commits from a feature branch are combined into only one commit that is added to main.

使用压缩并合并可以让仓库的 Git 历史更简洁。功能分支上的工作进行期间,提交记录对开发过程很有帮助,但不一定需要保留在 Git 历史中。如果在合并到默认分支时将这些提交压缩为一次提交,变更会被合并为单一提交,从而形成清晰的 Git 历史。

压缩合并的合并信息

在压缩并合并时,GitHub 会生成默认的提交信息,您可以自行编辑。根据仓库的配置以及拉取请求中(不包括合并提交)的提交数量,此信息可能包含拉取请求标题、拉取请求描述或提交的相关信息。

提交数量摘要描述
单个提交单个提交的提交信息标题,后跟拉取请求编号单个提交的提交信息正文
多个提交拉取请求标题,后跟拉取请求编号所有被压缩提交的提交信息列表,按日期顺序排列

拥有仓库维护者或管理员权限的人员可以为所有压缩提交配置仓库的默认合并信息,选择使用拉取请求标题、标题加提交详情,或标题加描述。更多信息请参见配置拉取请求的提交压缩

压缩并合并长期存在的分支

如果您计划在拉取请求合并后继续在该head 分支上工作,建议不要对该拉取请求使用压缩并合并。

创建拉取请求时,GitHub 会识别同时位于 head 分支和base 分支上的最近一次共同提交,即公共祖先提交。当您对拉取请求执行压缩并合并时,GitHub 会在 base 分支上创建一个提交,其中包含自公共祖先提交以来您在 head 分支上所做的所有更改。

由于该提交仅存在于 base 分支而不在 head 分支,两个分支的公共祖先保持不变。如果您继续在 head 分支上工作,并在两个分支之间再次创建拉取请求,该拉取请求将包含自公共祖先以来的所有提交,包括之前在拉取请求中被压缩并合并的提交。如果没有冲突,您可以安全地合并这些提交。但这种工作流会增加合并冲突的可能性。如果对长期存在的 head 分支持续使用压缩并合并,您将不得不一次又一次地解决相同的冲突。

变基并合并您的提交

当您在拉取请求中选择 Rebase and merge(变基并合并)选项时,主题分支(或 head 分支)中的所有提交会逐个添加到 base 分支上,且不会产生合并提交。这样,变基并合并的行为类似于快速前进合并,保持线性项目历史。但实际实现是通过在 base 分支上重写提交历史,生成新的提交。

GitHub 上的变基并合并与 git rebase 略有不同。GitHub 的变基并合并始终会更新提交者信息并生成新的提交 SHA,而在 GitHub 之外使用的 git rebase 在基于祖先提交进行变基时不会更改提交者信息。更多关于 git rebase 的信息,请参阅 Git 官方文档中的git-rebase

要变基并合并拉取请求,您必须在仓库中拥有写入权限,并且仓库必须允许变基合并

有关 git rebase 的可视化示例,请参阅 Pro Git 书中的 “Git Branching - Rebasing” 章节

以下情况下无法自动进行 rebase 合并:

  • 拉取请求存在合并冲突。
  • 将 base 分支的提交变基到 head 分支时出现冲突。
  • 变基被视为“不安全”,例如虽然可以在不产生合并冲突的情况下完成变基,但其结果会与合并产生的结果不同。

如果您仍希望变基这些提交,但无法自动进行变基合并,必须:

  • 在本地命令行上将主题分支(或 head 分支)变基到 base 分支
  • 在命令行上解决所有合并冲突.
  • 强制推送已变基的提交到拉取请求的主题分支(或远程 head 分支)

拥有仓库写入权限的任何人,然后可以使用变基并合并按钮合并这些更改。

间接合并

如果某个拉取请求的 head 分支已经被直接或间接合并到 base 分支(即 head 分支的 tip 提交从 target 分支的 tip 可以被访问),则该拉取请求可以自动合并。例如:

  • 分支 main 当前指向提交 C
  • 分支 feature 是从 main 分支创建的,当前指向提交 D。该分支有一个目标为 main 的拉取请求。
  • 分支 feature_2 是从 feature 分支创建的,当前指向提交 E。该分支同样有一个目标为 main 的拉取请求。

如果先合并拉取请求 Emain,则拉取请求 Dmain 会因为 feature 中的所有提交已经可以从 main 访问而被标记为自动合并。将 feature_2 合并到 main 并在命令行将 main 推送到服务器后,两个 拉取请求都会被标记为已合并。

间接合并只能在以下两种情况出现:要么拉取请求的 head 分支的提交直接推送到仓库的默认分支,要么这些提交出现在另一个拉取请求中并通过创建合并提交选项合并到仓库的默认分支。

如果使用 Squash and mergeRebase and merge 选项合并了包含其他拉取请求 head 分支中提交的拉取请求,则会在 base 分支上创建一个新提交,另一拉取请求将不会被自动合并。

间接合并的拉取请求即使未满足分支保护规则,也会被标记为 merged(已合并)。

延伸阅读

© . This site is unofficial and not affiliated with GitHub, Inc.