Skip to content

Git

Convenience recipes for inspecting, working with, and cleaning up git repositories. All recipes run in the current directory ([no-cd]).

Info

log shows a compact graph of the last 30 commits — useful for orienting yourself on a branch. branches lists all branches (local and remote) sorted by most recent commit, so stale branches sink to the bottom. recent filters to commits from the last 7 days. stats gives a per-author commit count. stashes lists the stash stack.

inspect [branch] (defaults to current; -i for fzf picker) shows enough about a branch to decide whether it's safe to delete: tip (sha + date + author + subject), upstream state, and which other refs (local + remote) also contain the tip. The "Contained in" line is the key fact — if it's empty AND upstream is gone or absent, deleting the branch will orphan its unique commits (recoverable via reflog for ~90 days, or until git gc --prune=now runs).

leak-check runs betterleaks against unpushed commits (@{u}..HEAD) — the same scan the pre-push hook performs, but on demand. Useful before a push when you want manual confirmation a stack is clean. --full / -f widens to every reachable object (branches, tags, stashes, reflog) — findings inside stashes are usually safe (stashes don't push) but worth knowing about if you intend to share the .git/ or unstash old work.

Upstream-state shorthand (from git status / git for-each-ref):

Display Meaning
up-to-date local matches upstream
[ahead N] local has N commits upstream doesn't — git push to publish
[behind N] upstream has N you don't — git pull (or rebase) to catch up
[ahead N, behind M] diverged, both sides have unique commits — rebase or merge to reconcile
[gone] upstream ref deleted (e.g. PR merged + branch removed on the remote)
none (never tracked) branch has no upstream tracking ref configured

Config

get-identity shows the current repo's user.name and user.email — quick check before pushing under the wrong identity. set-identity sets them (defaults to the dotfiles identity). Useful when cloning into a fresh repo that doesn't yet have an identity, or when switching between work and personal repos. The dotfiles config has useConfigOnly = true, which refuses commits without an explicit per-repo identity.

Workflow

undo soft-resets the last commit — changes stay staged. Use this when you committed too early or with the wrong message. Follow up with git commit to redo it. Always asks for confirmation; if the commit has been pushed you get a second confirmation about rewriting shared history (you will need to force-push afterwards).

amend folds staged changes into the last commit. Default opens $EDITOR on the commit message (matching git commit --amend); pass -n / --no-edit to keep the existing message. Always asks for confirmation; if the commit has been pushed you get a second confirmation about rewriting shared history (force-push afterwards).

unstage removes everything from the staging area without touching the working tree. Equivalent to git reset HEAD.

checkpoint creates a stash backup of all changes (including untracked files), verifies the working tree is clean, then restores your working tree. The stash entry remains as a safety net. Does nothing if the tree is already clean. The default message includes a timestamp but you can override it: just git checkpoint "before big refactor".

wip / unwip are a paired workflow. wip stages everything (including untracked files) and commits with the message chore: wip checkpoint — it shows what was staged so you can spot surprises. The conventional-commits prefix (chore:) is required because the commit-msg hook enforces format. unwip reverses it by matching the exact subject string, so you won't accidentally undo real work.

move-to-branch rescues commits made on the wrong branch ("I committed to main by mistake"). Moves the last N commits from the current branch to a new (or fork-aligned) target via ref shuffling — original commit SHAs preserved, no replay, no merge conflicts mid-operation. Target must be new or already at the fork point (HEAD~N); for other target states (divergent, behind, unrelated) the recipe refuses and prints exact copy-pasteable cherry-pick / rebase commands.

just git move-to-branch feature/my-fix       # move last commit
just git move-to-branch feature/my-fix 3     # move last 3 commits

Design rationale, primitive comparison table, refusal reasons, and manual workflows for each primitive live in the DESIGN NOTES block at the top of ~/.local/bin/git-move-to-branch.sh.

Cleanup

prune [branch] deletes a single local branch with informed confirmation:

  • No arg: picks from branches merged into current (fzf if available, numeric menu fallback). Protected branches and the current branch are never offered.
  • Named: skips the picker, goes straight to inspect + confirm. Protected branches are refused before deletion (the picker filter doesn't apply on this path).

Protected patterns live in home/.chezmoidata/data.yaml under git.protected_branches — bash regex, not auto-anchored. Defaults match exact main/master/develop and any branch with release in the name (e.g. release/v1, pre-release). Edit the data file to add patterns.

Always shows inspect output for the branch first so you see the tip, upstream state, and which other refs also contain the commits — then asks to confirm. Uses git branch -d (safe delete); refuses unmerged branches. "Merged" here is relative to your current branch — a branch may show as merged into feature/A while never reaching main. The inspect output's "Contained in" line tells you which other refs hold the commits.

gc runs git gc by default — compacts the object database, prunes unreachable objects older than 2 weeks (gc.pruneExpire). Recent orphaned commits/stashes stay recoverable via git fsck --lost-found. Pass -p/--prune-now to purge unreachable objects immediately — destructive, inline danger confirmation, no recovery after.

nuke is a destructive reset: discards all uncommitted changes and removes untracked files. Two confirmations (one for the recipe, one for _ensure-really-sure) because there's no recovery. Use to get back to a known clean state.