35

I was looking at an open source Mac application, and they gave some suggested values for .gitignore. They were what I would expect...

However, they also suggested an entry into a .gitattributes file:

*.pbxproj -crlf -diff -merge

I'm not the most knowledgable in terms of git, so I was wondering - what exactly are the benefits of adding this line? What does do in particular? I've only seen this suggested in this one project, and if it was normal practice I would have expected to see it elsewhere right now. So I was curious about how it applies to the pbxproj file specifically.

DarthNerdus
  • 1,340
  • 1
  • 13
  • 14
  • The post http://stackoverflow.com/questions/2615378/how-to-use-git-properly-with-xcode encourages merging of `.pbxproj` files. – Besi Jul 16 '12 at 12:10

4 Answers4

28

The pbxproj file isn't really human mergable. While it is plain ASCII text, it's a form of JSON. Essentially you want to treat it as a binary file.

Here's what the individual flags do:

-crlf: don't use crlf <=> cr conversion

-diff: do not diff the file

-merge: do not attempt to merge the file

From the Pro Git book by Scott Chacon

Some files look like text files but for all intents and purposes are to be treated as binary data. For instance, Xcode projects on the Mac contain a file that ends in .pbxproj, which is basically a JSON (plain text javascript data format) dataset written out to disk by the IDE that records your build settings and so on. Although it’s technically a text file, because it’s all ASCII, you don’t want to treat it as such because it’s really a lightweight database — you can’t merge the contents if two people changed it, and diffs generally aren’t helpful. The file is meant to be consumed by a machine. In essence, you want to treat it like a binary file.

Grant Limberg
  • 20,913
  • 11
  • 63
  • 84
  • `-crlf` is no "strip crlf characters" but **don't** (the option is negated) use crlf conversion (crlf <-> cr) on this file. – Jakub Narębski Oct 11 '09 at 09:27
  • 11
    In my (admittedly somewhat limited) experience, very simple changes (such as adding a new file) can usually be merged in a .pbxproj file. If you do anything more complicated, like have one branch add a file, and another re-arrange your source groups, then you'll usually get a corrupted .pbxproj, but for simple stuff it's often doable. I'm undecided on whether or not it's better to treat .pbxproj files as binary or not. – Nick Forge Apr 28 '10 at 11:51
  • 1
    I agree, I've had good success merging .pbxproj files using Perforce. I took great care and went over each change thoroughly. It takes time but it certainly is doable. So far I haven't ended up with a corrupt project file. But I also knew what changes I have made, and I'm only integrating in one direction (just not integrating everything). – CodeSmile Dec 09 '10 at 23:16
  • 4
    The thing that fails in merging project files, 99% of the time, is when two people add new files. Then there is a conflict, easily solved by accepting both changes. Other than that if one person did something like change settings it would easily nerd with other changes. If you think about it JSON is really just like any other code SCM systems have to merge. – Kendall Helmstetter Gelner Nov 02 '11 at 19:37
  • 19
    The quote from Scott Chacon is plain wrong. The .pbxproj format is perfectly "human" readable and easily modifiable... Btw, I recently started to use "merge=union" for .pbxproj files and it seems ok so far... – Ariel Malka Jun 05 '12 at 18:36
  • 1
    Plus the original "Xcode" project file format WAS binary. They changed it a while ago to be human readable precisely for dealing with the project residing in a version control system. – dbainbridge Jan 07 '13 at 23:56
  • "Treat it like a binary file?" Aaaaaannnnd what do you do when you have a merge conflict in this binary file? – ScottyBlades Aug 23 '21 at 04:31
7

A diff is oftentimes useful at commit time to check what has been changed. So I find it useful to keep the diffing ability but just prevent merging. So I use this in my .gitattributes file:

*.pbxproj -crlf -merge

On another note, has anybody tried using merge=union for pbxproj files? See: Should I merge .pbxproj files with git using merge=union?

Community
  • 1
  • 1
Ortwin Gentz
  • 52,648
  • 24
  • 135
  • 213
5

I faced the problem of corruption *.pbxproj file after resolving merge conflicts manually. Or, more often, my files just 'disappeared' from the working tree after the merge. It drove me mad because we work in a team, so you can imagine how messy it can become very fast.

So, I have tested merge=union and it works well so far. I know that it can't help if files were deleted or renamed at the same time, but for adding new files it works as expected: there is no conflicts and files don't disappear after the merge. And it also saves quite a bit of time.

If you want to try it out, here is what I did.

1) Create a global .gitattributes file. Run in terminal:

touch ~/.gitattributes
git config --global core.attributesfile ~/.gitattributes

2) This command should open it in a text editor:

open ~/.gitattributes

3) When the file opens, add this line and save the file:

*.pbxproj binary merge=union

Done. Hope this will help new readers like it helped me.

joliejuly
  • 2,127
  • 1
  • 21
  • 24
3

I wrote a python script named xUnique to solve this merge conflicts problem.

This script do following things:

  • replace all 24 chars UUID to project-wide unique 32 chars MD5 digests, and remove any unused UUIDs(usually caused by careless merge before). This would prevent duplicate UUIDs because different machines/Xcode generate different UUIDs in this file. Xcode does recognize it and the project could be opened. During this process, remove all invalid lines in project file
  • sort the project file. I wrote a python version of sort-Xcode-project-file from Webkit team with more new features:
    • support to sort PBXFileReference and PBXBuildFile sections
    • remove duplicated files/refs
    • avoid creating new file even if no changes made, this makes less commits after using this script

More details and updates of xUnique, please refer to README

Xiao
  • 12,235
  • 2
  • 29
  • 36
  • Good idea, but man it's complicated to use. – ScottyBlades Aug 23 '21 at 04:32
  • @ScottyBlades basically it's just a command to be executed. other options like git hook or 'build-post-action' just make you run the command a little easier. – Xiao Aug 24 '21 at 06:10