Reputation: 31745
This question arises from reading and commenting on another question: Git ignore file for Xcode projects
While Adam's answer (and accompanying gist) appears definitive, I cannot actually get it to work. My understanding of the gitignore syntax seems incomplete.
My setup: OSX 10.8.2, git version 1.7.9.6 (Apple Git-31.1). There are no global gitignore files.
I am testing on a new project created with the OSX Application template in Xcode 4.5.
This is the test project file layout:
./.gitignore
./MyApp
./MyApp/AppDelegate.h
./MyApp/AppDelegate.m
./MyApp/en.lproj
./MyApp/en.lproj/Credits.rtf
./MyApp/en.lproj/InfoPlist.strings
./MyApp/en.lproj/MainMenu.xib
./MyApp/main.m
./MyApp/MyApp-Info.plist
./MyApp/MyApp-Prefix.pch
./MyApp.xcodeproj
./MyApp.xcodeproj/project.pbxproj
./MyApp.xcodeproj/project.xcworkspace
./MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
./MyApp.xcodeproj/project.xcworkspace/xcuserdata
./MyApp.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad
./MyApp.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate
./MyApp.xcodeproj/xcuserdata
./MyApp.xcodeproj/xcuserdata/admin.xcuserdatad
./MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes
./MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/MyApp.xcscheme
./MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist
I set up the test project with source control disabled, then initialise the git repo manually in Terminal. The working directory is the project directory:
git init
git add .
git commit -m "first commit"
which returns a list of committed files:
13 files changed, 5204 insertions(+)
create mode 100644 MyApp.xcodeproj/project.pbxproj
create mode 100644 MyApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
create mode 100644 MyApp.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate
create mode 100644 MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/MyApp.xcscheme
create mode 100644 MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist
create mode 100644 MyApp/AppDelegate.h
create mode 100644 MyApp/AppDelegate.m
create mode 100644 MyApp/MyApp-Info.plist
create mode 100644 MyApp/MyApp-Prefix.pch
create mode 100644 MyApp/en.lproj/Credits.rtf
create mode 100644 MyApp/en.lproj/InfoPlist.strings
create mode 100644 MyApp/en.lproj/MainMenu.xib
create mode 100644 MyApp/main.m
After each .gitignore test I reset by deleting the .git folder and reinitialising.
If .gitignore is this
AppDelegate.h
then
./MyApp/AppDelegate.h
is excluded
If I change .gitignore to
AppDelegate*
Both of these are excluded
./MyApp/AppDelegate.h
./MyApp/AppDelegate.m
as expected
If my .gitignore is this:
AppDelegate*
!AppDelegate.m
Again, only AppDelegate.h
is excluded
This is all as expected
However I can't get reincludes to work when the exclusion rule is a containing folder
For example if my .gitignore is this
xcuserdata
then these files are excluded
./MyApp.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate
./MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/MyApp.xcscheme
./MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist
Now if I want to re-include the contents of xcschemes
xcuserdata
!xcschemes
the result is the same - !xcschemes
appears to be ignored.
similarly if .gitignore is
en.lproj
these files are excluded
./MyApp/en.lproj/Credits.rtf
./MyApp/en.lproj/InfoPlist.strings
./MyApp/en.lproj/MainMenu.xib
If I wanted to reinclude one of them
en.lproj
!Credits.rtf
the same files are excluded: !Credits.rtf
is ignored.
the manpage for gitignore just says this:
An optional prefix ! which negates the pattern; any matching file excluded by a previous pattern will become included again. If a negated pattern matches, this will override lower precedence patterns sources.
but I am not sure what "lower precedence patterns sources" means, or whether it is relevant here.
What am I missing?
update
Adam has updated his gitignore gist to take account of these issues. I have wrapped his changes into my fork, and also added some notes on how to add or change such a .gitignore when an XCode project is already under git control.
Upvotes: 1
Views: 1991
Reputation: 26545
Git traverses your file system tree and tries to match your ignore rules. If the rules match a directory that directory is, well, ignored. That means that git will not even look at any contents of it, that's why any exception inside of it will be ignored.
Getting around this is a bit tricky and not always possible.
/MyApp.xcodeproj/xcuserdata/*
!/MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/
/MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/*
!/MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/
/MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/*
!/MyApp.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/MyApp.xcscheme
The above .gitignore will ignore all files in /MyApp.xcodeproj/xcuserdata/
except for MyApp.xcscheme
.
Often it is also possible to pretty much ignore those exceptions and only specify what you actually want to ignore.
Upvotes: 2