git-mate
A focused Git CLI extension for workflows that blend branch checkout with optional worktrees. Built for my specific workflow using git.
Requirements
- Rust (for building from source)
gitgh(GitHub CLI, for issue/PR integration)
Installation
Because the binary is named git-mate, Git's extension mechanism picks it up automatically — no aliases needed. Every command is available as git mate <cmd> immediately after installation.
Then add the following to your .zshrc, .bashrc, or config.fish to enable automatic directory switching:
This installs a shell function that wraps git-mate and handles automatic cd for commands that change your working directory (new, co, finish). Without it, git-mate still works but won't navigate your shell.
Commands
git mate init <shell>
Prints the shell integration script to stdout. Pipe it through eval in your shell config to enable automatic directory switching.
git mate new <branch>
Creates a new branch from the default branch (main or master, auto-detected) and switches to it.
git mate co <branch>
Checks out an existing branch — local or remote. If the branch already exists in a worktree, navigates there instead.
When passing a GitHub issue number, git-mate uses gh to look up the associated branch. If no branch exists yet, it prompts you to create one.
git mate finish [branch]
You're done with a branch. Cleans up and returns you to the main worktree.
- If you're inside a linked worktree: removes the worktree, navigates to main
- If you're in the main worktree on a feature branch: switches to the default branch
- Optionally deletes the local branch with
--delete-branch(only if merged)
git mate sync
Fetches all remotes and prunes stale local tracking references. Optionally cleans up local branches whose upstream is gone.
git mate list
Shows all worktrees with their branch and status. Marks the main worktree and highlights dirty state.
# main /home/markus/project [main]
# worktree /home/markus/project-login [feature/login] (dirty)
# worktree /home/markus/project-auth [feature/auth]
Worktree location
By default, worktrees are created as siblings of the main worktree, named after the branch:
~/projects/
my-repo/ ← main worktree
my-repo-feature-login/ ← worktree for feature/login
my-repo-feature-auth/ ← worktree for feature/auth
Override the base path in config (see below).
Configuration
git-mate reads configuration from git config, giving you global defaults with per-repo overrides for free.
# Set global defaults
# Override for a specific repo (run inside that repo)
Or edit ~/.gitconfig and .git/config directly:
# ~/.gitconfig
[gwt]
worktreeBase = ~/worktrees
copyFiles = .env,.env.local
# .git/config (per-repo override)
[gwt]
worktreeBase = ../worktrees
postCreate = npm install
| Key | Description | Default |
|---|---|---|
mate.worktreeBase |
Where to create linked worktrees | sibling of main worktree |
mate.postCreate |
Command to run after creating a worktree | — |
mate.copyFiles |
Comma-separated files to copy from main worktree | — |
How the shell integration works
git mate init <shell> outputs a small shell function that wraps the git-mate binary. When commands need to change your working directory, the binary prints a directive to stdout:
GWT_CD:/path/to/worktree
The shell function captures this and calls cd in the current shell process. All other output passes through unchanged. This is the same approach used by zoxide and direnv — the binary itself never touches your shell state directly.
Non-goals
- GUI or TUI — this is a keyboard-first tool
- Bare repository workflows — regular clones only
- Replacing
git—git-mateshells out togitandgh, it doesn't reimplement them