AG

ahmedelgabri/git-wt

Developer tools
78 stars 품질 70 트렌드 70

A git custom command that enhances Git's native worktree functionality with interactive features, automation, and repository migration capabilities.

개요

A Git custom command that makes Git worktrees easier to use with interactive selection, safer destructive flows, repository migration, diagnostics, and compact dashboards. git-wt uses the structure where Git data lives in .bare/ and each branch gets its own sibling worktree directory. Git worktrees let you keep multiple branches checked out at the same time in separate directories. They are useful for: - working on multiple features in parallel without stashing - reviewing PRs while keeping local work intact - comparing implementations side by side - running tests on one branch while developing on another - with .bare/ for Git data - flows with fzf - with git wt init so git wt switch changes directory automatically - around worktree creation and removal (wt.beforeadd, wt.afteradd, wt.beforeremove, wt.

README

git-wt

A Git custom command that makes Git worktrees easier to use with interactive selection, safer destructive flows, repository migration, diagnostics, and compact dashboards.

git-wt uses the bare repository structure where Git data lives in .bare/ and each branch gets its own sibling worktree directory.

Why Git Worktrees?

Git worktrees let you keep multiple branches checked out at the same time in separate directories. They are useful for:

  • working on multiple features in parallel without stashing
  • reviewing PRs while keeping local work intact
  • comparing implementations side by side
  • running tests on one branch while developing on another

Features

  • Bare clone structure with .bare/ for Git data
  • Interactive add / switch / remove flows with fzf
  • Shell integration with git wt init so git wt switch changes directory automatically
  • Lifecycle hooks around worktree creation and removal (wt.beforeadd, wt.afteradd, wt.beforeremove, wt.afterremove)
  • Repository migration from a standard repo to the bare worktree layout
  • Safe cleanup filters with git wt remove --sweep
  • Repository diagnostics with git wt doctor
  • Status dashboard with git wt status
  • Structured output with git wt list --json
  • Agent skill installer with git wt agent-skill
  • Dry-run support for destructive operations
  • Preserves uncommitted changes, stashes, remotes, and repo-local config during migration

Dependencies

  • git (2.48.0+ for relative worktree support)

Installation

Homebrew

brew install ahmedelgabri/tap/git-wt

Shell completions are installed automatically for bash, zsh, and fish.

mise

mise use "github:ahmedelgabri/git-wt"

Nix Flakes

Add to your flake inputs:

{
  inputs.git-wt.url = "github:ahmedelgabri/git-wt";
}

Then add to your packages:

inputs.git-wt.packages.${system}.default

Or run directly:

nix run github:ahmedelgabri/git-wt

Manual installation

Download the latest release archive for your platform from the releases page:

curl -sL https://github.com/ahmedelgabri/git-wt/releases/latest/download/git-wt-VERSION-OS-ARCH.tar.gz | tar xz
cp git-wt-VERSION-OS-ARCH/git-wt ~/.local/bin/

Replace VERSION with the current release version and choose the correct platform archive.

Shell completions

For manual installs, the release archives include a completions/ directory:

# Bash
cp completions/git-wt.bash ~/.local/share/bash-completion/completions/git-wt

# Zsh
cp completions/_git-wt ~/.local/share/zsh/site-functions/_git-wt
cp completions/_git_wt ~/.local/share/zsh/site-functions/_git_wt # enables `git wt` completion

# Fish
cp completions/git-wt.fish ~/.config/fish/completions/git-wt.fish

For zsh, both completion files are needed:

  • _git-wt completes the standalone git-wt command
  • _git_wt bridges git wt ... when git/oh-my-zsh-style completion wrappers dispatch to the underscore form

Agent skill

Install an Agent Skills-compatible skill so coding agents can discover and use git-wt workflows:

git wt agent-skill

By default this writes ~/.agents/skills/git-wt/SKILL.md. Use git wt agent-skill --dir ~/.claude/skills for a different skill root, --print to review the skill, or --force to overwrite an existing copy.

Usage

Clone with the bare worktree layout

git wt clone https://github.com/user/repo.git

This creates:

repo/
├── .bare/         # Git data (bare repository)
├── .git           # gitdir pointer to .bare
└── main/          # Worktree for the default branch

Migrate an existing repository

cd existing-repo
git wt migrate

This converts a standard Git repository into the bare worktree layout while preserving tracked changes, untracked files, stashes, remotes, and selected repo-local config.

Create a worktree

# Interactive mode

git wt add

# From a remote branch
git wt add feature origin/feature

# Create a new branch
git wt add -b new-feature new-feature

# Detached, locked, or quiet modes
git wt add --detach hotfix HEAD~5
git wt add --lock -b wip wip-branch
git wt add --quiet -b feature feature

Switch worktrees

cd "$(git wt switch)"

Shell integration (automatic cd)

A subprocess can never change its parent shell’s directory, so by default switch prints the worktree path. The init command emits a small shell script that wraps the binary and runs the cd for you:

# bash (~/.bashrc)
eval "$(git-wt init bash)"

# zsh (~/.zshrc)
eval "$(git-wt init zsh)"

# fish (~/.config/fish/config.fish)
git-wt init fish | source

After sourcing, git wt switch changes directory directly. Only switch is intercepted: add keeps printing the created worktree path to stdout so scripts and hooks (like the Claude Code WorktreeCreate hook below) can rely on it. The script also defines a thin git() wrapper so the git wt spelling works; if another tool already wraps git, use eval "$(git-wt init zsh --no-git-wrapper)" and invoke git-wt switch instead.

Known limitation: the wrapper keys on the first argument, so global git flags before the subcommand (e.g. git -C wt switch) bypass it and print the path instead of changing directory.

Remove a worktree and local branch

git wt remove feature-branch
git wt remove --dry-run feature-branch

Remove a worktree and local + remote branch

git wt remove feature-branch --delete-remote

Sweep safe cleanup candidates

git wt remove --sweep

git wt remove --sweep --dry-run

Inspect repository health

git wt doctor

Show worktree status

git wt status

List worktrees

git wt list
git wt list --json
git wt list --porcelain

Update the default branch

git wt update # or: git wt u

Hooks

Run shell commands around worktree creation and removal. Hooks are configured through Git config, so they can be scoped per repository or globally with --global.

# Validate the repository before creating a worktree
git config --add wt.beforeadd './scripts/check-worktree.sh'

# Copy generated files into each new worktree
git config --add wt.afteradd 'cp ../main/compile_commands.json .'

# Clean up files while the worktree still exists
git config --add wt.beforeremove './scripts/cleanup-worktree.sh'

# Notify another tool after removal is complete
git config --add wt.afterremove 'workspace-registry remove "$GIT_WT_PATH"'
Hook When it runs Working directory Failure behavior
wt.beforeadd After add arguments and fetching are complete, immediately before creation Bare repository root Prevents worktree creation
wt.afteradd After creation and upstream configuration New worktree Leaves the worktree in place and exits non-zero
wt.beforeremove Immediately before removal Worktree being removed Preserves the worktree and exits non-zero
wt.afterremove After worktree and branch cleanup Bare repository root Removal remains complete and the command exits non-zero

Every hook receives the lifecycle context through environment variables:

  • GIT_WT_EVENT: beforeadd, afteradd, beforeremove, or afterremove
  • GIT_WT_PATH: absolute worktree path
  • GIT_WT_BRANCH: branch name, or empty for detached or unresolved cases
  • GIT_WT_BARE_ROOT: absolute bare repository root

Each configured value runs with sh -c. Repeated git config --add values run in order and stop at the first failure for that event; multiline values are supported. Hook output goes to stderr so successful git wt add output remains machine-readable.

Before-hooks are not transactional: the subsequent Git operation can still fail after a hook succeeds, so side effects should be idempotent. After-hook failures cannot roll back an operation that already completed. Removing the current worktree or a locked worktree is rejected before any hook runs; for stale, missing, or prunable worktrees the removal proceeds with the hooks skipped. DEBUG=1 echoes hooks instead of running them.

Hooks apply to git wt add and git wt remove; the initial worktree created by git wt clone does not trigger add hooks.

Commands

Command Description
clone Clone a repo with the bare worktree structure
migrate Convert an existing repo to the bare worktree structure
add [options] ... Create a new worktree
remove / rm Remove worktrees directly or by safe cleanup filters
doctor Run repository diagnostics
agent-skill Install the git-wt agent skill
init Print shell integration for automatic directory switching
status Show a compact dashboard for linked worktrees
list List worktrees with table, JSON, or passthrough Git output
switch Interactively select a worktree
update / u Fetch remotes and update the default branch

Native git worktree commands (lock, unlock, move, prune, repair) are also supported as pass-through commands.

Claude Code Integration

Claude Code can create and remove worktrees automatically during agentic sessions. Configure the WorktreeCreate and WorktreeRemove hooks in your project or user settings.json to delegate those operations to git wt, keeping every worktree consistent with the bare repository layout:

{
  "WorktreeCreate": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "git wt add \"$(cat /dev/stdin | jq -r '.name')\""
        }
      ]
    }
  ],
  "WorktreeRemove": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "echo y | git wt rm \"$(cat /dev/stdin | jq -r '.worktree_path')\""
        }
      ]
    }
  ]
}

The hooks receive a JSON payload on stdin. WorktreeCreate reads the .name field (the branch name) and passes it to git wt add. WorktreeRemove reads .worktree_path and passes it to git wt rm; the leading echo y | confirms the interactive prompt non-interactively.

Development

# Enter development shell
nix develop

# Format code
nix fmt

# Run all checks
nix flake check

License

MIT

View this README on GitHub

추천 도구

다른 키워드를 입력하거나 필터를 제거해 보세요.

설치

npx skillfish add ahmedelgabri/git-wt