.gitignore for Xcode and iOS

xcuserdata/ *.xcuserstate build/ DerivedData/ *.ipa *.dSYM .build/ Pods/

An Xcode .gitignore ignores per-user state (xcuserdata/, *.xcuserstate), build output (build/, DerivedData/, and .build/ from Swift Package Manager), packaged apps and debug symbols (*.ipa, *.dSYM), and CocoaPods’ Pods/. Those are the key lines of the tool’s Swift & Xcode template, which has 30.

What the blocks ignore

  • Per-user state: xcuserdata/ at any depth, inside the project and the workspace, holding window layout, breakpoints and unshared schemes.
  • Build output: build/, DerivedData/, .build/, and *.hmap.
  • Packaging: *.ipa, *.dSYM and *.dSYM.zip.
  • Swift packages: .swiftpm/configuration/registries.json and Xcode’s generated package.xcworkspace file, not the whole .swiftpm/ folder.
  • Dependencies and tooling: Pods/, Carthage/Build/, and fastlane’s reports and screenshots.

In a scratch repository with this file, git check-ignore -v -n --no-index names the line that matched each path, or prints :: when none did:

::	MyApp.xcodeproj/project.pbxproj
::	MyApp.xcodeproj/xcshareddata/xcschemes/MyApp.xcscheme
::	MyApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
.gitignore:3:xcuserdata/	MyApp.xcodeproj/xcuserdata/me.xcuserdatad/xcschemes/xcschememanagement.plist
.gitignore:8:DerivedData/	DerivedData/x
::	.swiftpm/xcode/xcshareddata/xcschemes/MyLib.xcscheme
::	Podfile.lock
.gitignore:31:Pods/	Pods/Alamofire/x

Never ignore xcshareddata

project.pbxproj is the project itself. Everything under xcshareddata/ is shared on purpose: schemes you marked Shared, which CI needs for xcodebuild -scheme, and swiftpm/Package.resolved, the lockfile for your Swift packages. A blanket *.xcodeproj/* or .swiftpm/ line hides them. Commit Podfile.lock too, so pod install restores the same Pods/.

build/ and a folder called Build

Git on a Mac usually runs with core.ignorecase on, so build/ also matches a source group folder named Build. On Linux CI it doesn’t, and the two machines disagree:

::	Sources/MyLib/Build/Helper.swift
.gitignore:7:build/	Sources/MyLib/Build/Helper.swift

The first line is core.ignorecase=false, the second true. Rename the folder, or anchor the line as /build/.

How the !default lines work

The template pairs each Xcode 3 per-user format with its shared default, such as *.pbxuser and !default.pbxuser. The ! line comes second, because the last match wins, and it works because neither file sits in an excluded folder:

.gitignore:11:*.pbxuser	me.pbxuser
.gitignore:12:!default.pbxuser	default.pbxuser

Inside an excluded folder, ! does nothing: Git never looks into xcuserdata/, so a line re-including xcuserdata/me.xcuserdatad/xcschemes/MyApp.xcscheme still leaves it reported against line 3. Tick Shared for it under Product > Scheme > Manage Schemes instead, and Xcode moves the scheme into xcshareddata/.

Committed xcuserdata already?

.gitignore only affects untracked files. Untrack it, keeping it on disk, and commit:

git rm -r --cached MyApp.xcodeproj/xcuserdata MyApp.xcodeproj/project.xcworkspace/xcuserdata
git commit -m "Stop tracking per-user Xcode state"

.DS_Store

This template doesn’t ignore .DS_Store; add the macOS template, or ignore it once for every repository:

git config --global core.excludesFile ~/.gitignore_global

Try it in the Gitignore Generator

In the file: Swift & Xcode

.gitignore

1 template · 30 pattern lines
# Swift & Xcode
# Per-user Xcode state; the project file itself is committed
xcuserdata/
*.xcuserstate
*.xcscmblueprint
*.xccheckout
build/
DerivedData/
*.moved-aside
# Per-user project files from Xcode 3, still written by some tools
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager's build directory
.build/
# Local registry settings and Xcode's generated workspace; the shared schemes in .swiftpm stay committed
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
# CocoaPods; Podfile and Podfile.lock stay committed
Pods/
Carthage/Build/
# Fastlane run output
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
  • ✓Not ignored: no line in this file matches "/MyApp.xcodeproj/xcshareddata/xcschemes/MyApp.xcscheme".

Lines are applied top to bottom, and the last one that matches wins — which is why a line of your own can overrule a template.

Runs in your browser. Nothing you enter is sent anywhere.