How to Build a Git Worktree Workflow for Faster Context Switching
How to Build a Git Worktree Workflow for Faster Context Switching
Git worktrees let you work on multiple branches from the same repository at once, which makes it much easier to juggle a feature, a bug fix, and a review without constantly stashing or re-cloning. The core commands are git worktree add, git worktree list, git worktree remove, git worktree move, and git worktree repair; they create linked working directories that share one repository’s data but keep separate working trees and indexes.
Why this workflow helps
A normal branch workflow forces you to stop, stash, switch, and restart every time you change tasks. With worktrees, each task gets its own directory, so your editor, terminal, and local server stay tied to one branch at a time. That reduces context-switching mistakes and makes parallel work feel much more like handling separate projects.
This is especially useful when you are reviewing a PR while still building another feature. Instead of losing your place, you can keep one worktree on the feature branch and another on the review branch, then compare behavior side by side.
When to use it
Use worktrees when you need one of these patterns:
- A hotfix must be patched immediately while feature work continues.
- You want to test a release candidate without disturbing your main branch.
- You need to compare two implementations in separate checkouts.
- You review a teammate’s branch while continuing your own work.
Git’s documentation says linked worktrees share the same repository objects but keep per-worktree files such as HEAD and index separate, which is why the setup stays lightweight. That means you get the speed of one clone with the isolation of multiple directories.
Set up the first worktree
Start from your main repository and create a dedicated folder for each task. A simple pattern is to name the directory after the branch or ticket, which makes it obvious what belongs where.
### from your main repo
git worktree add ../project-fix-login fix-login
git worktree add ../project-release-candidate release/v1.8
git worktree list
git worktree add <path> [<commit-ish>] creates a new working directory and checks out the chosen commit or branch there. If you do not specify a branch, Git can use the current checkout history, and if you want a new branch, you can use -b with add.
A practical habit is to run your normal setup inside each worktree:
cd ../project-fix-login
npm install
npm run dev
Treat every worktree like a fresh workspace. That keeps dependency caches, dev servers, and file watchers aligned with the branch you are actually editing.
Organize directories cleanly
A clear folder naming system prevents confusion when you have several branches open. Good names usually include the project, the issue number, or the branch purpose.
Examples:
~/code/myapp-main
~/code/myapp-bug-1421
~/code/myapp-review-pr-88
~/code/myapp-release-1.8
Keep one editor window per worktree if your tools tend to reuse terminals or caches aggressively. That separation lowers the risk of editing the wrong branch, running tests in the wrong directory, or pushing from the wrong checkout.
Daily branch switching without pain
A useful routine is to assign one worktree to one stream of work and leave it there until the task is done. For example, keep feature development in one directory and urgent bug fixes in another. When feedback arrives on a PR, open the review worktree and make the requested change there instead of interrupting your current task.
### see all active worktrees
git worktree list
### create a new worktree from the current branch
git worktree add ../myapp-review -b review/notes
### remove a finished worktree
git worktree remove ../myapp-review
Git will refuse to attach the same branch to multiple worktrees, so if you need a second checkout, create a new branch or use a detached HEAD. That rule is actually helpful because it prevents accidental overlap between two directories that are supposed to represent different states of the code.
Safe cleanup and repair
When a worktree is finished, remove it cleanly instead of deleting the folder manually. Git says git worktree remove only succeeds on clean trees unless you pass force, and the main working tree cannot be removed. That makes cleanup predictable and reduces the chance of orphaned metadata.
If a worktree folder gets moved outside Git’s knowledge, use git worktree move or git worktree repair rather than hand-editing paths. move is for intentional relocation, while repair helps restore administrative files if they become corrupted or outdated.
git worktree move ../myapp-bug-1421 ../archive/myapp-bug-1421
git worktree repair ../archive/myapp-bug-1421
git worktree prune
git worktree prune is useful after a manual cleanup because it removes stale references from Git’s internal worktree records.
Pair it with hooks
Worktrees become even better when you add guardrails to each checkout. Git hooks can stop risky actions before they cause damage; for example, pre-push hooks can abort a push if checks fail. That is useful when each worktree is tied to a different task and you want every branch to pass the same local checks before it leaves your machine.
A simple pre-push example:
#!/bin/sh
npm test || exit 1
npm run lint || exit 1
Put that in .git/hooks/pre-push and make it executable. Because worktrees share the same repository data but have separate working directories, the hook will run in the context of the worktree you are pushing from, which helps keep task-specific mistakes isolated.
Add fast feedback loops
Worktrees work best when each directory has a quick “edit, test, verify” loop. In practice, that means keeping commands short and repeatable:
npm test
npm run lint
npm run typecheck
If your project is on GitHub Actions, dependency caching can speed up CI so your local worktree rhythm and remote validation feel closer together. In other words, the more your local workflow and CI workflow agree, the less time you spend waiting for validation after each branch-specific change.
Example workflow
Here is a realistic flow for one developer on three parallel tasks:
- Keep
mainin the primary repo. - Create a worktree for a hotfix branch.
- Create a second worktree for a larger feature.
- Open a third worktree only for code review.
- Run tests and servers independently inside each directory.
- Merge the branch, remove the worktree, and prune stale references.
git worktree add ../app-hotfix hotfix/login-redirect
git worktree add ../app-feature feature/search-filters
git worktree add ../app-review review/pr-204
cd ../app-hotfix && npm test
cd ../app-feature && npm run dev
cd ../app-review && git diff origin/main
This setup gives you separate spaces for separate mental modes. That matters because debugging, feature building, and reviewing are not the same kind of work, even if they all happen in the same repo.
Common mistakes
The biggest mistake is treating worktrees like disposable folders and deleting them manually. That leaves stale metadata behind, which is why git worktree remove, prune, and repair exist. Another common mistake is running one dev server across multiple worktrees and assuming the port, cache, or watcher state will stay sane; it usually will not.
A third mistake is forgetting that the same branch cannot be checked out in two worktrees at once. If you need a duplicate checkout for experimentation, create a throwaway branch instead of trying to force one branch into two places.
A small starter policy
If you want this workflow to stick, keep the rules tiny:
- One worktree per active task.
- One terminal and editor window per worktree.
- One dev server per worktree.
- Remove worktrees as soon as the task ships.
- Use hooks so every worktree runs the same local checks.
That is enough to turn worktrees into a reliable productivity system instead of just another Git trick. Once the habit is in place, switching between tasks stops feeling like branch juggling and starts feeling like opening the right workspace for the right job.
-
Rizwan Saleem | https://rizwansaleem.co
Top comments (0)