37

There are often conflicts in the Xcode project file (Project.xcodeproj/project.pbxproj) when merging branches (I'm using git). Sometimes it's easy, but at times I end up with a corrupt project file and have to revert. In the worst case I have to fix up the project file manually in a second commit (which can be squashed with the previous) by dragging in files etc.

Does anyone have tips for how to handle merge conflicts in big and complex files like the Xcode project file?


EDIT-- Some related questions:

Git and pbxproj

Should I merge .pbxproj files with git using merge=union?

RESOURCES:

http://www.alphaworks.ibm.com/tech/xmldiffmerge

http://www2.informatik.hu-berlin.de/~obecker/XSLT/#merge

http://tdm.berlios.de/3dm/doc/thesis.pdf

http://www.cs.hut.fi/~ctl/3dm/

http://el4j.svn.sourceforge.net/viewvc/el4j/trunk/el4j/framework/modules/xml_merge/

Community
  • 1
  • 1
Felixyz
  • 19,053
  • 14
  • 65
  • 60
  • Interesting question. unfortunately I think there is no solution - I'm curious whether someone will come up with a good answer. If not, have a look at http://stackoverflow.com/questions/3929087/dividing-a-project-into-multiple-xcode-project-files/3932613#3932613 :) – w-m Oct 26 '10 at 10:07

5 Answers5

9
  1. Break your projects up into smaller, more logical libraries/packages. Massive projects are regularly the sign of a bad design, like the object that does way too much or is way too large.

  2. Design for easy rebuilding -- this also helps if you're writing programs which must be built by multiple tools or IDEs. Many of my 'projects' can be reconstructed by adding one directory.

  3. Remove extraneous build phases. Example: I've removed the "Copy Headers" build phase from all projects. Explicitly include the specific files via the include directive.

  4. Use xcconfig files wherever possible. This also reduces the number of changes you must make when updating your builds. xcconfig files define a collection of build settings, and support #include. Of course, you then delete the (majority of) user defined settings from each project and target when you define the xcconfig to use.

  5. For target dependencies: create targets which perform logical operations, rather than physical operations. This is usually a shell script target or aggregate target. For example: "build dependencies", "run all unit tests", "build all", "clean all". then you do not have to maintain every dependency change every step of a way - it's like using references.

  6. Define a common "Source Tree" for your code, and a second for 3rd party sources.

  7. There are external build tools available. This may be an option for you (at least, for some of your targets).

At this point, a xcodeproj will be much simpler. It will require fewer changes, and be very easy to reconstruct. You can go much further with these concepts to further reduce the complexity of your projects and builds.

Community
  • 1
  • 1
justin
  • 104,054
  • 14
  • 179
  • 226
  • Great suggestions, although they circumvent rather than solve the problem. 1+6 I am already doing. 4+5 I will consider. 2+7 -- could you provide more information? – Felixyz Nov 01 '10 at 08:26
  • yes, they do simply project files/structures (and circumvent the problem more than solve it). 2) structure your source files, resources, test cases, etc. so that you may easily recreate any target by adding all the contents of a directory into a project (specifically, test cases would either reside in another project or you'd have a second target dedicated to testing which you'd also construct by adding everything from the unit_test dir to the unit_test target). in this way, you'd write and layout source files (etc.) so you'd have the ability to reconstruct any target based on its (cont) – justin Nov 01 '10 at 09:44
  • (cont) dependencies, the (entire) contents of one directory, and an the addition of an xcconfig. if a project is corrupted or must be used in another ide (or version of xcode), the import takes less than 1 minute. this also may help to keep the unused bits out of the main project tree. it also makes it easy to make combined builds. if you're obsessive about declaration correctness wrt what's exported and visibility (which should definitely be a concern if you're working on non-trivial programs), then you can make a combined build in a very short time. (cont) – justin Nov 01 '10 at 09:54
  • 7) there are a few common options such as automake/make, and cmake. combined builds can also help in very large builds (also to reduce compile times). with an external build system or combined builds, the project is unlikely to change as often. in house tools are also great. with in-house tools, the dependence on the xcproject depends on how you've written your tools to operate. with the outlined directory structure, you could write a tool to compile the sources of a specified directory, link and output the object someplace. in that case, you'd have one line to write to build a library. – justin Nov 01 '10 at 10:04
  • Perfect suggestions. Thanks @justin – Manish Jan 22 '21 at 07:12
4

You might want to try https://github.com/simonwagner/mergepbx/

It is a script that will help you to merge Xcode project files correctly. Note that it is still alpha.

Disclaimer: I am the author of mergepbx.

idmean
  • 14,540
  • 9
  • 54
  • 83
Simon
  • 1,521
  • 2
  • 13
  • 20
  • Simon, is this project mature at the moment? – Alex Zavatone Oct 17 '14 at 15:05
  • 2
    Well, it works for me - so yes? There is unfortunately no possibility to make sure that it can really work with everything out there, as there is no documentation about the project file format. So it will never be better than "works for me and nobody has complained so far.". – Simon Dec 21 '14 at 18:07
  • Simon - After spending years in development and QA, hearing "well, it works for me", that scares me. Maybe it's all we've got, but still. – Alex Zavatone Dec 31 '14 at 15:24
  • 1
    Well, without documentation, there is nothing I can do :/. On the otherhand, merging by hand has the same risk (as you also won't have any idea how the project file works). So yes, it is unfortunately the best we can get.If you want to help you can take a look at https://github.com/simonwagner/mergepbx/tree/master/test . It contains the test cases for the basic merging functions and some fixtures for testing the parsing and merging code. – Simon Jan 04 '15 at 22:45
  • Used this without any problems for more than 2 years. Thanks for that ... Unfortunately it seems to start causing corrupt files as of XCode 9.2. Will report to your repository! – Christoph May 31 '18 at 12:37
2

To compare two Xcode projects open open FileMerge (open xcode and select Xcode (from the manu pane) --> Open developer tools --> FileMerge). now click "left" button and open xcode project main directory. click "right" button and open xcode project main directory to compare.

Now click "merge" button!

Thats it!

evya
  • 3,381
  • 1
  • 25
  • 28
  • 1
    Easiest, if you're using git: `git config --global merge.tool opendiff` (only needs to be done once), then `git mergetool` will launch it for you. – damian May 03 '13 at 16:50
  • 1
    I'm unclear that FileMerge has special support for Xcode project files in particular? – Benjohn Dec 02 '15 at 10:35
2

The best way I have found is to instruct Git to treat the .pbxproj file as a binary. This prevents messy merges.

Add this to your .gitatributes file:

*.pbxproj -crlf -diff -merge
radven
  • 2,296
  • 1
  • 22
  • 39
  • 1
    What difference does this make to the physical merge? – esbenr Sep 17 '12 at 11:52
  • 6
    If this makes the file effectively binary, how does that make the merge any easier? – damian May 03 '13 at 16:48
  • 1
    please check these out: http://robots.thoughtbot.com/xcode-and-git-bridging-the-gap ---- Quote: Because of the custom format used in this type of file, this is exactly what we want. When a merge conflict arises for this file, git will automatically combine the changes from both sides of the conflict, applying the upstream changes first. – chakming Jul 26 '14 at 15:49
0

Another option to consider which may help to reduce the number of times you experience the problem. To explain, I'll call the branch that team members' branches come from the "develop" branch. Have a convention in your team that when the project file is modified, the changes (along with any other changes required to ensure the build integrity) are committed in a separate commit. That commit is then cherry picked onto the develop branch. Other team members who plan to modify the project file in their branch can then either cherry pick into their branch or rebase their branch on the latest develop. This approach requires communication across the team and some discipline. As I said, it won't always be possible; on some projects it might help a lot and on some projects it might not.

Martin Lockett
  • 2,275
  • 27
  • 31