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 initsogit wt switchchanges 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-wtcompletes the standalonegit-wtcommand_git_wtbridgesgit 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, orafterremoveGIT_WT_PATH: absolute worktree pathGIT_WT_BRANCH: branch name, or empty for detached or unresolved casesGIT_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
추천 도구
다른 키워드를 입력하거나 필터를 제거해 보세요.
설치
npx skillfish add ahmedelgabri/git-wt