merge
引用及用途
10.3 Git 内部原理 - Git 引用 及 10.5 Git 内部原理 - 引用规范 中介绍了 Git 的引用(references,或简写为 refs)及其规范,可在本地 Git 仓库的 .git/refs
路径下查看已经 fetch 到本地的引用文件。
当我们在 GitLab 中创建一个 MergeRequest 时,remote 仓库中会自动创建 refs/merge-requests/$iid/head
和 refs/merge-requests/$iid/merge
两个引用,分别对应 MR 源分支内容,以及 将 MR 源分支内容合并至目标分支后的内容。
当我们对这个 merge
引用进行持续集成时,就可以实现未雨绸缪的效果:
即使尚未合并 MR,持续集成检查和验证的,却相当于是将 MR 合并至目标分支之后的效果。
这样在出现问题时,只需继续在 MR 中进行修改即可,而不是将已经合并至目标分支的内容回滚之后再重新处理。
本地获取 merge
引用
增加 fetch
引用规范
.git/config
配置文件中可以指定多个用于获取操作的引用规范。
添加 merge
引用的方式为增加 +refs/merge-requests/*/merge:refs/remotes/origin/merge-requests/*/merge
,如:
[remote "origin"]
url = https://gitlab.com/AlphaHinex/merge-refs-test.git
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/merge-requests/*/merge:refs/remotes/origin/merge-requests/*/merge
在 GitLab 上创建 MergeRequest 之后,可使用 fetch
命令获取 merge
引用,如:
$ git fetch origin
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
展开对象中: 100% (1/1), 248 字节 | 248.00 KiB/s, 完成.
来自 https://gitlab.com/AlphaHinex/merge-refs-test
* [新引用] refs/merge-requests/1/merge -> origin/merge-requests/1/merge
show-ref
查看引用列表
之后可通过 show-ref
查看引用及对应的 commit id:
$ git show-ref
dcaeb64e20196eda19b7f71b86287566d987ea56 refs/heads/main
8f8976a512437c13784586460556dffeef53c645 refs/heads/mr
dcaeb64e20196eda19b7f71b86287566d987ea56 refs/remotes/origin/HEAD
dcaeb64e20196eda19b7f71b86287566d987ea56 refs/remotes/origin/main
f03da17f11a905fcc4766c97f05de2fa8c78ecda refs/remotes/origin/merge-requests/1/merge
8f8976a512437c13784586460556dffeef53c645 refs/remotes/origin/mr
也可以将 fetch
配置为 +refs/merge-requests/*:refs/remotes/origin/merge-requests/*
,同时获得 MR 的 head
和 merge
分支:
$ git fetch
来自 https://gitlab.com/AlphaHinex/merge-refs-test
* [新引用] refs/merge-requests/1/head -> origin/merge-requests/1/head
$ git show-ref
dcaeb64e20196eda19b7f71b86287566d987ea56 refs/heads/main
8f8976a512437c13784586460556dffeef53c645 refs/heads/mr
dcaeb64e20196eda19b7f71b86287566d987ea56 refs/remotes/origin/HEAD
dcaeb64e20196eda19b7f71b86287566d987ea56 refs/remotes/origin/main
8f8976a512437c13784586460556dffeef53c645 refs/remotes/origin/merge-requests/1/head
f03da17f11a905fcc4766c97f05de2fa8c78ecda refs/remotes/origin/merge-requests/1/merge
8f8976a512437c13784586460556dffeef53c645 refs/remotes/origin/mr
可以看到,共有三个不同的 commit id:
dcaeb64e20196eda19b7f71b86287566d987ea56
:对应本地及远程的main
分支及HEAD
引用8f8976a512437c13784586460556dffeef53c645
:对应本地及远程的mr
分支,以及merge-requests/1/head
引用f03da17f11a905fcc4766c97f05de2fa8c78ecda
:对应远程的merge-requests/1/merge
引用
左侧未显示完整的即为
merge-requests/1/merge
引用。
从本地和 GitLab 上的 main
分支及 mr
分支提交记录里可以找到前两个 commit id,而第三个 commit id 则是 GitLab 在远程仓库的 merge-requests/1/merge
分支上将 mr
分支合并至目标分支 main
自动创建的 commit 对应的 id。
为 merge
引用创建分支
$ git branch -a
* main
mr
remotes/origin/HEAD -> origin/main
remotes/origin/main
remotes/origin/merge-requests/1/head
remotes/origin/merge-requests/1/merge
remotes/origin/mr
$ git checkout merge-requests/1/merge
分支 'merge-requests/1/merge' 设置为跟踪来自 'origin' 的远程分支 'merge-requests/1/merge'。
切换到一个新分支 'merge-requests/1/merge'
$ git branch -a
main
* merge-requests/1/merge
mr
remotes/origin/HEAD -> origin/main
remotes/origin/main
remotes/origin/merge-requests/1/head
remotes/origin/merge-requests/1/merge
remotes/origin/mr
$ git status
位于分支 merge-requests/1/merge
您的分支与上游分支 'origin/merge-requests/1/merge' 一致。
无文件要提交,干净的工作区
此时即可直接在本地的 merge-requests/1/merge
分支上审查 MR 合并后的代码状态。
merge
引用行为验证
以下内容在 GitLab Community Edition v16.8.1 版本,及在线版 GitLab Enterprise Edition 17.3.0-pre 453542d17ca 中验证。
创建 MR 之前,是否会在远程库中出现 head/merge 分支
不会。
在 MR 分支上提交新 commit 时,merge 分支内容是否会同步变化?
会。但可能稍微有个延迟。
$ git checkout mr
切换到分支 'mr'
您的分支与上游分支 'origin/mr' 一致。
$ touch new-file-in-mr-branch
$ git add .
$ git commit -am "New commit in mr branch"
[mr 3436570] New commit in mr branch
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 new-file-in-mr-branch
$ git push origin mr
枚举对象中: 3, 完成.
对象计数中: 100% (3/3), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (2/2), 完成.
写入对象中: 100% (2/2), 306 字节 | 306.00 KiB/s, 完成.
总共 2(差异 0),复用 0(差异 0),包复用 0
remote:
remote: View merge request for mr:
remote: https://gitlab.com/AlphaHinex/merge-refs-test/-/merge_requests/1
remote:
To https://gitlab.com/AlphaHinex/merge-refs-test.git
8f8976a..3436570 mr -> mr
拉取远程库的 merge
引用:
$ git fetch origin
来自 https://gitlab.com/AlphaHinex/merge-refs-test
8f8976a..3436570 refs/merge-requests/1/head -> origin/merge-requests/1/head
如果拉取时没有 merge 引用的变化,可稍等一会之后再试:
$ git fetch remote: Enumerating objects: 1, done. remote: Counting objects: 100% (1/1), done. remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) 展开对象中: 100% (1/1), 248 字节 | 248.00 KiB/s, 完成. 来自 https://gitlab.com/AlphaHinex/merge-refs-test + f03da17...b20a111 refs/merge-requests/1/merge -> origin/merge-requests/1/merge (强制更新)
在目标分支上提交新 commit 时,merge 分支内容是否会同步变化?
也会,同样可能有个延迟。
$ git checkout main
$ touch new-file-in-main-branch
$ git add .
$ git commit -am "New commit in main branch"
[main 8a98bc0] New commit in main branch
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 new-file-in-main-branch
$ git push origin main
枚举对象中: 4, 完成.
对象计数中: 100% (4/4), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (2/2), 完成.
写入对象中: 100% (3/3), 299 字节 | 299.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0
To https://gitlab.com/AlphaHinex/merge-refs-test.git
dcaeb64..8a98bc0 main -> main
$ git fetch origin
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
展开对象中: 100% (2/2), 293 字节 | 146.00 KiB/s, 完成.
来自 https://gitlab.com/AlphaHinex/merge-refs-test
+ b20a111...2978ae6 refs/merge-requests/1/merge -> origin/merge-requests/1/merge (强制更新)
MR 分支新 commit 与目标分支新 commit 存在冲突时,merge 分支内容是否会同步变化?
此时 merge 分支不再同步变化,后续 MR 分支上的新提交 commit 也不会同步到 merge 分支上,需要处理冲突之后,才能恢复同步。
MR 关闭之后,是否还会同步更新 merge 分支内容?
不会了,重新开启 MR 后会继续同步更新。
参考资料
- [Commit Status Publisher] Allow refs/merge-requests/* in gitlab support
- TeamCity Trigger on Pull Request vs Trigger on Merge
- 6.3 GitHub - Maintaining a Project
- Git refs merge vs head in pull request
- Create merge refs for MRs (merge and squash methods)
- Consider using the merge URL on PR builds
- Difference of refs/pull-requests/
/merge and refs/pull-requests/ /from - Use merge request HEAD ref for detached merge request pipelines
- Able to push to /ref/merge-requests/*/head
- Merge requests API
- Gitlab 中文文档 - Merge requests API
- Merge request pipelines
- Using Git refs to check out GitLab Merge Requests, from your local repo