Git Worktree with Xcode
Xcode projects have unique challenges when working with git worktree: scheme files, derived data, and the notorious .xcodeproj merge conflicts. This guide covers how to set up and manage worktrees effectively for iOS, macOS, and Swift development in Xcode.
Xcode and Git Worktree Compatibility
Xcode works well with git worktrees out of the box. Each worktree is a standard directory containing your full project, so you can open the .xcodeproj or .xcworkspace from any worktree just as you would from a normal clone. Xcode recognizes the git repository and shows branch information, diffs, and blame annotations correctly.
The main benefit for iOS developers is the ability to keep a stable branch open in one Xcode window while working on a feature or bug fix in another. No more stashing changes or waiting for Xcode to re-index after switching branches. Each worktree maintains its own build state, so you can build and run both branches simultaneously on different simulators.
# Create a worktree for a feature branch
git worktree add ../MyApp-feature feat/new-onboarding
# Open the worktree project in Xcode
open ../MyApp-feature/MyApp.xcodeprojSetting Up Worktrees for iOS Projects
When creating worktrees for an Xcode project, place them as sibling directories to your main checkout. This keeps paths predictable and avoids confusing Xcode with nested project structures.
# From your main project directory
cd ~/Developer/MyApp
# Create worktrees as siblings
git worktree add ../MyApp-bugfix fix/crash-on-launch
git worktree add ../MyApp-experiment experiment/swiftui-navigation
# List all active worktrees
git worktree list
# /Users/you/Developer/MyApp abc1234 [main]
# /Users/you/Developer/MyApp-bugfix def5678 [fix/crash-on-launch]
# /Users/you/Developer/MyApp-experiment ghi9012 [experiment/swiftui-navigation]If your project uses CocoaPods, you will need to run pod install in each new worktree since the Pods directory is typically gitignored. For Swift Package Manager dependencies, Xcode resolves them automatically when you open the project.
# After creating a worktree with CocoaPods
cd ../MyApp-bugfix
pod install
# Then open the workspace (not the project)
open MyApp.xcworkspaceManaging Xcode Project Files Across Worktrees
The project.pbxproj file is the most conflict-prone file in any Xcode project. Git worktrees help reduce these conflicts because each worktree works on its own branch independently. However, when two worktrees both add or remove files, you will still encounter merge conflicts when bringing branches together.
To minimize issues, follow these practices:
- Add new files in only one worktree at a time when possible. Merge frequently to keep branches in sync.
- Use Xcode's folder references instead of groups for directories that change often, as they generate fewer
pbxprojentries. - Consider using
xcodeprojmerge drivers or tools likemergepbxto handle project file merges automatically.
# Install mergepbx for better Xcode merge handling
brew install mergepbx
# Add to your .gitattributes
echo "*.pbxproj merge=mergepbx" >> .gitattributes
# Configure the merge driver
git config merge.mergepbx.name "Xcode project file merge driver"
git config merge.mergepbx.driver "mergepbx %O %A %B"Derived Data and Build Folders
By default, Xcode stores derived data in ~/Library/Developer/Xcode/DerivedData/. Each worktree project gets its own derived data subfolder based on the project name and path hash, so builds from different worktrees do not interfere with each other.
If you want even clearer separation or need to manage disk space, you can configure Xcode to use a per-worktree build directory:
# Option 1: Set derived data location per workspace in Xcode
# Xcode > Settings > Locations > Derived Data > Relative
# Option 2: Use xcodebuild with a custom derivedDataPath
xcodebuild -scheme MyApp \
-derivedDataPath ./build/DerivedData \
-destination 'platform=iOS Simulator,name=iPhone 16'
# Option 3: Clean derived data for a specific worktree
rm -rf ~/Library/Developer/Xcode/DerivedData/MyApp-*Keep in mind that derived data can consume significant disk space. When you remove a worktree, the associated derived data in ~/Library/Developer/Xcode/DerivedData/ is not automatically cleaned up. Periodically delete old derived data folders to reclaim disk space.
Tips for Swift/SwiftUI Projects
Run Multiple Simulators
With worktrees, you can run your app on different simulators from different branches at the same time. Open each worktree's project in a separate Xcode window, select different simulator destinations, and hit Run in both. This is especially useful for comparing UI changes or testing a fix against the current release.
SwiftUI Previews Work Per-Worktree
SwiftUI previews are tied to the project context, so each worktree gets its own preview state. You can have previews running in your main worktree showing the stable UI while iterating on a redesign in another worktree, all without any preview conflicts or cache issues.
Swift Package Manager Dependencies
SPM packages are resolved per workspace. When you open a worktree in Xcode, it will automatically resolve packages based on the Package.resolved file in that branch. If branches have different dependency versions, each worktree correctly uses the right versions independently.
Signing and Provisioning
Code signing settings are stored in the .xcodeproj and are shared across worktrees through git. If you use automatic signing, each worktree will work without additional configuration. For manual signing, ensure your provisioning profiles are installed system-wide so they are available regardless of which worktree you are building from.
Git worktrees integrate smoothly with Xcode and are particularly valuable for iOS development where branch switching can trigger lengthy re-indexing and rebuild cycles. For more on managing worktrees, see the git worktree add tutorial or return to the IDE integration overview.