85

There are two members in our team. We use Xcode's SCM (use SVN) to manger our source code files.
We all add files to our Xcode project. He has committed to SVN server. When I update, Xcode find there has conflicts in project.pbxproj file. Then I select quit Xcode and manually merge the conflicts. Then I start to edit my project.pbxproj, merge our changes. Actually I don't know how Xcode manage files, I just add some text that my project.pbxproj file did't have. When I finish, my project can't open. I guess that because the project.pbxproj file can't be edit by manual.

So, I want to know, when you find this problem, the project.pbxproj file have conflicts, how to solve it?

Thank you!

Forge
  • 6,538
  • 6
  • 44
  • 64
vcLwei
  • 1,927
  • 3
  • 16
  • 13

13 Answers13

159

I use git but we see the same issue - if two people add files there's a merge conflict.

Usually the editing is very easy though. Simply go into the project.pbxproj file with a text editor, and look for the merge conflict section - usually this is marked by something like :

>>>>>>>
Stuff 1
======
Stuff 2
<<<<<<<<

In 99% of Xcode project merge conflict cases, you simply want to accept both sides of the merge (because two people added different files) - so you would simply delete the merge markers, in the above case that would end up like:

Stuff 1
Stuff 2

Like I said, this works great in MOST cases. If Xcode will not read the project file when you are done, just take the most recent un-merged version and manually add your files again.

FOLLOWUP 2023

This advice still mostly holds, but in recent times I've been working on a very large and old application with a complex Xcode project file and several team members often working on large additions.

Manually examining merge conflicts is still the primary approach. Multiple people adding new files is often still just as easy as using both sides of a merge conflict.

There is still also always the fallback of simply taking in a project file you are attempting to merge into your branch, and using a copy of the Xcode project with conflicts to manually add back in your changes.

There are a few cases in particular though that I have found can present challenges, on scenario which has an extremely non-obvious solution...

The first is that sometimes, multiple people working on a file with the same name may result in multiple entires of the file with different identifiers. For this issue, look for file IDs within the group the file will be contained in, and pick which file ID to preserve, and which to discard.

The second is that introducing new groups in similar locations in your project might result in a conflict splitting up a group. In these cases you may need to take the contents of one side of the merge totally out of the merge conflict region, and introduce it correctly alongside other groups in the project file.

The last is the non-obvious solution that prompted me to update this answer. That is that sometimes, you may get a conflict where entries for all of your CoreData versions would have totally different identifiers. This might happen for example if two teams had bumped up the model version at the same time.

In that case it would seem that you can take one side or the other, using only those identifiers. This sometimes works.

However in some cases if I did that, on loading the project I would see no model versions at all - Xcode deleted them all.

The solution was again, to leave in BOTH sides of the merge which meant two entries for core data models! What happens if you do this is Xcode on loading the project, will choose valid identifiers for all of the models and save one correct version instead of allowing both to live.

For a large team using CoreData with multiple ongoing version bumps at once, one technique we found helped smooth thing over was to have a separate branch with CoreData model changes over. That way all teams would be using the same CoreData version with the same current model identifier, and internal Xcode project IDs ASAP. This branch only held the CoreData models themselves, not any classes related to the models (though it could).

Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150
  • 1
    Another answer to a very similar question arguing for treating the pbxproj file as a binary file: http://stackoverflow.com/questions/1549578/git-and-pbxproj/1549590#1549590 – Josh Metcalfe Nov 02 '11 at 19:27
  • 5
    They are dead wrong. Why should ANY textual format be more difficult for an automated system to merge than code itself? It makes no sense. I have been working with other people on XCode projects daily for many years now, every time applying the merge strategy above (though these days I just tell a merge tool to accept both sides of any conflict). This approach works just fine. Now storyboards, there I need to experiment more before I would claim that works. – Kendall Helmstetter Gelner Nov 02 '11 at 19:39
  • 2
    This wouldn't work at least for xcode 5. Seems it uses some magic numbers and regenerates them for all resources when something is added to the project. When a conflict occurs, you should remove both conflicting resources, add them manually so xcode can generate those magic numbers again. – Morteza Milani Jan 15 '14 at 18:16
  • I have not seen that at all, in a recent project when adding new resources only the new resources get new numbers (identifiers). My advices still remains the same after many months of working in XCode 5 on projects shared by other people. – Kendall Helmstetter Gelner Jan 15 '14 at 20:18
  • This solution works for Xcode 8 Version 8.0 (8A218a) – JLONG Oct 21 '16 at 05:19
  • It is NOT reasonable to deal with a file with thousands of lines and searching for conflicts everyday. Apple must solve this issue. – Milad Faridnia Mar 07 '19 at 09:09
  • Is this still an issue as of 2022? How are large teams handling this? – cumanzor Aug 05 '22 at 05:25
  • 1
    @cumanzor I thought I'd follow up on this as I am currently working on a very large, very old application with a complex Xcode project file, and several other team members. There is enough information learned from this that I'll append to the answer as I have come across tricky cases; but the basic summary is, manual checking and resolution of mere conflicts is still the best approach even with Xcode 14 in 2023. – Kendall Helmstetter Gelner Feb 26 '23 at 04:35
31

Unfortunately, there's not much you can do except to make the changes manually in one check out and then check-in the newly "merged" project.

Barry Wark
  • 107,306
  • 24
  • 181
  • 206
  • 1
    After spending an hour time to find a magical solution. This seems the only acceptable answer to me. – Kiran Ruth R Sep 11 '14 at 07:04
  • 1 alternative solution: Resolve by using "their" changes. Try to run it. And if there are errors about missing stuff it will be your missing stuff, for which you know where it should go. – iOS Blacksmith Jan 19 '21 at 15:49
21

This solution is only for git, but you can add a .gitattributes file to your project then within that file add the following line:

*.pbxproj merge=union

This will tell git to keep both sides of the merge which will be what you want the vast majority of the time.

mmilleruva
  • 2,110
  • 18
  • 20
13

To manually solve the merge conflicts, check the UUID of each conflicting item.

Example:

<<<<<<< HEAD
    6B01C4B72008E70000A19171 /* ExistingFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B01C4B62008E70000A19171 /* ExistingFile.swift */; };
    3F01C4B72008E70000889299 /* NewFileA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F01C4B72008E70000889299 /* NewFileA.swift */; };
=======
    6B01C4B72008E70000A19171 /* ExistingFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B01C4B62008E70000A19171 /* ExistingFile.swift */; };
    4DF01C4B72008E70000882ED /* NewFileB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF01C4B72008E70000882ED /* NewFileB.swift */; };
>>>>>>> branch_to_merge

Check each UUID:

  • If it occurs in both versions, remove it in one version: ExistingFile.swift
  • If it does not occur on the comparing branch, keep it: NewFileA.swift and NewFileB.swift
  • If it is not referenced anywhere else in the file, i.e. you can only find one occurrence in the whole project.pbxproj file, I would assume it is an artefact and safe to delete it.

The result would be:

    6B01C4B72008E70000A19171 /* ExistingFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B01C4B62008E70000A19171 /* ExistingFile.swift */; };
    3F01C4B72008E70000889299 /* NewFileA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F01C4B72008E70000889299 /* NewFileA.swift */; };
    4DF01C4B72008E70000882ED /* NewFileB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DF01C4B72008E70000882ED /* NewFileB.swift */; };

Note: I don't recommend adding *.pbxproj merge=union to the .gitattribues file to basically ignore merge conflicts because a conflicting merge should alway be checked manually unless there is a sophisticated script doing that for you.

Manuel
  • 14,274
  • 6
  • 57
  • 130
  • 1
    Question has been removed by the author. I think it’s highly unlikely that an UUID occurs twice. Refer to the *Unique* in UUID. – Manuel Sep 25 '18 at 10:50
3

I was looking for a straightforward solution to this problem when I came across this other question/answer:

https://stackoverflow.com/a/14180388/307217

I was completely blown away by how simple this solution is, I was trying to merge in a disparate feature branch which was almost 200 revisions behind the trunk, XCode and Mercurial were not being happy campers about it. I tried manually merging the pbxproj file (which had over 100 conflicts) 8 times before trying this solution.

Basically the solution is as such (assuming you use Mercurial, because it's awesome):

  1. Attempt your merge in mercurial:

    hg update FEATURE_BRANCH
    hg merge default
    *mercurial gives you a ton of crap about the pbxproj file having merge conflicts*
    
  2. Open Xcode

  3. From the top toolbar, select Xcode->Open Developer Tool->FileMerge
  4. On the left, open your conflicted 'project.pbxproj' file (the one with merge conflict markup in it)
  5. On the right side, open your 'project.pbxproj.orig'
  6. Select File->Save Merge and save over the 'project.pbxproj' file
  7. Then back at the command line:

    hg resolve -m ProjectName.xcodeproj/project.pbxproj
    *merge any other broken files*
    hg commit -m "manually merged with trunk"
    
  8. Eat Cake Because You Are Done
Community
  • 1
  • 1
G. Shearer
  • 2,175
  • 17
  • 19
  • 1
    Turns out Xcode 5 FileMerge crashes on almost everything. Great job shipping it out Apple… – Engin Kurutepe Oct 22 '13 at 14:43
  • 1
    it sucks, but in all honesty Apple doesn't generally ship very many bugs in comparison to Microsoft. At least the couple that they ship only affect a small percentage of their users (i.e. programmers), and we know how to google other merge tools – G. Shearer Oct 30 '13 at 16:16
  • While I use git, using FileMerge helped me too. – Josh Paradroid Sep 27 '22 at 14:16
3

So far the best visual merge tool I have used for pbx files is Visual Studio Code's merge tool. I open the pbx file in Code app and fix conflicts then open XCode again.

Ali Ersöz
  • 15,860
  • 11
  • 50
  • 64
2

Sometimes one or few files could be recreated (for example ManagedObjects) in different branches, so when you'll merge there may be two declarations for one file in one block. In this case you should delete one of the declarations.

Forge
  • 6,538
  • 6
  • 44
  • 64
2

As stated above the most common way of handling the conflicts is to

  1. accept "everything"
  2. re-import the files into the project

I Wrote a bash-script that takes care of (1) above.

Note that this will only solve the most common case of merge conflicts!

#!/bin/bash
#
#
#
if [ $# -eq 0 ]
 then
    echo "File must be provided as argument, darnit!"
    exit 1
fi

if [ $# -eq 2 ]
 then
    echo "only ONE File must be provided as argument, darnit!"
    exit 1
fi


echo "Will remove lines from file:" $1
grep -v "<<<<<" $1  | grep -v ">>>>>>" | grep -v "====" > out.tmp;mv out.tmp $1
echo "Done removing lines from file:" $1
tommys
  • 865
  • 1
  • 11
  • 21
1

I happened to encounter this tricky problem.

Instead of manually dealing with these conflicts, you can try this.
Suppose you are on feature branch.

  1. Git checkout master.
  2. Copy content in project.pbxproj
  3. Git checkout to your feature branch, and paste it.(Override the current content in project.pbxproj)
  4. Run

    react-native link
    
zx485
  • 28,498
  • 28
  • 50
  • 59
magentaqin
  • 1,949
  • 13
  • 10
  • 1
    First of all, that only seems to apply when you use RN, secondly, you'd override all the file linkings that are new in your feature branch. Makes no sense. – David Seek Oct 13 '21 at 21:54
0

I founded a tool "xUnique" https://github.com/truebit/xUnique, it works!

lighter
  • 11
  • 1
  • 5
    Note that [link-only answers](http://meta.stackoverflow.com/tags/link-only-answers/info) are discouraged, SO answers should be the end-point of a search for a solution (vs. yet another stopover of references, which tend to get stale over time). Please consider adding a stand-alone synopsis here, keeping the link as a reference. – kleopatra Jan 26 '16 at 08:42
  • Can you provide more details regarding how this tool can solve described problem? – Piotr Wittchen Mar 18 '22 at 13:55
0

You can open it on VSCODE and fix the conflicting merge there. look for some colored annotations on the IDE or look for <<< >>> in the text search.

0

I know that 90 percent of conflicts are clear and you can accept both changes in conflicts so you do not need to be worry you will resolve it if you will be patient the way I found that use tools like xUnique that will help you a lot

jamal zare
  • 1,037
  • 12
  • 13
-26

The best thing to do might be to simply accept either your version or his version in its entirety, without trying to combine the two. Also, consider whether the file in question is something that should be in the repository at all; it may be more appropriate to let each person have their own version of it.

Check out the documentation on how to resolve conflicts.

Michael Hackner
  • 8,605
  • 2
  • 27
  • 29
  • This. The .pbxproj files are fairly simple (if verbose) files, and the usual merging technique generally works just fine, as long as you're patient. – Stephen Canon Jan 05 '10 at 14:20
  • 14
    `project.pbxproj` is an important file to put in your repository, since it tells Xcode how to build the project. Not checking it in is equivalent to not checking in `Makefile`. – Steve Madsen Aug 02 '10 at 21:10
  • 4
    This answer is dangerously incorrect. Do not just accept one or the other or your project will be missing files. And yes, it should be in the repository, otherwise everyone will be building the project differently with varying results. – DougW Aug 18 '11 at 21:51
  • agree with DougW - following this answer will lead to pain and difficult bugs. – sujal May 15 '12 at 19:01
  • this answer cannot be improved – djskinner Aug 13 '12 at 21:46