-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Git is hard. Git workflows are complex. Write code, not git commands. Test and deploy in a flash. Learn later.
mr is a CLI tool designed to automate routine git branch flow, such as deploying a feature branch across a complex multi-branch workflow.
MR stands for Merge Request (GitLab) or Pull Request (GitHub). Here MR stands for branch (ex.: a branch with name TASK-42).
mr was written to be as git hosting agnostic as possible. If you're ok with some setup, use glab cli or gh cli instead.
-
node -v>=18.12 -
git --version>=2.23-
git --version >= 2.11.0fallback added sincemr-git-cli 0.1.0
-
npm install -g mr-git-cli@latest
Try it without installing:
npx mr-git-cli TASK-42
# create branch (press Enter to accept)
$ mr TASK-42
# the default repo branch will be detected
Create new branch 'TASK-4444' from 'origin/main' [Y/n]?
> git fetch
> git switch --guess --merge --create TASK-4444 origin/main
Switched to a new branch 'TASK-4444'
# add 'from' to specify any parent branch
$ mr r43 from origin/release
# switch branch
$ mr release
> git switch --merge --guess release
$ mr TASK-42
> git switch --merge --guess TASK-42If you are using GitLab, you can create a GitLab merge request from the command line using push options
$ mr
> npm test
> git push --set-upstream origin TASK-42:TASK-42 -o merge_request.create
-o merge_request.title='TASK-42 this is first commit message of branch' -o merge_request.target=main
remote: View merge request for TASK-42:
remote: https://gitlab.local/jonny64/mr-git-cli/-/merge_requests/1
remote:
To ssh://gitlab.local/jonny64/mr-git-cli.git
* [new branch] TASK-42 -> TASK-42GitLab presence is detected by the 'git remote' URL and push options are added to git push to create a merge request:
- the first commit message of
git log --reverse --pretty=format:%s master..TASK-42is added as the MR title - leading digits of such title are converted to the format TASK-42 to create an external issue tracker link in the merge request title
- merge request target is set as
git config branch.TASK-42.mr-target(was set whenmrcreated the branch) -
git config branch.TASK-42.descriptionis set to prevent duplicates:- next time you use
mr, it checksgit config branch.TASK-42.descriptionand if it is non-empty, it does nothing to prevent duplicate merge requests.
- next time you use
If the branch is already pushed, GitLab push options do nothing. If there is no merge request, you can create it:
- either via the UI
- or delete the branch and re-create it with
mr:git push origin --delete TASK-42 && mr.
You can run merge (see below) at once: it will push as the first step
Typical workflow:
- a developer commits broken tests
- CI sends you an email about a broken pipeline
- you should fix it. NOW.
mr applies the shift-left principle:
- a developer commits broken tests
- the developer can't push:
mrruns tests BEFORE branch push - the developer has time to fix it
mr will run this command BEFORE any branch push (topic or integration):
$ git config mr.test 'npm test' # for code repo
$ git config mr.test 'yamllint .' # for ci repoYou can clear any config value via git config --unset
$ mr TASK-42 to release
> git push --set-upstream origin TASK-42:TASK-42
> git switch release
> git merge origin/TASK-42
> npm test
> git push --set-upstream
# merge current git branch to release
$ mr to releaseTypical workflow:
- merge to one integration branch (e.g.,
test) - merge to another integration branch (e.g.,
premain) - merge to
main - everything that goes to
mainshould already be merged to the preceding branches in this exact order.
To configure those dependencies:
$ git config --global branch.main.mr-merge-after test,premainThis will confirm merge to test first, then premain, then main (target branch) last (order matters).
Use either --global or --local setting per repository clone, see git config reference.
mr:
- checks if the branch was already merged via
git log --oneline origin/master..origin/srcBranch - produces merge commands for all dependent branches
$ mr hotfix to master
> git push --set-upstream origin hotfix:hotfix
Everything up-to-date
Ok, here is the plan:
git switch test
git merge origin/hotfix
npm test
git push --set-upstream
git switch master
git merge origin/hotfix
npm test
git push --set-upstream
git checkout hotfix
Proceed [Y/n]?
> git switch test
> git merge origin/hotfix
> npm test
> git push --set-upstream
> git switch master
> git merge origin/hotfix
> npm test
> git push --set-upstream $ echo "alias task=mr" >> ~/.bash_aliases
$ echo "alias deploy=mr" >> ~/.bash_aliases
$ source ~/.bash_aliases
$ task TASK-42 from production
Create new branch 'TASK-42' from origin/production ? y
> git switch --create --guess TASK-42
# yuck yuck
# git commit
$ deploy
remote: View merge request for TASK-42:
remote: https://gitlab.local/jonny64/mr-git-cli/-/merge_requests/1
$ deploy TASK-42 to production
> git push --set-upstream origin TASK-42:TASK-42
> git switch production
> git merge origin/TASK-42
> npm test
> git push --set-upstream