Quick branch switching without confusing Xcode

Xcode doesn’t always like it when you swap branches, especially when there are a lot of code changes between the branches. This can cause all kinds of build caches to become invalid forcing your Xcode to do lots of work. What’s worse is now your mental resources are concentrated on getting your project compiling again instead of solving interesting problems.

The work I’ve been doing recently has been very bitty with helping colleagues by jumping on screen shares, reviewing PRs or even finding new requirements in my tickets that need work playing before I can continue. All of these scenarios require me to checkout a different branch, which leads to the problems mentioned above.


Use git worktree to get multiple checkouts of a project using a single git repo.

If I have a project called epic-todo-list-app and a colleague asks for help on their branch named feature/allow-users-to-complete-tasks, I can run the following command:

git worktree add ../epic-todo-list-app-tmp feature/allow-users-to-complete-tasks

Now on disk I’ll have both projects

ls -1 src/ios

The original project folder will just be my repo in whatever state I was in. The new project folder epic-todo-list-app-tmp will have the repo checked out to feature/allow-users-to-complete-tasks.

At this point I can now open both projects independently in Xcode and they’ll have their own derived data, which means I don’t need to deal with the time sink of getting Xcode to compile the new branch and then my original branch when I switch back.

NB - this technique is really helpful when working with different Xcode versions. I can have one checkout for the beta and one for the GM version and they won’t destroy each other’s derived data.

Why use git worktree?

I’ve been using a variation of this technique for a long time now where I was just keeping multiple complete copies (full clones) of the repo. This isn’t great for a few reasons:

git worktree solves the above problems by the fact that each project folder is backed by the same git repo on disk. So any operations like fetch, checkout -b, merge…. are all reflected in each place you invoke git.


Once you’ve finished with the worktree you can easily remove it using the remove command. If I wanted to get rid of the worktree I created earlier I’d call

git worktree remove ../epic-todo-list-app-tmp

It’s worth exploring the docs as they aren’t long or too scary looking https://git-scm.com/docs/git-worktree.