#!/usr/bin/env bash # Single entry point for all git operations in this skill. Designed so # there is never a reason to use `cd` or shell chaining (&&, ;, |) to run # git commands across different repos in one session. # # Usage: git_cmd.sh [--repo ] [-- ] # # Examples: # git_cmd.sh status # git_cmd.sh log --repo homelab-notes -- --oneline -10 # git_cmd.sh commit --repo homelab-notes -- -m "Update DNS notes" # git_cmd.sh push --repo homelab-notes -- origin main # # - must be one of the allowed subcommands in _lib.sh; anything # else is rejected before git is ever invoked. # - --repo is optional. If omitted, operates on the current working # directory (which must already be inside a git work tree) — this is what # replaces `cd && git ...`, since Claude Code already sets the # working directory per project/session. # - Everything after `--` is passed through to git as-is via argv (not # re-interpreted by a shell), so quoting/spaces in e.g. commit messages # are safe. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=_lib.sh source "$SCRIPT_DIR/_lib.sh" SUBCOMMAND="${1:-}" if [ -z "$SUBCOMMAND" ]; then echo "Usage: git_cmd.sh [--repo ] [-- ]" >&2 echo "Allowed subcommands: ${ALLOWED_SUBCOMMANDS[*]}" >&2 exit 1 fi shift if ! is_allowed_subcommand "$SUBCOMMAND"; then echo "Error: subcommand '$SUBCOMMAND' is not allowed." >&2 echo "Allowed subcommands: ${ALLOWED_SUBCOMMANDS[*]}" >&2 exit 1 fi REPO_NAME="" GIT_ARGS=() while [ $# -gt 0 ]; do case "$1" in --repo) REPO_NAME="${2:-}" shift 2 ;; --) shift GIT_ARGS=("$@") break ;; *) echo "Error: unexpected argument '$1'. Put git flags/args after '--'." >&2 exit 1 ;; esac done REPO_RAW="$(resolve_repo_path "$REPO_NAME")" REPO="$(canonicalize_and_check_repo "$REPO_RAW")" echo "== Repo: $REPO ==" echo "== Running: git $SUBCOMMAND ${GIT_ARGS[*]:-} ==" echo if [ "${#GIT_ARGS[@]}" -eq 0 ]; then git -C "$REPO" "$SUBCOMMAND" else git -C "$REPO" "$SUBCOMMAND" "${GIT_ARGS[@]}" fi