foundry
foundry

Reputation: 31745

gitignore negations ignored by git for osx xcode project

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

Answers (1)

michas
michas

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

Related Questions