===== Overview ===== How to create, use and remove worktrees, as an alternative to constantly stashing and popping when you need to change contexts. ===== DESCRIPTION ===== From ''man git-worktree'': A git repository can support multiple working trees, allowing you to check out more than one branch at a time. With git worktree add a new working tree is associated with the repository. This new working tree is called a "linked working tree" as opposed to the "main working tree" prepared by "git init" or "git clone". A repository has one main working tree (if it’s not a bare repository) and zero or more linked working trees. When you are done with a linked working tree, remove it with git worktree remove. ===== SYNOPSIS ===== Also from ''man git-worktree'': git worktree add [-f] [--detach] [--checkout] [--lock] [-b ] [] git worktree list [--porcelain] git worktree lock [--reason ] git worktree move git worktree prune [-n] [-v] [--expire ] git worktree remove [-f] git worktree unlock ===== Links ===== Various online links related to worktrees: * [[https://git-scm.com/docs/git-worktree|man page]] * [[https://stackoverflow.com/questions/31935776/what-would-i-use-git-worktree-for|Stack Overflow: What would I use git-worktree for?]] * [[https://spin.atomicobject.com/2016/06/26/parallelize-development-git-worktrees/|Atomic Object: Parallelize Development Using Git Worktrees]] * [[https://stacktoheap.com/blog/2016/01/19/using-multiple-worktrees-with-git/|StackToHeap: Using multiple worktrees with git]] * [[https://www.saltycrane.com/blog/2017/05/git-worktree-notes/|SaltyCrane Blog: git worktree notes]] * [[https://blog.reelworx.at/detail/git-worktree-making-typo3-core-development-more-efficient/|ReelWorx: git worktree - making TYPO3 Core development more efficient]] * [[https://152percent.com/blog/2018/4/17/code-review-with-git-worktrees|Code review with Git Worktree]] ===== Issues related to worktrees ===== Drawbacks of ''git stash'': * Constant stashing and unstashing to move between different working directory states. * ''git stash'' doesn't work with unmerged paths, after a merge or rebase with conflicts. * If you work with a compiled language, stashing means you'll have to recompile everything upon unstashing. Applications of worktrees: * Emergency fixes. * Having multiple released versions of the software open at a time, for maintenance. * Testing that takes a long time that would normally tie up your working directory. * Comparing the //behaviour// of different versions of the software. Weaknesses of worktrees: * Can't (normally) have the same branch checked out in two working trees. * Incomplete support for submodules. ===== Condensed example ===== ==== Create a new worktree ==== From within your current working tree, create a new worktree outside the working tree, with a new branch called ''emergency'' off of the current master branch: $ git worktree add -b emergency ../temp master ==== Work in that worktree ==== ''cd'' to that new worktree, work, commit your work on the ''emergency'' branch, and return to your original working tree: $ pushd ../temp ... hack hack hack hack hack hack hack hack hack fix ... $ git commit -a -m "commit emergency fix" $ popd where you can see the additional branch you created in the worktree: $ git branch emergency * master $ ==== Remove the worktree ==== If you have no further use for the worktree, remove it, which has no effect on the branch that was created: $ git worktree remove ../temp $ git branch emergency * master $ ===== Detailed example ===== ==== Initial state of the main working tree ==== Using the "Pro Git" book as a test repo, start with some staged and unstaged changes on the ''master'' branch: $ git status On branch master Your branch is up to date with 'rpjday/master'. Changes to be committed: (use "git reset HEAD ..." to unstage) modified: README.asc Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: LICENSE.asc $ The original working tree is referred to as the "main working tree", while subsequent worktrees are "linked working trees," so you always have at least one worktree: $ git worktree list /home/rpjday/ebooks/progit/progit2 dd124f7 [master] $ ==== Creating the linked working tree ==== Create a working tree off of an earlier tag (''2.1.100''): $ git worktree add -b emergency ../temp 2.1.100 Preparing worktree (new branch 'emergency') HEAD is now at f2d0827 Merge pull request #1145 from rpjday/topic/rpjday/maintaining $ List the working trees: $ git worktree list /home/rpjday/ebooks/progit/progit2 dd124f7 [master] /home/rpjday/ebooks/progit/temp 90bdf0a [emergency] $ Note that nothing has changed in the current working tree: $ git status On branch master Your branch is up to date with 'rpjday/master'. Changes to be committed: (use "git reset HEAD ..." to unstage) modified: README.asc Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: LICENSE.asc $ ==== Move to new working tree ==== $ pushd ../temp Check the status: $ git status On branch emergency nothing to commit, working tree clean $ List all working trees: $ git worktree list /home/rpjday/ebooks/progit/progit2 dd124f7 [master] /home/rpjday/ebooks/progit/temp 90bdf0a [emergency] $ Verify current branch, and current position in history: $ git show commit f2d082747b0a9474f9d2d08c6945482b55691e4a (HEAD -> emergency, tag: 2.1.100) Merge: 7a13f5a 5c0663e Author: Ben Straub Date: Mon Dec 10 10:06:11 2018 -0800 Merge pull request #1145 from rpjday/topic/rpjday/maintaining maintaining: explain how "git describe" works with lightweight tags $ Examine the ''.git'' //file// in this linked working tree -- this is what identifies a linked working tree: $ cat .git gitdir: /home/rpjday/ebooks/progit/progit2/.git/worktrees/temp $ ==== Make and commit a change in the worktree ==== Make a change, and stage it: $ git diff --cached diff --git a/README.asc b/README.asc index fa40bad..9d69d12 100644 --- a/README.asc +++ b/README.asc @@ -1,3 +1,5 @@ +Change to README.asc on emergency branch in worktree + = Pro Git, Second Edition Welcome to the second edition of the Pro Git book. $ Commit: $ git commit -m "Change README.asc in worktree" [emergency 8b31c7b] Change README.asc in worktree 1 file changed, 2 insertions(+) $ Verify: $ git show commit 8b31c7b18e22fddca50eb9af706b6927f2c14ddc (HEAD -> emergency) Author: Robert P. J. Day Date: Sun Feb 24 08:36:12 2019 -0500 Change README.asc in worktree diff --git a/README.asc b/README.asc index fa40bad..9d69d12 100644 --- a/README.asc +++ b/README.asc @@ -1,3 +1,5 @@ +Change to README.asc on emergency branch in worktree + = Pro Git, Second Edition Welcome to the second edition of the Pro Git book. $ ==== Return to main working tree ==== $ popd ~/ebooks/progit/progit2 $ Everything here is just where we left it: $ git status On branch master Your branch is up to date with 'rpjday/master'. Changes to be committed: (use "git reset HEAD ..." to unstage) modified: README.asc Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: LICENSE.asc $ Linked working tree and ''emergency'' branch are still there: $ git worktree list /home/rpjday/ebooks/progit/progit2 5df317d [master] /home/rpjday/ebooks/progit/temp 8b31c7b [emergency] $ $ git branch emergency * master $ What you choose to do with the work committed to the ''emergency'' branch is up to you. ==== Remove working tree ==== Once you're done with the worktree, remove it and "prune" it: $ git worktree remove ../temp [rpjday@localhost progit2]$ git worktree list /home/rpjday/ebooks/progit/progit2 5df317d [master] $ Note that the ''emergency'' branch still exists. $ git branch emergency * master $ ===== Additional issues to cover ===== * locking and unlocking working trees * moving working trees * git config %%--%%worktree (man git-config) * config var ''extensions.worktreeConfig'' * config var ''gc.worktreePruneExpire'' * config var ''worktree.guessRemote'' * setting up tracking branches * detached HEAD state $GIT_DIR/config.worktree This is optional and is only searched when extensions.worktreeConfig is present in $GIT_DIR/config.