Switch between branches like a pro - your Git branch switching yard
A powerful command-line tool for managing Git worktrees with intelligent GitHub Pull Request integration. Just like railroad turnouts route trains between tracks, Git Turnouts helps you seamlessly switch between multiple branches and work contexts.
Currently Supported Platforms: macOS, Linux (Unix-like systems)
In railroad terminology, a turnout (also called a "switch" or "point") is a mechanical installation that guides trains from one track to another. This perfectly mirrors what Git Turnouts does - it helps you smoothly switch between different development tracks (branches) without the friction of stashing, committing unfinished work, or losing context.
Key metaphor parallels:
- π€οΈ Multiple tracks = Multiple branches
- π Switching trains = Switching work contexts
- π Railroad junction = Git worktree workspace
- π Track routing = Branch management
- PR-Aware Worktree Creation: Automatically detect and checkout GitHub PRs by number or title
- Smart Branch Resolution: Intelligently handles local, remote, and new branches
- Organized Workspace: Creates worktrees in a structured hierarchy
- Automatic Opening: Open worktrees in your IDE (IntelliJ IDEA, VS Code) or other applications (iTerm, Warp, Finder)
- Bulk Removal: Remove multiple worktrees efficiently in a single command
- Protected Branches: Automatically protects main/master branches from deletion
- Safety Checks: Prevents branch conflicts and duplicate worktrees
- Progress Tracking: Shows detailed progress and summary statistics
- Unix-like OS (macOS, Linux)
- Git (2.5 or newer, with worktree support)
- Bash (3.2+)
- jq (for JSON parsing) - Install jq
- GitHub CLI (gh) (optional, for PR integration features) - Install gh
Platform Notes:
- Core features (worktree management, PR integration): Fully supported on macOS and Linux
- Automatic opening (
--openflag): Currently uses macOS-specific commands. On Linux, worktrees are created successfully but automatic opening in applications is not yet supported.
-
Clone this repository:
git clone https://github.com/andr3van/git-turnouts.git cd git-turnouts -
Make the script executable:
chmod +x git-turnouts
-
Add to your PATH (choose one method):
Option A: Symlink to a directory in your PATH
ln -s "$(pwd)/git-turnouts" /usr/local/bin/git-turnoutsOption B: Add to PATH in your shell profile
# Add to ~/.bashrc, ~/.zshrc, etc. export PATH="$PATH:/path/to/git-turnouts"
-
Verify installation:
git-turnouts --version
# Create worktree with branch name
git-turnouts add feature-branch
# Create worktree with different folder and branch names
git-turnouts add my-folder feature-branch# Checkout PR by number
git-turnouts add 7113
# Search for PR by title (partial match)
git-turnouts add "feature name"
# Search for PR by exact title
git-turnouts add "Exact PR Title"
# Custom folder name with PR title search
git-turnouts add my-folder "PR Title"# Open in VS Code (default is IntelliJ IDEA)
git-turnouts add feature-x --open code
# Open in iTerm
git-turnouts add feature-x --open iterm
# Available options: idea, code, iterm, warp, finder# Remove a single worktree
git-turnouts remove feature-branch
# Remove multiple worktrees (bulk operation)
git-turnouts remove feature-1 feature-2 feature-3
# Short alias
git-turnouts rm feature-branch# List all worktrees
git-turnouts list
# Short alias
git-turnouts lsWorktrees are organized in a clean hierarchy:
~/projects/
βββ my-project/ # Main repository
βββ worktree/
βββ my-project/ # Project-specific worktrees
βββ feature-1/
βββ feature-2/
βββ 7113/ # PR-based worktree
-
PR Number: If input is numeric (e.g.,
7113), directly fetches that PR- Checks PR state (open/closed/merged)
- Merged PRs: Blocks creation (branch likely deleted)
- Closed PRs: Allows creation with warning (branch may still exist)
- Open PRs: Proceeds normally
- Uses PR's branch name
- Fetches latest changes from remote
-
PR Title Search: Searches open PRs for matching titles
- Quoted strings = exact match
- Unquoted strings = partial match
- Uses PR's branch if found
-
Standard Branch: Falls back to normal Git branch resolution
- Checks for remote branch first
- Creates new branch from HEAD if needed
- Prevents checking out the same branch in multiple worktrees
- Protects main/master branches from deletion
- Validates target directories don't exist
- Handles merged/closed PRs appropriately
# Create worktrees for different features (one at a time)
git-turnouts add feature-authentication
git-turnouts add feature-dashboard
git-turnouts add feature-api
# Work on them simultaneously in different IDE windows# Quickly checkout PR #7113 for review
git-turnouts add 7113 --open code
# When done reviewing
git-turnouts remove 7113# Remove multiple completed feature branches at once
git-turnouts remove feature-1 feature-2 feature-3 pr-7113
# Progress tracking shows: [1/4], [2/4], [3/4], [4/4]Git Turnouts uses a single YAML configuration file that manages all your projects. The configuration file lives in the git-turnouts installation directory.
-
Create your configuration file:
git-turnouts config init
This creates
.config.ymlin the git-turnouts directory -
Edit your configuration:
# The init command shows you the path to edit vim ~/.../git-turnouts/.config.yml
-
View your current configuration:
git-turnouts config show
This shows the detected project name and effective settings
Your settings will be applied automatically across all projects!
See .config.yml.example for all available options with detailed comments. Here's a quick overview:
worktree:
# Global settings apply to all projects
global:
# Base directory for all projects
# Project name is automatically added as a subdirectory
base_dir: ~/worktrees
# Files to copy from main worktree to new worktrees
copy_files:
- .editorconfig
- .env.example
- .nvmrc
# Project-specific settings (overrides global)
# The 'name' must match your repository's directory name exactly
projects:
- name: my-app
base_dir: ~/custom/my-app
copy_files:
- .editorconfig
- .env.local
- name: another-project
base_dir: /tmp/another-projectHow it works:
- Project name is detected from your repository's directory name (e.g.,
/path/to/my-appβ project name ismy-app) - The project name is always added as a subdirectory for organization
- If a project-specific
base_direxists β use it:{base_dir}/{project}/{branch} - Else if global
base_direxists β use it:{base_dir}/{project}/{branch} - Else β auto-detect:
../worktree/{project}/{branch}
Example: With global.base_dir: ~/worktrees and project my-app:
- Worktrees created at:
~/worktrees/my-app/feature-x
The copy_files feature is one of Git Turnouts' most powerful workflow improvements. It automatically copies essential configuration files from your main worktree to every new worktree you create.
The problem it solves:
Many files are essential to run your application but are NOT in version control (listed in .gitignore):
.envfiles containing personal API keys, credentials, or secrets- Local IDE settings or personalized configurations
- Files with environment-specific values unique to your machine
Without copy_files, you'd need to manually recreate or copy these files for every single worktree - a tedious and error-prone process.
Why this matters:
- No manual setup - Each worktree is instantly ready to work with
- Never forget essential files - Stop worrying about missing
.envfiles or credentials - Consistency across worktrees - All your worktrees use the same local configuration
- Save time - Eliminate the tedious copy-paste routine for every new worktree
Common files to copy:
copy_files:
- .env # Personal environment variables, API keys, secrets (NOT in git)
- .env.local # Local development overrides (NOT in git)
- .editorconfig # Editor settings (indentation, formatting)
- .nvmrc # Node.js version for the project
- .ruby-version # Ruby version manager
- .prettierrc # Code formatting rules
- .eslintrc.js # Linting configuration
- .idea/codeStyles/ # IDE code style settingsReal-world example:
worktree:
global:
base_dir: ~/worktrees
copy_files:
- .env # Contains your personal database credentials
- .env.local # Your local API keys
- .editorconfig
- .nvmrcWhen you run git-turnouts add feature-auth, it will:
- Create the worktree at
~/worktrees/my-app/feature-auth - Automatically copy
.env,.env.local,.editorconfig, and.nvmrcto the new worktree - Open in your IDE, ready to work immediately - no manual file copying, no missing credentials
Without copy_files: Every time you create a worktree, you must:
- Remember which files to copy
- Manually copy
.envfile with your credentials - Set up local configurations again
- Deal with "Cannot connect to database" errors when you forget
With copy_files: Every worktree is automatically set up with all your personal configurations. Just run the app - it works immediately. π
defaults:
global:
# Default application to open worktrees (idea, code, iterm, warp, finder)
# idea/code = IDEs, iterm/warp = terminals, finder = file manager
open_with: code
projects:
- name: my-app
open_with: ideaprotection:
global:
# Branches that cannot be deleted when removing worktrees
# Note: main, master, and your repo's default branch are always protected
protected_branches:
- develop
- staging
- production
projects:
- name: critical-app
protected_branches:
- develop
- staging
- production
- hotfixremove:
global:
# Auto-run git worktree prune after removing worktrees
auto_prune: true
projects:
- name: experimental
auto_prune: falsedefaults:
global:
open_with: codeworktree:
global:
# All projects go to ~/worktrees/{project-name} by default
# (project name is automatically added)
base_dir: ~/worktrees
copy_files:
- .editorconfig
- .env.example
# But my-important-project goes to a specific location
projects:
- name: my-important-project
base_dir: ~/criticalResults:
- Most projects:
~/worktrees/my-app/branch-name - my-important-project:
~/critical/my-important-project/branch-name
protection:
global:
# main and master are already protected by default
protected_branches:
- develop
- staging
- production
- hotfixworktree:
global:
base_dir: ~/worktrees
copy_files:
- .editorconfig
- .env.example
projects:
- name: critical-app
base_dir: ~/production
defaults:
global:
open_with: code
protection:
global:
protected_branches:
- develop
- staging
remove:
global:
auto_prune: trueResults:
- Most projects:
~/worktrees/{project}/branch-name - critical-app:
~/production/critical-app/branch-name
- Configuration is optional - git-turnouts works perfectly without any configuration file
- Configuration is centralized - one
.config.ymlfile in the git-turnouts directory manages all projects - Project names are detected automatically from the repository directory name
- Project name is always added as a subdirectory for organization
- Project-specific settings override global settings
- The
.config.yml.examplefile serves as a template and reference
GitHub CLI is required for PR integration features.
Solution:
# macOS
brew install gh
# Linux
# See: https://cli.github.com/After installation, authenticate with GitHub:
gh auth loginNote: You can still use git-turnouts with branch names without gh installed - PR integration features will not be available.
jq is required for JSON processing.
Solution:
# macOS
brew install jq
# Linux (Debian/Ubuntu)
sudo apt-get install jq
# Linux (RHEL/CentOS)
sudo yum install jq
# Or download from: https://jqlang.github.io/jq/download/Git 2.5 or newer is required.
Solution:
# Check your current version
git --version
# macOS - upgrade via Homebrew
brew upgrade git
# Linux - upgrade via package manager
sudo apt-get update && sudo apt-get upgrade git # Debian/Ubuntu
sudo yum update git # RHEL/CentOSThe worktree base directory may not be writable.
Solution:
# Check permissions
ls -la ~/worktrees/
# Fix permissions
chmod u+w ~/worktrees
# Or use a different directory in your config
git-turnouts config init
# Edit .config.yml and set base_dir to a writable locationThe git-turnouts directory may not be writable.
Solution:
# Find the git-turnouts directory
which git-turnouts
# Fix permissions on the directory
chmod u+w /path/to/git-turnouts
# Or create a local config by setting environment variable
export GIT_TURNOUTS_CONFIG=~/.config/git-turnouts/config.ymlA directory with that name already exists in the worktree location.
Solution:
# Check what's there
ls -la ~/worktrees/my-project/
# Remove the conflicting directory if it's not a worktree
rm -rf ~/worktrees/my-project/branch-name
# Or choose a different folder name
git-turnouts add my-custom-name branch-nameGit prevents checking out the same branch in multiple worktrees.
Solution:
# List all worktrees to find where it's checked out
git worktree list
# Remove the existing worktree first
git-turnouts remove branch-name
# Or use a different branch
git-turnouts add new-branch-nameWorktree has uncommitted changes that would be lost.
Solution:
# Option 1: Commit the changes
cd path/to/worktree
git add .
git commit -m "Save work in progress"
# Option 2: Stash the changes
git stash save "Work in progress"
# Option 3: Manually delete (WARNING: loses changes)
rm -rf path/to/worktree
git worktree pruneThe PR doesn't exist or you don't have access to it.
Solution:
# Verify PR exists
gh pr view 123
# Check you're authenticated
gh auth status
# Try re-authenticating
gh auth login
# Verify you're in the correct repository
git remote -vGit Turnouts shows a warning but proceeds to create the worktree.
Explanation: Closed PRs that aren't merged can still have their branches available. The worktree will be created if the branch exists remotely.
Git Turnouts blocks worktree creation for merged PRs.
Reason: Merged PR branches are typically deleted from the remote repository and no longer exist.
Solution:
# Option 1: Work with the base branch where it was merged
git-turnouts add main
# Option 2: Checkout the specific commit if you need to review it
# (Use git log to find the merge commit hash)
# Option 3: If the branch still exists remotely, fetch it manually
git fetch origin branch-name
git-turnouts add branch-nameNo open PRs match your search query.
Solution:
# List all open PRs
gh pr list
# Try a different search term
git-turnouts add "different keywords"
# Use the branch name directly
git-turnouts add branch-nameThe application may not be installed or not in the expected location.
Solution:
# Verify application is installed and can be opened from terminal
# macOS examples:
open -a "IntelliJ IDEA" # IDE
open -a "Visual Studio Code" # IDE
open -a "iTerm" # Terminal
open -a "Warp" # Terminal
# Check your configuration
git-turnouts config show
# Change default application
git-turnouts config init
# Edit .config.yml and set defaults.open_with
# Or specify application per command
git-turnouts add branch-name --open codeApplication opening currently uses platform-specific commands.
Solution:
# Create worktree without automatic opening
git-turnouts add branch-name
# Then navigate manually
cd path/to/worktree # Path shown in output
# Or use your system's file manager/terminal
# macOS:
open path/to/worktree
# Linux:
xdg-open path/to/worktreeCurrent Application Support:
- VS Code (
code): IDE - May work on both macOS and Linux if installed - IntelliJ IDEA (
idea): IDE - Currently macOS-specific command - iTerm (
iterm): Terminal - macOS only - Warp (
warp): Terminal - Currently macOS-specific command - Finder (
finder): File Manager - macOS only
Tip: On platforms with limited application support, create worktrees without the --open flag and navigate manually.
Your .config.yml file may have YAML syntax errors.
Solution:
# Backup your config
cp .config.yml .config.yml.backup
# Reset to example template
git-turnouts config init
# Or manually check YAML syntax
# Common issues:
# - Incorrect indentation (use spaces, not tabs)
# - Missing colons after keys
# - Unquoted strings with special characters
# View what's being read
git-turnouts config showMake sure you're editing the right config file.
Solution:
# Find where config should be
which git-turnouts
# Config should be in the same directory as the script
# Show current effective configuration
git-turnouts config show
# Shows detected project name and pathsYou must run git-turnouts from within a Git repository.
Solution:
# Navigate to your repository first
cd /path/to/your/repository
# Verify it's a git repo
git status
# Then run git-turnouts
git-turnouts listNetwork operations (fetching PRs, pulling branches) can be slow.
Explanation: This is normal for:
- Fetching large repositories
- Slow network connections
- First-time branch fetches
Git Turnouts will show progress where possible. Be patient during network operations.
- Check verbose error messages - git-turnouts provides detailed error information
- Enable debug mode (if needed):
bash -x git-turnouts add branch-name
- Open an issue: GitHub Issues
Contributions are welcome! Whether you're fixing bugs, adding features, improving documentation, or suggesting new ideas - all contributions are appreciated.
Getting Started:
- Read our CONTRIBUTING.md for detailed guidelines
- Fork the repository and create a feature branch
- Make your changes and test thoroughly
- Submit a Pull Request with a clear description
Areas where help is appreciated:
- π¨ New IDE/application adapters
- π Bug reports and fixes
- π Documentation and tutorials
- β¨ New features and enhancements
- π Platform support (Windows native, additional Unix-like systems)
For questions or discussions, open an issue on GitHub.
MIT License - see LICENSE file for details
Created to streamline Git worktree workflows with modern GitHub PR integration. Born from the need to work on multiple features, review PRs, and handle hotfixes without the constant context switching pain.
Built for developers who work on multiple features simultaneously and need to switch tracks without losing momentum. Like a well-designed railroad junction, Git Turnouts keeps your development workflow running smoothly.