Create Merge Request
Create a GitLab merge request for the current branch targeting main.
Steps
-
Get the first commit message of the current branch (compared to main):
git log main..HEAD --reverse --format="%s" | head -n 1 -
Create the MR using glab, following the commit message conventions of the repo. Pick one of these two modes - never mix them (see "glab flag rules" below):
# A. You write the title and body (the usual case). No --fill. # Requires the branch to be pushed already, or add --push. glab mr create -t "<FIRST_COMMIT_MESSAGE>" -d "<SUMMARY_OF_WHAT_HAS_BEEN_DONE>" -b main -y # B. Derive both from the commit history. Pushes the branch itself. glab mr create --fill --fill-commit-body -b main -y
glab flag rules
Check glab mr create --help before reaching for a flag - glab is not gh, and
the installed version may predate a flag that exists upstream.
--fillwith both-tand-dis a hard error:usage of --title and --description overrides --fill. Mode A above drops--fillfor that reason.--description-filedoes not exist in anyglabversion. That isgh pr create --body-file. For a long body use-dwith the file contents, or-d -to open an editor (interactive only, so useless to an agent).--fill-commit-bodyrequires--fill:--fill-commit-body should be used with --fill.--templateis mutually exclusive with-d,--fill, and--related-issue, and is absent from older builds.- Non-interactive runs need either
-tor--fill, otherwise:--title or --fill required for non-interactive mode. --fillimplies--push; mode A does not, so push first.
Attaching a screenshot/image (optional)
A local image can't be embedded in an MR description directly - it must first be uploaded to the project, which returns ready-to-paste markdown.
-
Upload via the project uploads endpoint. Use raw
curl --form, notglab api(glab api -F file=@pathsends the file contents as a string field → HTTP 400, not a multipart upload):# URL-encode the project path: aircall/foo/bar -> aircall%2Ffoo%2Fbar curl -s --request POST \ --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \ --form "file=@/path/to/image.png" \ "https://gitlab.com/api/v4/projects/<URL-ENCODED-PROJECT-PATH>/uploads" \ -o /tmp/upload.json python3 -c "import json; print(json.load(open('/tmp/upload.json'))['markdown'])"The response
markdownfield looks like. -
Put that markdown in the MR description. For a multi-line body, write it to a file and pass its contents to
-d- there is no--description-file:glab mr create -t "<TITLE>" -d "$(cat /tmp/mr_body.md)" -b main -y # bash/zshIn fish the substitution is
-d (cat /tmp/mr_body.md); simplest is to put the whole invocation in a.shfile and runbash script.sh.
Notes
- Ensure the branch has been pushed before running this command
- The MR title will be the first commit message of the branch
- Reviewer/assignee: add
--reviewer <username>and--assignee @me(e.g.--reviewer pierre.goutheraud). Requesting a review pings the reviewer. - Token for the upload curl:
glabauthenticates via the$GITLAB_TOKENenv var - use it directly. Itsconfig.ymltoken is often!!null, andglab auth status --show-tokenprints it on aToken found:line (notToken:), so don't try to scrape it. - fish shell gotcha: if the shell is fish,
VAR=$(...)command substitution fails to parse - write the commands to a.shfile and runbash script.sh. Also prefercurl -o file.jsonover piping curl intopython json.load(piped reads can truncate).