Skip to content
Go back

Git Worktrees

Published:

Worktrees enable checking out multiple branches out at the same time.

You could just clone the whole repo to a new folder to check out a different branch.

    πŸ“‚ MyApp/
    πŸ“‚ MyApp-hotfix/
    πŸ“‚ MyApp-featureX/

But with worktrees you can just use the existing repo to generate more folders with states of different branches.

    πŸ“‚ MyApp/
       β”œβ”€β”€ πŸ“‚ .git
       β”œβ”€β”€ πŸ“‚ main
       β”œβ”€β”€ πŸ“‚ hotfix
       └── πŸ“‚ featureX

Why

In mobile, quickly switching branches for bugfix/review doesn’t really work. With heavily compiled projects a branch switch often causes a long recompilation. Its more efficient to have multiple variants ready on disk.

With AI, having multiple variants allows parallelizing the work agents and you are doing.

Why worktrees

You’ll have a single shared .git folder:

Setup:

  1. Create a root folder for the project.

    mkdir MyApp
    cd MyApp
  2. Clone β€œ.git folder” of the repo

    git clone --bare --config remote.origin.fetch="+refs/heads/*:refs/remotes/origin/*" git@gh.com:u/repo.git .git
    • clone --bare: will copy the repository, but will not populate the source files on disk. We want the sources to be populated in separate worktree folders later.
    • --config remote.origin.fetch: Because bare is intended for git server, it omits the configuration of mapping remote branches to origin/*. We add it back, so our client could see the branches in remote.
    • .git: We name this folder .git. This is convenient as this is the standard .git folder, and now any tooling will also be able to identify it as such. Meaning you can execute git commands in the root MyApp folder.

    Repo state now:

     πŸ“‚ MyApp/
        └── .git/            <-- Repo history
            β”œβ”€β”€ config
            β”œβ”€β”€ HEAD
            └── objects/ ...
  3. Add a worktree

    git worktree add main

    syntax is: git worktree add <worktree_path> -b <branch_name>

    The first command will create a worktree folder in path main and will try to checkout or create a branch named main.

    Repo now:

     πŸ“‚ MyApp/
        β”œβ”€β”€ .git/            <-- Repo history
        └── main/            <-- Project source files (Worktree)
            β”œβ”€β”€ .git         <-- Points to shared .git dir at root.
            β”œβ”€β”€ app/
            β”œβ”€β”€ build.gradle
            └── src/
  4. Profit

    Open the worktree folder main in IDE to work on it. Add more worktrees if needed.

  5. Managing worktrees

    List them by:

    $ git worktree list
    /Users/me/MyApp           (bare)
    /Users/me/MyApp/main      7ac0703be [main]
    /Users/me/MyApp/feature   aa45c02a1 [feature/fix-123]

    Delete:

    git worktree remove <worktree_name>

    Note: Renaming/deleting the worktree folders manually needs caution, as the shared .git is refering to those folders.

Extra

Why not just open an existing repo and worktree add straight away?

You can, but then that worktree would appear alongside the existing source files. So its messy and you have to .gitignore it. Structure:

πŸ“‚ MyApp/               <-- Existing repo and worktree
    β”œβ”€β”€ .git/
    β”œβ”€β”€ src/            <-- Existing source files
    β”œβ”€β”€ build.gradle.   <-- Existing source files
    β”œβ”€β”€ MyApp-Hotfix/   <-- New worktree with new source files
    └── ...

Worktrees in practise

It is more beneficial to have persistent worktrees named by the kind of work you are doing. Such as: work, review, side-work. This means that you are just switching branches inside the worktree, as opposed to creating new worktree/folder for each branch.

With this you can just use your IDE to switch branches. And since you are not opening new folders, you don’t have to do the full initial setup that comes with new projects.



Next Post
KMP Primer