Skip to content
This repository was archived by the owner on Feb 24, 2026. It is now read-only.

Commit 0be8088

Browse files
feat: add wt-update, wt-destroy tasks and fetch-before-add (#11)
- wt-add now fetches all remotes before branching (skips gracefully when no remotes are configured) - wt-update fetches all remotes and fast-forwards main - wt-destroy removes worktree, local branch, and remote branch - Updated README and AGENTS.md with new tasks, linked the followup post "git-wt: Worktrees Simplified", and expanded credits for Ahmed el Gabri Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4bb3699 commit 0be8088

5 files changed

Lines changed: 85 additions & 10 deletions

File tree

README.md

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
A [copier](https://copier.readthedocs.io/) template that scaffolds git projects using the
44
**bare repo + worktree** pattern described in
5-
[Git Worktrees Done Right](https://gabri.me/blog/git-worktrees-done-right).
5+
[Git Worktrees Done Right](https://gabri.me/blog/git-worktrees-done-right) and its followup
6+
[git-wt: Worktrees Simplified](https://gabri.me/blog/git-wt) by Ahmed el Gabri.
67

78
Instead of switching branches with `git checkout`, you keep multiple branches checked out
89
simultaneously as separate directories (worktrees). A bare clone holds all git data, and
@@ -44,7 +45,9 @@ my-project/
4445
│ └── tasks/ # Project tasks
4546
│ ├── wt-add # Create a new worktree
4647
│ ├── wt-rm # Remove a worktree
48+
│ ├── wt-destroy # Remove worktree + local + remote branch
4749
│ ├── wt-ls # List all worktrees
50+
│ ├── wt-update # Fetch remotes and fast-forward main
4851
│ ├── repo-public # Create a public GitHub repo
4952
│ ├── repo-private # Create a private GitHub repo
5053
│ └── remote-add # Add a remote to an existing repo
@@ -70,8 +73,14 @@ cd my-feature/
7073
# List all worktrees
7174
mise run wt-ls
7275

73-
# Clean up when done
76+
# Fetch latest and fast-forward main
77+
mise run wt-update
78+
79+
# Clean up when done (keeps remote branch)
7480
mise run wt-rm my-feature
81+
82+
# Or nuke everything: worktree + local + remote branch
83+
mise run wt-destroy my-feature
7584
```
7685

7786
The `main/` worktree stays pristine as a clean reference for diffing. Never edit files in it
@@ -164,9 +173,11 @@ outside version control.
164173

165174
| Task | Usage | Description |
166175
|------|-------|-------------|
167-
| `wt-add` | `mise run wt-add <branch> [base]` | Create a new worktree. Defaults to branching from `main`. |
168-
| `wt-rm` | `mise run wt-rm <branch>` | Remove a worktree and its directory. |
176+
| `wt-add` | `mise run wt-add <branch> [base]` | Create a new worktree. Fetches remotes first, defaults to branching from `main`. |
177+
| `wt-rm` | `mise run wt-rm <branch>` | Remove a worktree and its local branch. |
178+
| `wt-destroy` | `mise run wt-destroy <branch>` | Remove a worktree and delete both local and remote branches. |
169179
| `wt-ls` | `mise run wt-ls` | List all active worktrees. |
180+
| `wt-update` | `mise run wt-update` | Fetch all remotes and fast-forward `main`. |
170181
| `repo-public` | `mise run repo-public <owner/repo>` | Create a public GitHub repo, set up remote, and push `main`. |
171182
| `repo-private` | `mise run repo-private <owner/repo>` | Create a private GitHub repo, set up remote, and push `main`. |
172183
| `remote-add` | `mise run remote-add <owner/repo> [name]` | Add an existing GitHub repo as remote and push `main`. Defaults remote name to `origin`. |
@@ -179,5 +190,11 @@ To add your own, edit `.bare/info/exclude` directly.
179190

180191
## Credit
181192

182-
Based on the workflow from [Git Worktrees Done Right](https://gabri.me/blog/git-worktrees-done-right)
183-
by Ahmed el Gabri.
193+
Based on the workflow from Ahmed el Gabri:
194+
195+
- [Git Worktrees Done Right](https://gabri.me/blog/git-worktrees-done-right) -- the bare repo
196+
+ worktree pattern that this template scaffolds.
197+
- [git-wt: Worktrees Simplified](https://gabri.me/blog/git-wt) -- a standalone CLI tool that
198+
wraps the same pattern. Several of our mise tasks (`wt-update`, `wt-destroy`, fetch-before-add)
199+
are inspired by `git-wt`'s approach. If you prefer a single CLI over mise tasks, check out
200+
[git-wt](https://github.com/ahmedelgabri/git-wt).

template/.mise/tasks/wt-add

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ set -euo pipefail
66
BRANCH="${1:?Usage: mise run wt-add <branch-name> [base-branch]}"
77
BASE="${2:-main}"
88

9+
# Fetch latest from all remotes (skip if no remotes configured)
10+
if git remote | grep -q .; then
11+
git fetch --all --quiet
12+
fi
13+
914
if git show-ref --verify --quiet "refs/heads/$BRANCH"; then
1015
# Local branch exists, check it out
1116
git worktree add "$BRANCH" "$BRANCH"

template/.mise/tasks/wt-destroy

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
#MISE description="Remove a worktree and delete its local and remote branches"
3+
4+
set -euo pipefail
5+
6+
BRANCH="${1:?Usage: mise run wt-destroy <branch-name>}"
7+
8+
if [ "$BRANCH" = "main" ]; then
9+
echo "Error: refusing to destroy the main worktree." >&2
10+
exit 1
11+
fi
12+
13+
git worktree remove "$BRANCH"
14+
15+
git branch -D "$BRANCH"
16+
17+
if git remote | grep -q . && git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then
18+
git push origin --delete "$BRANCH"
19+
echo "Removed worktree, local branch, and remote branch '$BRANCH'"
20+
else
21+
echo "Removed worktree and local branch '$BRANCH' (no remote branch found)"
22+
fi

template/.mise/tasks/wt-update

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
#MISE description="Fetch all remotes and fast-forward the main branch"
3+
4+
set -euo pipefail
5+
6+
if ! git remote | grep -q .; then
7+
echo "No remotes configured. Nothing to update." >&2
8+
exit 1
9+
fi
10+
11+
git fetch --all --quiet
12+
13+
# Fast-forward main inside its worktree
14+
if git -C main merge --ff-only origin/main 2>/dev/null; then
15+
echo "Updated main to $(git -C main rev-parse --short HEAD)"
16+
else
17+
echo "Could not fast-forward main (diverged or worktree missing)." >&2
18+
echo " Resolve manually: cd main && git pull"
19+
exit 1
20+
fi

template/AGENTS.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ This project uses a **bare repo + worktree** structure. Read this before making
1212
├── <feature>/ # Worktree for a feature branch
1313
├── .mise/
1414
│ └── tasks/ # Project tasks (run via mise)
15-
│ ├── wt-add # Create a new worktree
16-
│ ├── wt-rm # Remove a worktree
17-
│ ├── wt-ls # List worktrees
15+
│ ├── wt-add # Create a new worktree
16+
│ ├── wt-rm # Remove a worktree
17+
│ ├── wt-destroy # Remove worktree + local + remote branch
18+
│ ├── wt-ls # List worktrees
19+
│ ├── wt-update # Fetch remotes and fast-forward main
1820
│ ├── repo-public # Create a public GitHub repo
1921
│ ├── repo-private # Create a private GitHub repo
20-
│ └── remote-add # Add a remote to an existing repo
22+
│ └── remote-add # Add a remote to an existing repo
2123
├── .mise.toml # Mise configuration
2224
├── _/ # Scratchpad for notes and one-off scripts
2325
├── .claude/ # Agent configuration (outside version control)
@@ -53,10 +55,19 @@ List active worktrees:
5355
mise run wt-ls
5456
```
5557

58+
Fetch latest from all remotes and fast-forward main:
59+
60+
```bash
61+
mise run wt-update
62+
```
63+
5664
Remove a worktree when done:
5765

5866
```bash
5967
mise run wt-rm my-feature
68+
69+
# Or remove worktree + local + remote branch in one shot
70+
mise run wt-destroy my-feature
6071
```
6172

6273
## Setting up a remote

0 commit comments

Comments
 (0)