This content originally appeared on DEV Community and was authored by Sivaram
The Problem That Started It All
Picture this: You’re deep in feature development, carefully crafting your code. Suddenly:
- Slack notification: “Can you review my PR real quick?”
- Email: “URGENT: Production bug needs fix”
- Brain: “What if we tried that experimental approach?”
The traditional git response?
git stash
git checkout pr-branch
# Review PR
git checkout main
git checkout -b hotfix
# Fix bug
git checkout feature-branch
git stash pop
# Wait... which stash was mine again?
I was tired of this dance. Really tired.
Discovering Git Worktrees
Git worktrees have been around since 2015, but they’re surprisingly underused. They let you have multiple working directories attached to the same repository. Think of it as having multiple synchronized clones without the disk space overhead.
But the UX is… rough:
git worktree add ../my-feature origin/my-feature
cd ../my-feature
# Now manage multiple directories manually
That’s when I decided to build branchyard.
The Vision: Parallel Development That Sparks Joy
I wanted a tool that would:
- Make creating multiple worktrees as easy as listing branch names
- Handle all the directory management automatically
- Generate editor workspaces so everything opens correctly
- Remember my setups (sessions) for common workflows
- Be fun to use (yes, developer tools can be fun!)
Demo Gif
https://cdn.jsdelivr.net/gh/SivaramPg/branchyard@main/assets/branchyard-demo.gif
The Journey: Key Decisions and Lessons
Decision 1: Bun as the Runtime
I chose Bun for several reasons:
- Blazing fast startup (CLI tools need to feel instant)
- Native TypeScript execution (no build step!)
- Excellent subprocess handling for git commands
- Built-in prompt() function (though this caused issues – more on that later)
Decision 2: The Oprah Easter Egg
When creating multiple worktrees, users are greeted with ASCII art and:
“YOU GET A TREE! YOU GET A TREE! EVERYBODY GETS A TREE!”
Why? Because developer tools should make you smile. The cognitive load of our work is heavy enough – a little joy goes a long way.
Decision 3: Safety by Default
Every destructive operation requires explicit confirmation:
- “Also delete the git branches? (y/N):” – Notice the capital N
- Force removal requires double confirmation
- Dry-run mode for everything
This wasn’t just about preventing mistakes – it was about building trust. Users should feel confident experimenting.
The Big Architecture Change (v1.3.0)
Initially, I put worktrees in the parent directory:
/parent/
project/
feature-x/ # worktree
bugfix-y/ # worktree
This was wrong. Really wrong. It polluted parent directories, broke permissions, made projects non-portable. In v1.3.0, I made a breaking change:
/project/
.worktrees/
feature-x/ # worktree
bugfix-y/ # worktree
Lesson learned: Get your architecture right early, even if it means breaking changes.
Technical Challenges and Solutions
Challenge 1: Terminal Hanging After Prompts
Problem: After creating worktrees, the terminal would hang. Users had to Ctrl+C to get their prompt back.
Investigation: Bun’s stdin handling through iterators wasn’t closing properly.
Solution: Switched to Bun’s built-in prompt()
function and added explicit stdin cleanup:
export function closePrompts() {
if (process.stdin.isTTY) {
process.stdin.pause();
}
}
Challenge 2: Cross-Platform Path Handling
Problem: Windows uses backslashes, Unix uses forward slashes. Git likes forward slashes everywhere.
Solution: Always use forward slashes in git commands, use Node’s path module for filesystem operations:
const dir = `.worktrees/${name}`; // Always forward slashes for git
const fullPath = path.join(process.cwd(), '.worktrees', name); // Platform-specific
Challenge 3: Parallel Operations with Error Handling
Problem: Creating multiple worktrees should be fast (parallel) but safe (proper error handling).
Solution: Promise.all with individual try-catch blocks:
async function createWorktree(name: string) {
try {
await $`git worktree add ${dir} -b ${name} ${baseBranch}`;
} catch (error) {
console.error(`Failed to create ${name}: ${error.message}`);
}
}
await Promise.all(worktrees.map(createWorktree));
The Current State: Feature Complete
branchyard now includes:
-
Parallel worktree creation:
branchyard feature-x bugfix-y hotfix-z
- Workspace generation: Auto-creates editor workspace files
- Session management: Save and restore worktree sets
- Smart removal: Optional branch deletion with safe defaults
-
Interactive mode: Just run
branchyard
for guided setup - Multi-editor support: VSCode, Cursor, Windsurf, Zed
- Migration warnings: Smooth upgrade path between versions
Usage Patterns I’ve Discovered
The PR Review Pattern
branchyard review-pr-123 review-pr-124
# Review multiple PRs simultaneously in different editor windows
The Experiment Pattern
branchyard main-safe experiment-wild experiment-wilder
# Keep main safe while trying crazy ideas
The Sprint Pattern
branchyard save-session sprint-42
# Restore all sprint work with one command
What’s Next?
Some ideas I’m exploring:
-
Automatic PR checkout:
branchyard --pr 123
to checkout PR branches - Worktree templates: Auto-copy config files to new worktrees
- Git hooks integration: Run setup scripts after worktree creation
- Status dashboard: See all worktrees’ git status at once
Lessons Learned
- Start with the UX: I wrote the README first, imagining the ideal commands
- Defensive defaults matter: Users remember when tools lose their work
- Joy is a feature: That Oprah easter egg makes people smile
- Breaking changes are OK: Better to fix architecture early than live with bad decisions
- Ship iteratively: v1.0 was simple, v1.3.0 is polished
Try It Yourself
npm install -g branchyard
branchyard --help
branchyard --fun # For the easter egg!
GitHub: https://github.com/SivaramPg/branchyard
Final Thoughts
Building developer tools is deeply satisfying. We spend thousands of hours with these tools – even small improvements compound into massive productivity gains.
But more than productivity, I wanted branchyard to reduce cognitive load. Every git stash
is a mental bookmark. Every branch switch is context destroyed. With worktrees, your work stays exactly as you left it.
As developers, we’re builders. Sometimes, the best thing we can build is a tool that makes building everything else a little bit easier.
What’s your git workflow pain point? How do you handle parallel development? I’d love to hear your stories and ideas!
P.S. – Yes, the name “branchyard” is a pun. A yard full of branches. I’m not sorry.
This content originally appeared on DEV Community and was authored by Sivaram