Git worktrees
Most of the time when using git, your project folder looks like
project/ # root folder├── .git/ # git data├── src/ # code└── README.mdThis works most of the time, but what if you really need to ship a bug fix?
git stash? Clone the repo again somewhere else on your computer? Those work,
but they fall apart with more usecases.
As matklad brings up, what if you need to review someone else’s code, or have a long-running fuzz test session? Cloning the repo 3 times, and pushing back up to github to sync your local changes between the 3 repos is not a great workflow.
Good thing git has a built-in feature that solves this problem: bare
repositories and git worktrees.
In git, a working tree is the folder that contains the actual project files. A
bare repo is a git repo with no working tree. It’s just the .git folder.
Decouple the working tree from the git state allows you to create multiple
working trees for the same git repo.
git init --bare project.giteza --tree project.gitproject.git├── config├── description├── HEAD├── hooks/│ └── ...├── info/│ └── exclude├── objects/│ ├── info│ └── pack└── refs/ ├── heads └── tagsThis is exactly what is in a regular project/.git/.
cd project.gitWhen adding a worktree to your bare repo, you can either check out an existing
branch (git switch / git checkout), or create a new branch (git switch -c
/ git checkout -b).
Since the main branch doesn’t exist, we need to create it.
git worktree add -b main ./maineza --tree ..├── config├── description├── HEAD├── hooks/│ └── ...├── info/│ └── exclude├── main/ # new!│ └── .git├── objects/│ ├── info│ └── pack├── refs/│ ├── heads│ └── tags└── worktrees/ # new! └── main/ ├── commondir ├── gitdir ├── HEAD ├── index └── refsgit added a main folder with the working tree of the main branch. It also
added some bookkeeping for the worktree.
cd mainnvim .and you know the rest.
If you don’t like having the worktrees within mixed with the git files, you can structure your bare repo like
project/├── feature/├── main/└── project.git/You either need to be in the project.git/ folder to run in the commands, or
provide --git-dir=. For example
git --git-dir=project.git worktree add -b feature ./feature mainor
git worktree add -b feature ../feature main