Git worktree

Share on:

The following blog post illustrates how to use worktree in a git workflow.

A Git worktree allows you to check out multiple branches or commits at the same time. Each worktree is a separate working directory linked to the same repository. This is useful for working on multiple features concurrently, reviewing pull requests without stashing your changes, or experimenting without affecting your main working directory.

Once the worktree is declared, the typical cycle of Add, Commit, Push are then used to sync staging to a repository.

The following will be covered in this blog.

  • Creating a worktree
  • Listing available worktrees
  • Deleting a worktree

Creating a Worktree

Creating a worktree:

This command creates a worktrees associated with the repository.

1git worktree add <path> [<commit-ish>]
  • <path>: This is the only mandatory argument. It specifies the directory where the new worktree will be created. This directory should be empty or non-existent. Git will create the directory if it doesn't exist. It's common practice to use a descriptive name for the worktree directory that reflects its purpose (e.g., ../hotfix-branch, ../experiment-new-feature). The path can be absolute or relative to the root of your repository.
  • [<commit-ish>]: This is an optional argument. It specifies the commit, branch, or tag that the new worktree should be based on. If you omit this, the new worktree will be based on your current HEAD. If you specify a branch name, the new worktree will be linked to that branch. If you specify a commit hash, the new worktree will be in a detached HEAD state, meaning changes you make won't be automatically associated with a branch. Using a branch name is the most common and recommended approach.

Example:

  1. This command creates a new worktree in the directory ../feature-branch.
1git worktree add ../feature-branch feature-branch
  1. This new worktree will be checked out to the feature-branch branch.
1git worktree add ../hotfix HEAD

Any changes you make in this worktree will be reflected on the feature-branch branch. This creates a new worktree at ../hotfix based on the current commit.

Important Considerations:

  • The <path> you choose must not already be a Git repository or a subdirectory of an existing Git repository (other than the main repository).
  • The <commit-ish> you specify must exist in the repository.
  • Creating a worktree doesn't automatically switch you to it. You'll need to cd into the worktree directory to start working there.
  • Worktrees share the same .git directory as the main repository, meaning they share the object database, configuration, etc. This saves disk space compared to cloning the entire repository.

Listing available Worktrees

  1. This command displays all worktrees associated with the repository.
1git worktree list

The main worktree (the one created when you cloned the repository) will be indicated. Other worktrees will show their path and the commit they are checked out to. The output helps you keep track of existing worktrees and their locations.

Deleting a Worktree

  1. Using git worktree remove:

    • Safely removes the worktree. It checks if the worktree is clean (no uncommitted changes or untracked files) before removing it.
    • If the worktree is not clean, the command will fail to prevent data loss. You can force the removal using the -f or --force option (see below).
    • Example: git worktree remove <worktree_name> or git worktree remove <path_to_worktree>
  2. Using git worktree move:

    • If you are using a version of git older than 2.17, git worktree remove may not be available or fully functional. In such cases, moving the worktree outside the repository and then deleting it is a safe alternative.
    • Move the worktree directory outside the main repository directory.
    • Then, delete the directory using your operating system's file manager or command-line tools (e.g., rm -rf <path_to_worktree> on Unix-like systems).
    • After moving and deleting, you'll also need to prune the worktree information from the git config using git worktree prune.
  3. Using git worktree prune:

    • This command cleans up stale worktree information from the .git/config file. It's useful after a worktree has been deleted manually (e.g., using rm -rf or after moving it and deleting it).
    • It removes the entries for worktrees that no longer exist.
    • You usually run this in the main repository.
    • Example: git worktree prune
  4. Forcing removal with -f or --force:

    • If the worktree has uncommitted changes or untracked files, git worktree remove will prevent you from deleting it to avoid data loss.
    • You can use the -f or --force option to override this safety check and force the removal.
    • Example: git worktree remove -f <worktree_name>
    • WARNING: Using -f will delete any uncommitted changes and untracked files in the worktree. Make sure you understand the consequences before using this option. It's generally better to commit or stash your changes first.
  5. Important considerations:

    • Before deleting a worktree, always ensure that you have committed or stashed any important changes. Deleting a worktree is a destructive operation, and you could lose data if you're not c areful.
    • After deleting a worktree, you can run git worktree list to verify that it has been removed.
    • If you accidentally delete a worktree, there's usually no way to recover it unless you had committed the changes or created a backup.

Worktree Example

Git worktree example walkthrough:

  1. Create a new worktree in the repository root folder:

    1git worktree add <path> <branch>
    

    Example: git worktree add ../feature-branch feature/my-new-feature This creates a new directory ../feature-branch and checks out the feature/my-new-feature branch into it. If the branch doesn't exist it will create it based on your current branch.

  2. Change to new worktree folder: Navigate to the newly created directory: cd ../feature-branch Make changes to the files in this directory. These changes are independent of the main working directory. Commit your changes: git add ., git commit -m "Implemented awesome feature"

  3. (Optional) Work in the main worktree: Navigate back to your main working directory: cd ../my-project Make other changes, commit them, and push them, independently of the feature branch.

  4. Push changes from the new worktree: Navigate back to the feature branch worktree: cd ../feature-branch Push your changes: git push origin feature/my-new-feature

  5. List worktrees:**

    1git worktree list
    

    This command shows all active worktrees, their paths, and the branch they are associated with.

  6. Remove a worktree:

    1git worktree remove <path>
    

    Example: git worktree remove ../feature-branch This removes the worktree. Important: The worktree must be clean (no uncommitted changes) before you can remove it. If it's not clean, you will need to either commit or stash the changes. Alternately, you can use the --force flag, but this will delete any uncommitted changes in that worktree. Use with caution. git worktree remove -f ../feature-branch will remove the worktree, discarding any uncommitted changes.

  7. Prune dangling worktrees: If a worktree's directory is deleted without using git worktree remove, Git will still consider it an active worktree (a "dangling" worktree). git worktree prune will remove information about these dangling worktrees. You may need to run this with administrator privileges on some systems if the worktree had different file ownership. git worktree list will no longer show the pruned worktrees.

Conclusion

Git worktrees offer a powerful way to manage multiple working contexts within a single repository. They allow for parallel development, clean experimentation, and streamlined review processes without the need for constant switching of branches or cloning. By understanding and utilizing git worktree, you can significantly enhance your Git workflow and boost your productivity. Remember to clean up worktrees when they are no longer needed using git worktree prune to avoid cluttering your repository.