Skip to content

Instantly share code, notes, and snippets.

@nazq
Created June 13, 2025 11:47
Show Gist options
  • Select an option

  • Save nazq/8a47bc731ea256c899d9ac160e861b49 to your computer and use it in GitHub Desktop.

Select an option

Save nazq/8a47bc731ea256c899d9ac160e861b49 to your computer and use it in GitHub Desktop.
git worktree helper
######################################
# git_wt_init - Set up Git worktree repo
######################################
git_wt_init() {
local GIT_URL="$1"
local MAIN_BRANCH="${2:-main}"
if [[ "$1" == "--help" || -z "$GIT_URL" ]]; then
echo ""
echo "Usage:"
echo " git_wt_init <git-url> [main-branch]"
echo ""
echo "This will:"
echo " - Create a directory based on the repo name"
echo " - Clone the bare repo into .bare/"
echo " - Create a .git pointer"
echo " - Check out the initial branch using worktree"
echo ""
echo "πŸ’‘ Worktree usage examples:"
echo " cd <project-dir>"
echo " git worktree add -b feature-x feature-x main"
echo " git fetch origin"
echo " git worktree add feature-y origin/feature-y"
echo " git worktree remove feature-x"
echo " git branch -D feature-x"
echo " git push origin --delete feature-x"
echo " git worktree prune"
echo ""
return 0
fi
# Extract project name from Git URL (e.g., foo.git β†’ foo)
local PROJ_NAME="$(basename "$GIT_URL" .git)"
local PROJ_DIR="$PWD/$PROJ_NAME"
if [[ -e "$PROJ_DIR" ]]; then
echo "❌ Directory '$PROJ_DIR' already exists. Choose a different location or delete it first."
return 1
fi
# Detect default branch if not provided
if [[ -z "$MAIN_BRANCH" ]]; then
echo "πŸ” Detecting default branch from remote..."
MAIN_BRANCH="$(git ls-remote --symref "$GIT_URL" HEAD 2>/dev/null | awk '/^ref:/ {sub("refs/heads/", "", $2); print $2}')"
if [[ -z "$MAIN_BRANCH" ]]; then
echo "⚠️ Could not detect default branch. Falling back to 'main'."
MAIN_BRANCH="main"
else
echo "πŸ“Œ Default branch is '$MAIN_BRANCH'"
fi
fi
echo "πŸ“ Creating project directory: $PROJ_DIR"
mkdir -p "$PROJ_DIR"
cd "$PROJ_DIR"
echo "πŸ“¦ Cloning bare repo into .bare..."
git clone --bare "$GIT_URL" .bare
echo "πŸ”— Writing .git pointer to .bare..."
echo "gitdir: ./.bare" > .git
echo "🌱 Creating initial '$MAIN_BRANCH' worktree..."
git --git-dir=.bare worktree add "$MAIN_BRANCH" "$MAIN_BRANCH"
echo ""
echo "βœ… Git worktree repo initialized at:"
echo " $PROJ_DIR"
echo ""
echo "πŸ“‚ Layout:"
echo " .bare/ β†’ bare repo"
echo " .git β†’ points to .bare"
echo " $MAIN_BRANCH/ β†’ initial working branch"
echo ""
echo "πŸ’‘ Worktree usage examples:"
echo " cd $PROJ_DIR"
echo " git worktree add -b feature-x feature-x $MAIN_BRANCH # create and checkout new local branch"
echo " git fetch origin"
echo " git worktree add feature-y origin/feature-y # check out existing remote branch"
echo " git worktree remove feature-x # remove folder and detach worktree"
echo " git branch -D feature-x # delete local branch"
echo " git push origin --delete feature-x # delete remote branch"
echo " git worktree prune # clean up metadata"
echo ""
}
######################################
# Completion for git_wt_init
######################################
_git_wt_init_completions() {
local cur prev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case $COMP_CWORD in
1)
# Git remote URLs (https or SSH)
COMPREPLY=( $(compgen -W "$(grep -Eo 'git@[^ ]+|https://[^ ]+' ~/.bash_history 2>/dev/null)" -- "$cur") )
;;
2)
# Common branch names
COMPREPLY=( $(compgen -W "main master trunk" -- "$cur") )
;;
esac
}
complete -F _git_wt_init_completions git_wt_init
######################################
# Alias for git worktree
######################################
alias gwt='git worktree'
type __git_complete &>/dev/null && __git_complete gwt git
@nazq
Copy link
Author

nazq commented Jul 2, 2025

Git Worktree Manager Setup & Usage Guide

πŸš€ Quick Setup

1. Download the script

# Create the directory if it doesn't exist
mkdir -p ~/.bash_functions

# Download the script
curl -o ~/.bash_functions/git-worktree.sh https://gist.githubusercontent.com/nazq/8a47bc731ea256c899d9ac160e861b49/raw/git-worktree.sh

2. Add to your .bashrc

Add this line to your ~/.bashrc or ~/.bash_profile:

# Source Git Worktree Manager
[ -f ~/.bash_functions/git-worktree.sh ] && source ~/.bash_functions/git-worktree.sh

3. Reload your shell

source ~/.bashrc
# or just open a new terminal

πŸ“– Usage

Basic Command

git_wt_init <git-url> [main-branch]

Example Output

Here's what you'll see when initializing a new worktree repository:

$ git_wt_init https://github.com/user/awesome-project.git

πŸ” Detecting default branch from remote...
πŸ“Œ Default branch is 'main'
πŸ“ Creating project directory: /home/user/projects/awesome-project
πŸ“¦ Cloning bare repo into .bare...
Cloning into bare repository '.bare'...
remote: Enumerating objects: 1234, done.
remote: Counting objects: 100% (1234/1234), done.
remote: Compressing objects: 100% (456/456), done.
remote: Total 1234 (delta 789), reused 1234 (delta 789), pack-reused 0
Receiving objects: 100% (1234/1234), 2.34 MiB  < /dev/null |  5.67 MiB/s, done.
Resolving deltas: 100% (789/789), done.
πŸ”— Writing .git pointer to .bare...
🌱 Creating initial 'main' worktree...
Preparing worktree (checking out 'main')
HEAD is now at abc1234 Latest commit message

βœ… Git worktree repo initialized at:
  /home/user/projects/awesome-project

πŸ“‚ Layout:
  .bare/       β†’ bare repo
  .git         β†’ points to .bare
  main/        β†’ initial working branch

πŸ’‘ Worktree usage examples:
  cd /home/user/projects/awesome-project
  git worktree add -b feature-x feature-x main         # create and checkout new local branch
  git fetch origin
  git worktree add feature-y origin/feature-y          # check out existing remote branch
  git worktree remove feature-x                        # remove folder and detach worktree
  git branch -D feature-x                              # delete local branch
  git push origin --delete feature-x                   # delete remote branch
  git worktree prune                                   # clean up metadata

Help Output

The script includes built-in help with examples:

$ git_wt_init --help

Usage:
  git_wt_init <git-url> [main-branch]

This will:
  - Create a directory based on the repo name
  - Clone the bare repo into .bare/
  - Create a .git pointer
  - Check out the initial branch using worktree

πŸ’‘ Worktree usage examples:
  cd <project-dir>
  git worktree add -b feature-x feature-x main
  git fetch origin
  git worktree add feature-y origin/feature-y
  git worktree remove feature-x
  git branch -D feature-x
  git push origin --delete feature-x
  git worktree prune

🎯 Working with Worktrees

After initialization, your project structure looks like:

awesome-project/
β”œβ”€β”€ .bare/          # Bare repository (all git data)
β”œβ”€β”€ .git            # Pointer to .bare (single line: "gitdir: ./.bare")
└── main/           # Initial worktree checkout

Create new feature branch

cd awesome-project
git worktree add -b feature-auth feature-auth main

Checkout existing remote branch

git fetch origin
git worktree add feature-ui origin/feature-ui

Remove worktree

git worktree remove feature-auth
git branch -D feature-auth                  # Delete local branch
git push origin --delete feature-auth       # Delete remote branch

πŸ’‘ Why Use Git Worktrees?

Traditional Git Workflow Problems

  • Need to stash/commit before switching branches
  • Lose context when switching between features
  • Can't run tests on one branch while coding on another

Git Worktree Benefits

  • Multiple branches checked out simultaneously
  • No more stashing - each branch has its own directory
  • Parallel workflows - run builds/tests on different branches at once
  • Instant branch switching - just cd to another directory
  • Preserve working state - each worktree maintains its own state

πŸ—οΈ Real-World Example

# Initialize project
git_wt_init https://github.com/myteam/webapp.git

cd webapp/

# Work on multiple features in parallel
git worktree add -b feature/api-v2 api-v2 main
git worktree add -b feature/new-ui new-ui main
git worktree add -b bugfix/login-issue login-fix main

# Your workspace now looks like:
# webapp/
# β”œβ”€β”€ .bare/
# β”œβ”€β”€ .git
# β”œβ”€β”€ main/           # stable main branch
# β”œβ”€β”€ api-v2/         # working on API v2
# β”œβ”€β”€ new-ui/         # UI redesign
# └── login-fix/      # fixing login bug

# Run tests in main while developing in feature branch
cd main && npm test
cd ../api-v2 && npm run dev

# When done with a feature
cd ..
git worktree remove api-v2

πŸ› οΈ Aliases Included

The script includes a handy alias:

  • gwt β†’ git worktree (with git completion support)
gwt list
gwt add -b new-feature new-feature main
gwt remove old-feature

πŸ“‹ Requirements

  • Git 2.5+ (for worktree support)
  • Bash 4.0+

⚑ Pro Tips

  1. Keep main branch clean: Always have a clean main worktree for quick hotfixes
  2. Name consistency: Name your worktree directories after branches for clarity
  3. Cleanup regularly: Use git worktree prune to remove stale metadata
  4. IDE friendly: Each worktree is a separate directory - perfect for multiple IDE windows
  5. CI/CD testing: Test different branches simultaneously on your local machine

🚨 Common Pitfalls to Avoid

  • Don't create worktrees inside other worktrees
  • Remember to fetch before checking out remote branches
  • Each branch can only have one worktree at a time
  • Worktrees share the same git hooks and config

πŸ“š Learn More

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment