diff options
author | Adam House <a@context.town> | 2024-06-21 08:22:41 -0500 |
---|---|---|
committer | Adam House <a@context.town> | 2024-06-21 08:22:41 -0500 |
commit | 964d68dbe94ee3be5d95086b61ed21e3df19917b (patch) | |
tree | 6f9421a43907e625e775f305c54ba49156e5a579 |
-rw-r--r-- | LICENSE | 3 | ||||
-rw-r--r-- | README.md | 37 | ||||
-rwxr-xr-x | ag | 122 |
3 files changed, 162 insertions, 0 deletions
@@ -0,0 +1,3 @@ +CC0, No Rights Reserved + +https://creativecommons.org/publicdomain/zero/1.0/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f98b20 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# ag + +*Adam's Git* + +`ag` is a trivial shell script to wrap git, adding new commands of use to me +during my professional work. If `ag` doesn't recognize a command, it falls back +to git. + +## Usage + +The added commands are: + +* `ag review`: Accepts a GitLab MR number; fails if the remote is not GitLab. +Pulls the branch associated with that MR number if it exists, displays the +author and description, then displays the diff compared to latest main. After +quitting from the diff, asks whether the MR is approved. If so, approval +is pushed to GitLab, else nothing is done. Then deletes the local branch +and switches back to main or master if available. Requires +[jq](https://jqlang.github.io/jq/) and +[glab](https://gitlab.com/gitlab-org/cli). + +* `ag scrub`: If main or master exists (checked in that order), switches to it, +deletes all other local branches, and pulls latest changes from remote. + +* `ag submit`: If on main or master branch, accepts a branch name as an +argument, switches to that branch prefixed with `ajwh/`, commits all changes +(opening `$EDITOR` as usual for commit message), and pushes them to the new +branch. If already on a branch prefixed with `ajwh/`, amend prior commit and +force-push to the current branch. If neither scenario applies, do nothing. + +## Motivation + +These commands help with workflows I perform during full-time work as a software +engineering manager, and are therefore opinionated procedures. I don't expect +others will get much use from this, but I display it publicly (a) for fun and +(b) because it may inspire others to wrap git for their convenience. We're all +better off automating. ([Within reason!](https://xkcd.com/1205/)) @@ -0,0 +1,122 @@ +#!/bin/bash + +submit() { + current_branch=$(git rev-parse --abbrev-ref HEAD) + + if [[ "$current_branch" == ajwh/* ]]; then + # Amend commit, opening $EDITOR for commit message modification + git add . + git commit --amend + git push origin "$current_branch" --force + elif [ "$current_branch" == "main" ] || [ "$current_branch" == "master" ]; then + # Check if branch name is provided + if [ -z "$1" ]; then + echo "no branch name" + exit 1 + fi + + # Prefix the new branch name with "ajwh/" + new_branch="ajwh/$1" + + git checkout -b "$new_branch" + git add . + git commit + git push --set-upstream origin "$new_branch" + else + echo "not on main, master, or 'ajwh/'-prefixed branch" + fi +} + +scrub() { + if git show-ref --verify --quiet refs/heads/main; then + default_branch="main" + elif git show-ref --verify --quiet refs/heads/master; then + default_branch="master" + else + echo "no main or master branch" + exit 1 + fi + + git checkout "$default_branch" + git branch | grep -v "$default_branch" | xargs git branch -D + git pull origin "$default_branch" +} + +review() { + remote_url=$(git config --get remote.origin.url) + if [[ "$remote_url" != *"gitlab.com"* ]]; then + echo "remote is not a gitlab repo" + exit 1 + fi + + if ! glab mr view "$1" --repo "$remote_url" > /dev/null 2>&1; then + echo "mr #$1 does not exist in this repo" + exit 1 + fi + + mr_status=$(glab mr view "$1" --repo "$remote_url" --output json | jq -r .status) + if [[ "$mr_status" == "closed" || "$mr_status" == "merged" ]]; then + echo "note: mr #$1 is $mr_status" + sleep 1 + fi + + branch_name=$(glab mr view "$1" --repo "$remote_url" --output json | jq -r .source_branch) + + git checkout "$branch_name" + git pull origin "$branch_name" + + author_username=$(glab mr view "$1" --repo "$remote_url" --output json | jq -r .author.username) + echo "author: $author_username" + sleep 1 + + mr_description=$(glab mr view "$1" --repo "$remote_url" --output json | jq -r .description) + echo "$mr_description" | less + + git fetch origin main + git diff "origin/main" "$branch_name" + + echo -n "approve mr? [y/N]: " + read -r approval + if [[ "$approval" == [yY] ]]; then + glab mr approve "$1" --repo "$remote_url" + fi + + if git show-ref --verify --quiet refs/heads/main; then + default_branch="main" + elif git show-ref --verify --quiet refs/heads/master; then + default_branch="master" + else + echo "no main or master branch" + exit 1 + fi + + git checkout "$default_branch" + git branch -D "$branch_name" +} + +# Function to pass through to git +fallback() { + git "$@" + exit_status=$? + if [ $exit_status -ne 0 ]; then + echo "Usage: ag <command> [arguments]" + echo "Commands:" + echo " submit [branch-name] - Create or amend a branch prefixed with 'ajwh/'." + echo " Branch name is required for new branches." + echo " scrub - Cleans local branches and resets to default branch state." + echo " review <mr-number> - Reviews a merge request on GitLab." + echo "Other commands pass to underlying git." + fi +} + +case "$1" in + submit|scrub) + "$1" "${@:2}" + ;; + review) + review "$2" + ;; + *) + fallback "$@" + ;; +esac |