Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ jobs:
git-wt add test-branch
git-wt list | grep -q "test-branch"
git-wt path test-branch
git-wt remove test-branch
git-wt remove test-branch --delete-branch
git-wt prune
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2026-03-09

### Added

- `--go` flag for `git wt add` — prints the worktree path to stdout for `cd` integration (`cd "$(git wt add branch --go)"`).
- `git wt root` command — prints the main repository root path, works from any worktree.
- Hook system via `.git-wtrc` config file — supports `pre-add`, `post-add`, `pre-remove`, and `post-remove` hooks with environment variables (`GIT_WT_BRANCH`, `GIT_WT_PATH`, `GIT_WT_ROOT`, `GIT_WT_BASE`). Hooks can be any executable: shell, Python, Ruby, etc.
- `--delete-branch` (`-db`) flag for `git wt remove` — automatically deletes the local branch without prompting (`git wt rm feature -db`).

### Changed

- Status messages (`info`, `success`) now print to stderr, keeping stdout clean for machine-readable output.

### Fixed

- `git wt remove` no longer fails in non-interactive environments (CI/CD) when `/dev/tty` is unavailable — the branch delete prompt is now safely skipped with an informational message.

## [1.0.0] - 2026-03-09

### Added
Expand All @@ -24,4 +41,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- CI workflow with ShellCheck linting and smoke tests on Ubuntu and macOS.
- Release workflow with automated GitHub Releases, Homebrew tap updates, and Scoop bucket updates.

[1.1.0]: https://github.com/silasvasconcelos/simple-git-worktreee/releases/tag/v1.1.0
[1.0.0]: https://github.com/silasvasconcelos/simple-git-worktreee/releases/tag/v1.0.0
56 changes: 56 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
SHELL := /bin/bash
BINARY := bin/git-wt
SCRIPTS := $(BINARY) install.sh

.PHONY: help lint test ci install clean

help: ## Show available targets
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*## "}; {printf " \033[36m%-12s\033[0m %s\n", $$1, $$2}'

lint: ## Run ShellCheck on all shell scripts
@command -v shellcheck >/dev/null 2>&1 || { echo "shellcheck not found — brew install shellcheck"; exit 1; }
shellcheck $(SCRIPTS)
@printf '\033[1;32m✔\033[0m shellcheck passed\n'

test: ## Run smoke tests (same as CI)
@chmod +x $(BINARY)
@printf '\n\033[1;34m==>\033[0m Verify help output\n'
$(BINARY) help
@printf '\n\033[1;34m==>\033[0m Verify version output\n'
$(BINARY) version | grep -q "git-wt"
@printf '\033[1;32m✔\033[0m version OK\n'
@printf '\n\033[1;34m==>\033[0m Test add/list/path/remove/prune in a temp repo\n'
@bash -c '\
set -euo pipefail; \
TMPDIR=$$(mktemp -d); \
trap "rm -rf $$TMPDIR" EXIT; \
cd "$$TMPDIR"; \
git init -b main -q; \
git config user.name "test"; \
git config user.email "test@test"; \
git commit --allow-empty -m "init" -q; \
export PATH="$(CURDIR)/bin:$$PATH"; \
git-wt add test-branch; \
git-wt list | grep -q "test-branch"; \
printf "\033[1;32m✔\033[0m add + list OK\n"; \
git-wt path test-branch >/dev/null; \
printf "\033[1;32m✔\033[0m path OK\n"; \
git-wt remove test-branch; \
printf "\033[1;32m✔\033[0m remove OK\n"; \
git-wt add test-branch-db; \
git-wt remove test-branch-db --delete-branch; \
git branch --list test-branch-db | grep -q "test-branch-db" && exit 1 || true; \
printf "\033[1;32m✔\033[0m remove --delete-branch OK\n"; \
git-wt prune; \
printf "\033[1;32m✔\033[0m prune OK\n"; \
'
@printf '\n\033[1;32m✔ All tests passed\033[0m\n'

ci: lint test ## Run full CI pipeline (lint + test)

install: ## Install git-wt to /usr/local/bin
bash install.sh

clean: ## Remove build artifacts
rm -rf dist/
124 changes: 115 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ my-project/

| Command | Description |
|---|---|
| `git wt add <branch> [base]` | Create a worktree. Base defaults to `main` |
| `git wt add <branch> [base] [--go]` | Create a worktree from current branch. `--go` outputs path for `cd` |
| `git wt list` | List all worktrees |
| `git wt remove <branch>` | Remove a worktree |
| `git wt prune` | Clean up stale worktree references |
| `git wt path <branch>` | Print the absolute path of a worktree |
| `git wt root` | Print the main repository root path |
| `git wt help` | Show help |
| `git wt version` | Show version |

Expand Down Expand Up @@ -100,17 +101,34 @@ cd my-project
git wt add feature-login
# ==> created .worktrees/
# ==> fetching from origin…
# ==> creating worktree for 'feature-login' based on 'main'…
# ==> creating worktree for 'feature-login' based on 'develop'…
# ✔ worktree created at .worktrees/feature-login

cd .worktrees/feature-login
# You now have a full checkout — run tests, edit code, etc.
```

### Branch from develop instead of main
### Create and jump into the worktree with `--go`

```bash
git wt add feature-payment develop
cd "$(git wt add feature-login --go)"
# ==> creating worktree for 'feature-login' based on 'develop'…
# ✔ worktree created at .worktrees/feature-login
# You're now inside .worktrees/feature-login
```

> **Tip:** Add a shell function to your `.bashrc` / `.zshrc` for even less typing:
>
> ```bash
> gwt() { cd "$(git wt add "$@" --go)"; }
> ```
>
> Then just: `gwt feature-login`

### Branch from a specific base instead of the current branch

```bash
git wt add feature-payment main
```

### See all active worktrees
Expand All @@ -135,6 +153,15 @@ git wt remove feature-login
# ✔ worktree 'feature-login' removed
```

### Go back to the project root

```bash
# From any worktree, return to the main project directory
cd "$(git wt root)"
```

This works from anywhere — inside a worktree, a subdirectory, or the main repo itself. It always resolves to the original project root.

### Prune orphaned references

```bash
Expand All @@ -143,20 +170,99 @@ git wt prune

---

## Hooks

You can run custom commands before and after worktree operations by creating a `.git-wtrc` file in your repository root.

### Configuration

Create a `.git-wtrc` file with `key = command` pairs:

```ini
# .git-wtrc — hook configuration for git-wt

# Runs before creating a worktree
pre-add = echo "Setting up $GIT_WT_BRANCH…"

# Runs after creating a worktree (e.g. install dependencies)
post-add = cd $GIT_WT_PATH && npm install

# Runs before removing a worktree
pre-remove = echo "Cleaning up $GIT_WT_BRANCH…"

# Runs after removing a worktree
post-remove = echo "Done removing $GIT_WT_BRANCH"
```

### Available hooks

| Hook | Trigger |
|---|---|
| `pre-add` | Before worktree creation |
| `post-add` | After worktree creation |
| `pre-remove` | Before worktree removal |
| `post-remove` | After worktree removal |

### Environment variables

Each hook receives these environment variables:

| Variable | Description | Available in |
|---|---|---|
| `GIT_WT_BRANCH` | Branch name | All hooks |
| `GIT_WT_PATH` | Absolute path of the worktree | All hooks |
| `GIT_WT_ROOT` | Repository root path | All hooks |
| `GIT_WT_BASE` | Base branch name | `pre-add`, `post-add` |

### Hook examples

**Install dependencies after creating a worktree:**

```ini
post-add = cd $GIT_WT_PATH && npm install
```

**Run a Python setup script:**

```ini
post-add = python3 ./scripts/setup-worktree.py
```

**Use a Ruby script for cleanup:**

```ini
post-remove = ruby ./scripts/cleanup.rb
```

**Backup before removal:**

```ini
pre-remove = tar czf "/tmp/${GIT_WT_BRANCH}-backup.tar.gz" "$GIT_WT_PATH"
```

**Chain multiple commands:**

```ini
post-add = cd $GIT_WT_PATH && cp ../.env.example .env && npm install && npm run db:migrate
```

> **Note:** A failing `pre-*` hook aborts the operation. A failing `post-*` hook logs a warning but does not roll back.

---

## Real-world workflow

```bash
# 1. Start a hotfix while your feature branch is still in progress
git wt add hotfix-auth
# 1. Start a hotfix — jump straight into it with --go
cd "$(git wt add hotfix-auth --go)"

# 2. Fix the bug in the hotfix worktree
cd .worktrees/hotfix-auth
vim src/auth.js
git add -A && git commit -m "fix: auth token expiry"
git push origin hotfix-auth

# 3. Go back to main worktree — your feature branch is untouched
cd ../..
# 3. Go back to main project root — your feature branch is untouched
cd "$(git wt root)"

# 4. Clean up after the hotfix is merged
git wt remove hotfix-auth
Expand Down
Loading
Loading