@shutootaki/gwm
Version:
git worktree manager CLI
282 lines (191 loc) • 8.81 kB
Markdown
<p align="center">
<strong>English</strong> | <a href="README_JA.md">日本語</a>
</p>
# gwm – Git Worktree Manager
A CLI tool for managing Git worktrees, allowing you to work on multiple branches simultaneously.
<div align="center">
[](https://www.npmjs.com/package/@shutootaki/gwm)
[](LICENSE)
[](https://github.com/shutootaki/gwm/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/@shutootaki/gwm)
</div>
## What problem does gwm solve?
When reviewing multiple PRs or working on a hotfix while developing another feature, you end up running `git stash` and `git checkout` repeatedly. gwm uses Git's worktree feature to **manage separate directories for each branch**.
- Switch branches without stashing
- Create worktrees from remote branches instantly
- Auto-detect and remove merged worktrees
## Commands
| Command | Description |
| ----------------------- | -------------------------------------------- |
| `gwm list` / `gwm ls` | List worktrees |
| `gwm add` | Create a new worktree |
| `gwm go` | Jump to a worktree or open in VS Code/Cursor |
| `gwm remove` / `gwm rm` | Remove worktrees |
| `gwm clean` | Detect and remove merged worktrees |
| `gwm pull-main` | Run `git pull` in main worktrees |
Run `gwm help <command>` for details on each command.
## Installation
```bash
npm install -g @shutootaki/gwm
# Try without installing
npx @shutootaki/gwm
```
## Usage
**Start working on a new branch:**
```bash
gwm add feature/new-login --code # Create worktree and open in VS Code
```
**Review a PR:**
```bash
gwm add fix-bug -r --code # Create worktree from remote branch and open in VS Code
# After review
gwm remove fix-bug # Remove it
```
**Clean up old worktrees:**
```bash
gwm clean # Detect and remove merged worktrees
```
## Directory Layout
Worktrees are created at:
```
~/git-worktrees/<repository-name>/<branch-name>/
```
Example: `~/git-worktrees/my-app/feature-login/`
## Configuration
Customize behavior in `~/.config/gwm/config.toml`.
### Configuration Options
| Option | Description | Default |
| ------------------------------------- | ------------------------------------------ | -------------------- |
| `worktree_base_path` | Directory to create worktrees | `~/git-worktrees` |
| `main_branches` | Branch names treated as main branches | `["main", "master"]` |
| `clean_branch` | Delete local branch when removing worktree | `"ask"` |
| `copy_ignored_files.enabled` | Copy gitignored files to new worktrees | `false` |
| `copy_ignored_files.patterns` | File patterns to copy | `[]` |
| `copy_ignored_files.exclude_patterns` | File patterns to exclude from copying | `[]` |
| `hooks.post_create.enabled` | Run hooks after worktree creation | `true` |
| `hooks.post_create.commands` | Commands to run after creation | `[]` |
**`clean_branch` values:**
- `"auto"`: Auto-delete if safe
- `"ask"`: Prompt for confirmation (default)
- `"never"`: Never delete
### Example Configuration
```toml
worktree_base_path = "/Users/me/worktrees"
clean_branch = "ask"
[copy_ignored_files]
enabled = true
patterns = [".env", ".env.*", ".env.local"]
exclude_patterns = [".env.example", ".env.sample"]
[hooks.post_create]
commands = ["npm install"]
```
### Project-specific Configuration
Create `gwm/config.toml` in your repository for project-specific settings. Project settings override global settings.
**Example: Use pnpm for this project**
`my-project/gwm/config.toml`:
```toml
[hooks.post_create]
commands = ["pnpm install"]
```
### Hook Environment Variables
The following environment variables are available during `post_create` hooks:
| Variable | Description |
| ------------------- | --------------------------------- |
| `GWM_WORKTREE_PATH` | Absolute path to the new worktree |
| `GWM_BRANCH_NAME` | Branch name |
| `GWM_REPO_ROOT` | Git repository root path |
| `GWM_REPO_NAME` | Repository name |
## Command Reference
### `gwm list` (alias: `ls`)
List worktrees in the current project.
```text
STATUS BRANCH PATH HEAD
* feature/new-ui /Users/me/project a1b2c3d
M main ~/git-worktrees/project/main 123abc4
- hotfix/logfix ~/git-worktrees/project/logfix c7d8e9f
```
**STATUS meanings:**
- `* ACTIVE`: Current worktree
- `M MAIN`: Main branches (main, master, etc.)
- `- OTHER`: Other worktrees
---
### `gwm add [branch_name]`
Create a new worktree.
**Without arguments (`gwm add`):**
- Opens interactive UI for entering a new branch name
- Press `Tab` to switch to remote branch selection mode
**With arguments:**
- `gwm add feature/new-login`: Create new branch and worktree
- `gwm add existing-branch`: Create worktree from existing local branch
- `gwm add pr-branch -r`: Create worktree from remote branch
**Options:**
| Option | Description |
| ----------------- | ---------------------------------------------------- |
| `-r, --remote` | Create from remote branch |
| `--from <branch>` | Base branch (default: main or master) |
| `--code` | Open in VS Code after creation |
| `--cursor` | Open in Cursor after creation |
| `--cd` | Change to worktree directory (for shell integration) |
| `--skip-hooks` | Skip post_create hooks execution |
**Automatic file copying:**
When `copy_ignored_files` is enabled, `.env` files are automatically copied from the main worktree to the new worktree.
---
### `gwm go [query]`
Select a worktree and jump to it (launches a subshell).
- `gwm go`: Interactive selection
- `gwm go feat`: Filter by "feat" and select
**Options:**
| Option | Description |
| ------------ | --------------- |
| `-c, --code` | Open in VS Code |
| `--cursor` | Open in Cursor |
---
### `gwm remove [query]` (alias: `rm`)
Interactively select and remove worktrees. Supports multi-select.
**Options:**
| Option | Description |
| ----------------------- | -------------------------------------------------- |
| `-f, --force` | Force delete even with uncommitted changes |
| `--clean-branch <mode>` | Delete local branch too (`auto` / `ask` / `never`) |
---
### `gwm clean`
Auto-detect and remove worktrees that are safe to delete.
**A worktree is eligible if:**
1. Remote branch is deleted or merged into main
2. No uncommitted or unpushed local changes
3. Not a main branch or the current worktree
**Options:**
| Option | Description |
| --------------- | ---------------------------- |
| `-n, --dry-run` | Show list only, don't delete |
| `--force` | Delete without confirmation |
---
### `gwm pull-main`
Find main branch worktrees (main, master, etc.) and run `git pull` to update them. Works from any directory.
## Workflow Comparison
### Traditional Git
```bash
# Reviewing a PR
git stash # Save current work
git checkout main # Switch to main
git pull # Update main
git checkout pr-branch # Switch to PR branch
git pull origin pr-branch # Update PR branch
# ... review work ...
git checkout main # Back to main
git stash pop # Restore work
```
### With gwm
```bash
# Reviewing a PR
gwm add pr-branch -r # Create worktree from remote
gwm go pr-branch # Jump to review worktree
# ... review work ... (original work untouched)
gwm remove pr-branch # Remove when done
```
## Help
- `gwm help`: General help
- `gwm help <command>`: Command-specific help
- [GitHub Issues](https://github.com/shutootaki/gwm/issues): Bug reports and feature requests
## License
MIT