Giter VIP home page Giter VIP logo

mergepbx's Introduction

mergepbx

A tool for merging Xcode project files in git

Version: 0.6 - 2nd Oct 2014 Status: Alpha

Buy me a cup of tea: Donate to mergepbx

Why mergepbx?

Tracking a Xcode project in a version control system is annoying. Simply adding files can lead to merge conflicts that have to be solved manually, although it would be possible to resolve the conflict automatically, if the merge algorithm would be aware of the structure of Xcode's project file.

After long and annoying merge sessions in one of my projects, I came to the conclusion, that writing a merge driver for git which understands the structure of the project file would be a worthwhile endeavour, as it would save me from solving the merge conflicts for my co-workers.

Unfortunately, that script was finished only after the project ended. However, as I didn't want to let the work go to waste, this script is now published as open source under the GNU GPL 3.

Status

This script needs knowledge about the structure of Xcode's project. However, there doesn't seem to be any documentation (and I would be surprised if there were any). Luckily, the format of the project file is a plain text Plist, so reverse engineering the structure is rather easy.

Nevertheless, I do not know all possible variants of project files that are out there. Currently, this script works for the projects I worked on, however, you might encounter a project file that has some structures in it that I haven't seen yet.

If the script doesn't work, you might want to open an issue and attach your project file to it.

Note also, that this script can't solve conflicts, that are really conflicts. For example, if you rename a file and a co-worker of yours is going to delete it, well, then you are going to end up in a pretty weird state.

Usage

To use this script, you have to configure it as a merge driver for you project file. To do this, you have to take the following steps:

Building

Execute the following command in the directory of the cloned project:

./build.py

That should build the mergepbx executable that you can use. It is a specially crafted zip file that contains all needed python files and can directly be executed on the commandline

Using mergepbx as merge tool

You can add mergepbx as a merge tool, so you can use it to manually start merging the project file with git mergetool --tool=mergepbx PROJECT.pbxproj.

Add mergepbx as a merge tool

Open ~/.gitconfig (create if it does not exist) and add the following lines to it:

#driver for merging Xcode project files
[mergetool "mergepbx"]
	cmd = mergepbx "$BASE" "$LOCAL" "$REMOTE" -o "$MERGED"

Merging project files

After you have encountered a failed automatic merge, you can now use the following command to start the automatic merge with mergepbx:

git mergetool --tool=mergepbx PROJECT.pbxproj

Afterwards, the project file should be merged and marked as resolved.

Using mergepbx as a merge driver

You can also configure git to always use mergepbx automatically, when it encounters a conflict in a project file

Open ~/.gitconfig (create if it does not exist) and add the following lines to it:

#driver for merging Xcode project files
[merge "mergepbx"]
        name = Xcode project files merger
        driver = mergepbx %O %A %B

Replace mergepbx with the path to the file you downloaded (You might want to add that file to your $PATH)

Configure your repository to use the driver

In your repository root directory, open the file .gitattributes (create if it does not exist). Add the following lines to it:

*.pbxproj merge=mergepbx

Merging project files

If you merge branches with git now, git will automatically use mergepbx for .pbxproj files. You don't have to do anything special, simply merge your branches as before.

Note that this script is not really fast, I didn't optimize it for speed and especially the plist parser is not very fast.

Alternatives

An alternative to using this script, is to use the union merge driver of git, by adding the following line to .gitattributes:

*.pbxproj merge=union

This tells git to combine the files by adding lines from both, the remote file and your local file. That works most of the time, however it is not bulletproof, as git still has no idea what it is doing here. If my script does not work for you, you can however try out this strategy.

How to help

If you encounter a project file that can not be parsed, please open an issue and attach the project file to it. I will then take a look at it and add the missing parts to the script

Disclaimer

This code published here and any programs that are created from it are not claimed to be fit for any purpose. Running them might lead to your project being eliminated, kittens killed and the end of the world.

Be careful, you have been warned!

Contributers

  • Simon Wagner

mergepbx's People

Contributors

ahti avatar bitdeli-chef avatar esttorhe avatar kaneshin avatar ncalexan avatar simonwagner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mergepbx's Issues

Unknown merge tool after installing with brew

Hi

I've installed mergepbx via brew brew install mergepbx and tried to use it to merge a .pbxproj file with git mergetool --tool=mergepbx something.xcodeproj/project.pbxproj but git gives the output

Merging:
something.xcodeproj/project.pbxproj

Normal merge conflict for 'something.xcodeproj/project.pbxproj':
  {local}: modified file
  {remote}: modified file
Unknown merge tool mergepbx

However running mergepbx barewords gives the expected mergepbx: error: too few arguments along with the usage: message. which mergepbx reveals it is located in /usr/local/bin/mergepbx but using the entire path for --tool= still gives the unknown merge tool.

Adding the lines from the README to .gitattributes and .gitconfig did not change this

How do I proceed? I would have hoped brew would have informed me if there was a caveat to installing using homebrew...

about cocoaPods

Hi,It's a cool tool!,Thanks a lot.
I read your blog, and I wan't to use a .gitattributes file to solve the problem, but I'm worried about that if I use cocoaPods to add lib . Is there any issue in my project ?

merging failed: can not merge projects with objectVersion 50

Hello !

First of all, thank you very much for creating and contributing to MergePbx. It saves me so much troubles when having xcodeproj conflicts !

Now, the issue ; as said in the title i got an error when trying to resolve conflicts in my xcodeproj.
I'm using Xcode 10.1 and xcodeproj has been created with this version of the IDE.

I think this is not a problem with the content of my Xcodeproj itself, as you can see on the image below. It is a simple conflict (that i succeed to resolve !).
image

Do you think that supporting version 50 is possible ?

Merges by just removing files

Hi,

I have mergepbx setup as a merge driver (reference in .gitconfig and .gitattributes) but whenever I merge two branches all it seems to do is remove references to files from the project that would result in a merge conflict leaving me to add them back by hand. That can't be the intended usage, right?

Thanks
Jan

Merge fails on "currentVersion"

I have a project which had a new data model created on both branches. When we try to merge using the tool, it fails on the XCVersionGroupMerger3. Specifically the isa, "XCVersionGroup," with "currentVersion" and "children" conflicting.
mytraps_fixreleaes_ vim_mytraps_xcodeproj_project_pbxproj vim_mytraps_xcodeproj_project_pbxproj solarized_dark_ansi _259x60
screen_shot_2015-12-08_at_10_28_51_pm

Mergepbx doesn't work on macOS 12.3

Apple has dropped support for python2 on macOS 12.3 and it seems that mergepbx doesn't work anymore. Is it possible to upgrade the tool so it runs with python3?

Screenshot 2022-03-23 at 3 22 41 PM

I know this project is probably abandoned but I though it might worth a shot. Thanks in advance!

Merging fails

I've just upgraded to Xcode 6 and when attempting to rebase mergepbx fails with this error:

Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/Users/apple/bin/mergepbx/mergepbx.py", line 67, in main
  File "/Users/apple/bin/mergepbx/plist/antlr/runtime/antlr3/exceptions.py", line 317, in __str__
  File "/Users/apple/bin/mergepbx/plist/antlr/runtime/antlr3/exceptions.py", line 184, in getUnexpectedType
AttributeError: 'NoneType' object has no attribute 'type'

I'm not certain that Xcode 6 is the problem, but it's the only thing I can think of that has changed.

Thanks for making such a useful tool. I'm lost without it!

mergepbx cannot handle paths with whitespace

The path to my project.pbxproj file contains whitespace:

Foo Project.xcodeproj/project.pbxproj

I cannot get mergepbx to work with this. My first attemt was this:

$ grep bin/mergepbx ~/.gitconfig
cmd = /usr/local/bin/mergepbx -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE"

$ git mergetool --tool=mergepbx
Merging:
Foo Project.xcodeproj/project.pbxproj
[..]
usage: mergepbx [-h] [-o OUTPUT] [-d] [--dump DUMP] [--clean] [--no-clean]
                base mine theirs
mergepbx: error: unrecognized arguments: ./Foo Project.xcodeproj/project_LOCAL_42551.pbxproj ./Foo Project.xcodeproj/project_REMOTE_42551.pbxproj

The errormessage makes me assume that "./Foo" gets assigned to output, " Project.xcodeproj/project.pbxproj" to base, "./Foo" to mine and "Project.xcodeproj/project_BASE_42551.pbxproj" to theirs, as if the spaces are incorrectly treated as argument separators.

The same .gitconfig line works perfectly fine for p4merge or kdiff3. I also tried various combinations of escaping and extra quotes, but all of the following give the exact same result:

cmd = /usr/local/bin/mergepbx -o \"$MERGED\" \"$BASE\" \"$LOCAL\" \"$REMOTE\"
cmd = /usr/local/bin/mergepbx -o "\"$MERGED\"" "\"$BASE\"" "\"$LOCAL\"" "\"$REMOTE\""
cmd = /usr/local/bin/mergepbx -o \\\"$MERGED\\\" \\\"$BASE\\\" \\\"$LOCAL\\\" \\\"$REMOTE\\\"
cmd = /usr/local/bin/mergepbx -o "\\\"$MERGED\\\"" "\\\"$BASE\\\"" "\\\"$LOCAL\\\"" "\\\"$REMOTE\\\""

mergepbx crash on currentVersion conflict

It seems I'm running into a crash with the latest version of mergepbx. My Xcode project is from the latest 8.3.1.

Traceback (most recent call last):
  File "<string>", line 5, in <module>
  File "/Users/jacob/Downloads/mergepbx-master/mergepbx/mergepbx.py", line 78, in main
    merge_pbx_files(args.base, args.mine, args.theirs, output, clean=args.clean)
  File "/Users/jacob/Downloads/mergepbx-master/mergepbx/mergepbx.py", line 102, in merge_pbx_files
    merged_project = merge_pbxs(base, mine, theirs)
  File "/Users/jacob/Downloads/mergepbx-master/mergepbx/pbxproj/merge/__init__.py", line 8, in merge_pbxs
    return merger.merge(base, mine, theirs)
  File "/Users/jacob/Downloads/mergepbx-master/mergepbx/pbxproj/merge/pbxmerge.py", line 146, in merge
    self.merge_objects(result, base, mine, theirs)
  File "/Users/jacob/Downloads/mergepbx-master/mergepbx/pbxproj/merge/pbxmerge.py", line 204, in merge_objects
    merged_obj = merger.merge(base_obj, mine_obj, theirs_obj)
  File "/Users/jacob/Downloads/mergepbx-master/mergepbx/pbxproj/merge/pbxmerge.py", line 72, in merge
    result = self.handle_conflicts(base, mine, theirs, diff3)
  File "/Users/jacob/Downloads/mergepbx-master/mergepbx/pbxproj/merge/pbxmerge.py", line 93, in handle_conflicts
    raise MergeConflictException("conflict while merging with %s merger" % self.__class__.__name__)
MergeConflictException: conflict while merging with XCVersionGroupMerger3 merger

I'm not sure what key or section of my project it's getting held up on as there's no logging for that sort of thing. Do you have any suggestions on how to go about debugging this?

mergepbx is not work in my japanese environment

I made a simple project for checking.
I added a new file in the branch 'test1', and added a new file in the branch 'test2'.
Then I tried to merge 'test1' and 'test2', but I was warned this errors.

$ git checkout test1
Switched to branch 'test1'

$ git merge test2
merging failed: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
Auto-merging DummyProjectForMergepbx.xcodeproj/project.pbxproj
CONFLICT (content): Merge conflict in DummyProjectForMergepbx.xcodeproj/project.pbxproj
Automatic merge failed; fix conflicts and then commit the result.

This project include that branches is here -> https://github.com/tokorom/DummyProjectForMergepbx

and my LANG environment variable is ja_JP.UTF-8.

$ echo $LANG
ja_JP.UTF-8

merge same file_reference

Hi @simonwagner,
first of all great repo, I was wondering how mergepbx handle the cases such as: my colleague added file a.swift to a group, at the same time I also added a.swift to the same group, when we merge our stuff, we will get merge conflict, same file_reference but different uuid, currently what I am seeing when I use mergepbx as merge tool is the merge conflict was resolved but in the group there are two a.swift file. I though mergepbx would only choose one of the file_reference from merge conflict.
thanks!

merging failed: can not merge projects with objectVersion 47

When the pbxproj has objectVersion = 47, this merge tool does not work :(

It returns with this message:
merging failed: can not merge projects with objectVersion 47 PROJECT.xcodeproj/project.pbxproj seems unchanged. Was the merge successful? [y/n]

merging failed: strategy not found: PBXHeadersBuildPhaseMerger3

I'm seeing consistent merge failures with Mozilla's Firefox for iOS Swift project at https://github.com/mozilla/firefox-ios. The error log (snippet) is below.

Merge failure would not be a huge deal except that my configuration doesn't fall back to manual; it obliterates the change entirely. (I think this is an issue with my configuration, not necessarily with mergebpx.)

A quick skim of the code suggests that the project section corresponding to the Swift "bridging header" needs to be explicitly handled, somehow, in mergepbx. I will try to figure out what needs to be done but would appreciate direction.

Applying: Bug 1141843 - Final: project changes for Sync working branch.
Using index info to reconstruct a base tree...
M   Client.xcodeproj/project.pbxproj
Falling back to patching base and 3-way merge...
merging failed: strategy not found: PBXHeadersBuildPhaseMerger3
Auto-merging Client.xcodeproj/project.pbxproj
CONFLICT (content): Merge conflict in Client.xcodeproj/project.pbxproj
Failed to merge in the changes.
Patch failed at 0014 Bug 1141843 - Final: project changes for Sync working branch.
The copy of the patch that failed is found in:
   /Users/nalexander/Mozilla/firefox-ios/.git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

Crash on project files with source name of (null)

I encountered an unmergeable project file. For some reason XCode created a few lines in the project file that looked like:

9F7A68181A24D72800A23C41 /* (null) in Sources */ = {isa = PBXBuildFile; };

Removing lines like that from the project file caused mergepbx to work perfectly again! I have no idea at all why it would be doing that, but it happened when I added a file into my project. I am using Xcode 6.1.1.

I can send you the project file dumps but I'd prefer to do this via email rather than through Github if that's ok.

Thanks again for the brilliant project!

ANTLR merge problem

I have Python 2.7.8 installed from MacPorts and ANTLR 3.1.3 from the antlr website. I get the following error when merging.

Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/Users/kasper/mergepbx/mergepbx.py", line 67, in main
  File "/Users/kasper/mergepbx/plist/antlr/runtime/antlr3/exceptions.py", line 317, in __str__
  File "/Users/kasper/mergepbx/plist/antlr/runtime/antlr3/exceptions.py", line 184, in getUnexpectedType
AttributeError: 'NoneType' object has no attribute 'type'

I can't share my project files in public.

Merge Conflicts in Branches are not made visible

Whenever I have a valid Merge Conflict, e.g.

Branch A is setting the Deployment Target to 8.0
Branch B is setting the Deployment Target to 7.0

I am supposed to have a merge conflict since both branches modified the same value.

I am correctly shown a merge conflict when Rebasing Changes from Branch B onto A.
But I am not seeing the conflict in the project file. I would have expected to see something like:

<<<
Deployment Target 7.0
'===
Deployment Target 8.0

in the project file.

But it seems pbxmerge just used the value from the Branch that was merged upon.

Building produces unusable script

When I build a file via build.py the output file is not usable:

  1. It has an empty line at the beginning, making the hashbang not recognized. This is easily fixed by hand, BUT:
  2. Running the fixed file results in the following:
> ./mergepbx 
Traceback (most recent call last):
  File "<stdin>", line 5, in <module>
ImportError: No module named mergepbx

The same problems apply to the prebuilt variant mentioned in the readme.

I'm running python 2.7.3 on OSX 10.8.

No module named antlr3.streams

I have used mergepbx with good results. Recently I updated to the latest version and have started getting errors like the above

merging failed: No module named antlr3.streams

Do I miss something in my Python installation?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.