The branch-based approach that GitLab merge request uses can slow things down
when you really want to create dependent MRs so they can be reviewed in
parallel. With great amount of manual effort and carefulness, you can actually
achieve that by setting an MR's target branch to the one it's dependent on and
making sure before merging any MRs, you change their target branch back to
master
(or any default main branch in your project). This becomes pretty
error-prone with more than 2 MRs, not to mention that you must merge the MRs
strictly following the dependency order (otherwise, branches can be
accidentally deleted where outstanding MRs still have dependencies).
Does this somehow remind you of the good things about Gerrit? Yeah, in Gerrit, nothing stops you from creating dependent reviews, since every commit creates a new review. To bring this Gerrit-style code review to GitLab repos, this project implements a "git lab" command that greatly simplifies the steps to create/update/merge MRs.
Clone this repo and install the package.
$ git clone https://github.com/yaoyuannnn/gerritlab.git
$ cd gerritlab
$ pip install .
A .gitreview
file can be created in a repo to configure how Gerritlab
operates for a given remote. The .gitreview
is an INI file with sections
naming remotes. In each section the following optional settings are allowed:
host
: The base URL of the GitLab server. By default, this is extracted from the git remote URL.target_branch
: The target branch that you want the MRs to eventually merge into. By default,target_branch
is whatever the default branch of the GitLab repo is.remove_source_branch
: Boolean value, indicating whether the source branch of an MR should be deleted once it's merged. By default,remove_source_branch
isTrue
.
Example .gitreview
:
[origin]
host=https://gitlab.example.com
target_branch=main
remove_source_branch=True
GerritLab requires a GitLab private token with api access.
You have the option to store it either in:
git config
- git credential helper
To store in your git config:
$ git config --global gerritlab.private-token "[your-private-token]"
# OR
$ git config --local gerritlab.private-token "[your-private-token]"
A more secure option is to use a git credential store.
If you've configured a credential.helper
in git, then GerritLab will prompt
you for a username and token and attempt to store it in your credential helper.
This is all that's needed for helpers supporting the store
action (e.g.,
osxkeychain, libsecret).
But if you're using a credential store which does NOT support the store
action (e.g., pass-git-helper), then you'll need to manually store your GitLab
token where GerritLab expects to find it.
GerritLab expects to find credentials stored as the host
from your .gitreview
.
For example, if your host is https://gitlab.com
, GerritLab will look for your GitLab
username and token in your credential helper under
https://gitlab.com/
.
Git credential helpers are available for nearly every operating system and password store.
For more details, see:
We need a commit-msg hook that will add a Change-Id to every commit. This Change-Id will be used as the key to find if there's an existing MR in the GitLab repo. The following installs the commit-msg hook to your project.
$ git lab --setup
Commits created/amended after installation of the hook will automatically have a Change-Id added. Commits created prior to the installation of the hook will need to amended so that they'll get the Change-Id added on.
To create/update MRs, simply do:
$ git lab
This will create/update an MR for each commit on the current branch that's
ahead of origin/master
(if master
is the target_branch
). Note that if
you want to create/update MRs in a remote other than the default origin
, do
git lab my-remote
. If a commit finds an existing MR with the same
Change-Id in the GitLab repo, the MR will be updated with new commit. The
following shows an example that creates 3 new MRs.
$ git lab origin
SUCCESS
New MRs:
* https://gitlab.example.com/arch/myproject/-/merge_requests/3719 tests: Add commit a.
master-2c77 -> master
* https://gitlab.example.com/arch/myproject/-/merge_requests/3720 tests: Add commit b.
master-857b -> master-2c77
* https://gitlab.example.com/arch/myproject/-/merge_requests/3721 tests: Add commit c.
master-79e5 -> master-857b
To ssh://[email protected]:12051/arch/myproject.git
For merging MRs, use the same git command with a -m
or --merge
flag to
merge any mergeable MRs created off of the current branch, which takes into
account the MR dependency chain.
$ git lab -m
Merging merge requests:
* https://gitlab.example.com/myproject/-/merge_requests/110 tests: Add commit a.
[mergeable]: True
* https://gitlab.example.com/myproject/-/merge_requests/111 tests: Add commit b.
[mergeable]: True
* https://gitlab.example.com/myproject/-/merge_requests/109 tests: Add commit c.
[mergeable]: True
SUCCESS
New Merged MRs:
* https://gitlab-master.example.com/myproject/-/merge_requests/110 tests: Add commit a.
master -> master-2c77 (master)
* https://gitlab-master.example.com/myproject/-/merge_requests/111 tests: Add commit b.
master -> master-857b (master)
* https://gitlab-master.example.com/myproject/-/merge_requests/109 tests: Add commit c.
master -> master-79e5 (master)
To ssh://[email protected]:12051/myproject.git
$ pip install -e .
This will make a git lab
command available which points to your
development checkout (assuming you have pip's local bin directory in
your PATH).
Integration tests require a submodule at unit_tests/gerritlab_tests
, with a
Gitlab upstream and a personal access token configured (project access tokens
cannot delete MRs).
Tests can then be triggered using ./unit_tests/merge_request_test.py
or just
pytest
.