Simple shell wrapper for git worktree that adds helpers like fork go and
fork main, and integrates with your shell so branch hopping stays fast, clean,
and scriptable.
- Consistent worktree layout: worktrees in
../<repo>_forks/<branch> - Simple navigation:
fork go <branch>to switch or create,fork mainto return - Shell integration: automatic directory changes and config loading
- Container isolation: optional containerized development per fork using Docker or Podman
# Make fork.sh executable after downloading it
chmod +x fork.sh
# Make available on PATH by symlinking or copying
sudo ln -sf "$(pwd)/fork.sh" /usr/local/bin/forkTo support automatic directory changes, add the integration snippet to your shell config.
Add to ~/.bashrc or ~/.zshrc:
# Optional: set FORK_ENV before loading integration
export FORK_ENV=~/.config/fork/config.env
eval "$(fork sh)"Reload: source ~/.zshrc or source ~/.bashrc
Add to ~/.config/fish/config.fish:
# Optional: set FORK_ENV before loading integration
set -gx FORK_ENV ~/.config/fork/config.env
fork sh | sourceReload: source ~/.config/fish/config.fish
The fork sh command auto-detects your shell from $SHELL. If you prefer to specify explicitly:
fork sh bashfor Bashfork sh zshfor Zshfork sh fishfor Fish
You can then copy the output of fork sh and paste it into your shell config file.
If FORK_ENV is set when running fork sh, the configuration variables are
embedded directly into the generated shell function, ensuring they're passed to
every fork invocation.
fork go feature-x # create from main and switch
git commit -am "work"
fork go feature-y # jump to another worktree
fork main # return to main worktree
fork new one two three # create multiple worktrees
fork co one # switch to `one` worktree
fork new dev -t develop # create from develop branch
fork ls # list worktrees
fork clean # remove merged and clean worktreesfork new feature-x # create from main
fork new feature-a feature-b # create multiple
fork new bugfix --target develop # create from develop branchfork go feature-x # go to worktree (create if needed)
fork co feature-x # go to worktree (must exist)
fork main # go to main worktreefork ls # list all worktrees
fork ls -u # list unmerged only
fork ls -m # list merged only
fork ls -d # list dirty worktrees (uncommitted/untracked changes)
fork ls -c # list clean worktreesfork rm # remove current worktree
fork rm feature-x # remove specific
fork rm -f feature-x # force remove (if unmerged or dirty)
fork rm -a # remove all
fork clean # remove all merged and clean worktreesProtection: Worktrees are protected from deletion if they are:
- Unmerged (have commits not in the base branch), OR
- Dirty (have uncommitted changes, staged changes, or untracked files)
Use -f/--force to bypass these protections.
/path/to/
├── myproject/ # base repository
└── myproject_forks/ # forks directory
├── feature-x/
├── feature-y/
└── bugfix-123/
You can customize this pattern using the FORK_DIR_PATTERN environment variable
(see Configuration).
fork supports creating isolated containers for each fork, providing a clean environment separate from your host system. This is useful for:
- Testing code in a clean environment
- Isolating dependencies per branch
- Running potentially unsafe code
- Consistent development environments across machines
# Work in a temporary container (auto-removed on exit)
fork go feature-x -c
# Keep container running for faster re-entry
fork go feature-x -c -k
# Use a custom image
export FORK_CONTAINER_IMAGE=ubuntu:22.04
fork go feature-x -c
# Use a Dockerfile
export FORK_CONTAINER_DOCKERFILE=./dev.Dockerfile
fork go feature-x -cSet these in your ~/.config/fork/config.env or shell environment:
FORK_CONTAINER=1 # Enable container mode by default
FORK_CONTAINER_IMAGE=ubuntu:latest # Base image to use
FORK_CONTAINER_DOCKERFILE=/path/to/Dockerfile # Build from Dockerfile (overrides IMAGE)
FORK_CONTAINER_RUNTIME=docker # Runtime: docker or podman
FORK_CONTAINER_NAME=myproject # Container name prefix
FORK_CONTAINER_KEEP_ALIVE=1 # Keep containers running in backgroundNote: If FORK_CONTAINER_DOCKERFILE is set, images are built with the tag fork_{branch}_image and used instead of pulling FORK_CONTAINER_IMAGE.
- Ephemeral mode (default): Container runs with
--rmand is automatically removed when you exit - Keep-alive mode (
-kflag orFORK_CONTAINER_KEEP_ALIVE=1): Container runs in background and persists between sessions - Mount: Only the worktree directory is mounted at
/{repo_name}with read-write access - Working directory: Automatically set to the mounted worktree
- Removal: Use
fork rm <branch> -cto remove both worktree and container
- Docker or Podman installed and running
- Sufficient permissions to run containers
- Base image should have
gitand your preferred shell/tools installed
- Wraps
git worktree - Enforces consistent directory structure
- Never deletes branches, only worktrees
- Git 2.5 or newer with
git worktree - POSIX-compliant
shplus standard utilities (awk,sed,grep,mkdir,rm) - Bash, Zsh, or Fish shell for directory-changing integration
Run the shell-based harness from the repository root:
sh test.sh # run full suite
sh test.sh --fast # fail fast after the first error
sh test.sh --no-cache # run full suite without reusing cache
# Docker
docker build -f .docker/Dockerfile -t fork-tests .
docker run --rm fork-tests # full suite
docker run --rm fork-tests --fast # fail fast mode
docker run --rm fork-tests --no-cache # full suite without cache
docker run --rm fork-tests --verbose # full verbose outputBy default only the final summary is shown; pass --verbose to stream every assertion. The script creates temporary repositories under ${TMPDIR:-/tmp} and removes them on exit. Results are cached based on the contents of fork.sh and test.sh; pass --no-cache to bypass the cache for a single run, set FORK_TEST_CACHE_PATH to override the cache directory, or delete the cache file to force a rerun.
fork supports loading configuration from an environment file via the FORK_ENV variable:
export FORK_ENV=~/.config/fork/config.envThe env file should contain FORK_* prefixed variables (one per line):
# ~/.config/fork/config.env
FORK_DIR_PATTERN=../{repo}_forks/{branch}
FORK_DEBUG=1- Only variables prefixed with
FORK_are loaded - When using shell integration (
fork sh), these variables are automatically embedded in the generated function so they're passed to everyforkinvocation
fork inspects the following environment variables:
FORK_CD: Controls navigation message output
- When
FORK_CD=1, commands such asfork go,fork co,fork main, andfork rmemit only the target path on stdout so wrapper functions cancdinto place without extra output. - When
FORK_CDis unset or0, the same commands print human-friendly status messages on stderr in addition to the path.
FORK_ENV: Path to configuration file
- If set, loads
FORK_*variables from the specified file on startup
FORK_DIR_PATTERN: Custom worktree directory pattern
- Currently displays on startup if set (for demonstration purposes)
- Future versions may use this to customize worktree directory patterns
Container-related variables:
FORK_CONTAINER: Enable container mode by default
- Set to
1to use containers without-cflag
FORK_CONTAINER_IMAGE: Container image to use
- Default:
ubuntu:latest - Can be any Docker/Podman image
FORK_CONTAINER_DOCKERFILE: Path to Dockerfile to build
- If set, builds image from Dockerfile instead of using
FORK_CONTAINER_IMAGE - Built images are tagged as
fork_{branch}_image
FORK_CONTAINER_RUNTIME: Container runtime
- Default:
docker - Also supports:
podman
FORK_CONTAINER_NAME: Container name prefix
- Default: none (containers named
{branch}_fork) - If set, containers named
{prefix}_{branch}_fork
FORK_CONTAINER_KEEP_ALIVE: Keep containers running
- Default:
0(containers auto-removed with--rm) - Set to
1to keep containers running in background between sessions
fork help
fork help --verboseMIT