I have been an iphone developer for a while, and I have recently been including git in my workflow. I have used git settings found on http://shanesbrain.net/2008/7/9/using-xcode-with-git for my workflow so far.
Those settings tell git to exclude *.pbxproj from merges? Is there a real reason for doing this? For example, when I add a file to the project and push to origin, my fellow developers will not have that file added to their xcode project when they pull. Then if one of them builds a release this file may not be included. Shouldn't I just let git handle the merges for the project file? Why or why not this file should be in merges and how to properly handle the situation when files are added to the project?
I have worked on iPhone applications full time since the SDK launch, most of that time spent working on teams with multiple developers.
The truth is that it's way more harmful to disallow merging of that .pbxproj file than it is helpful. As you say, when you add a file unless other people get that file, they have to also add it to their project - in an application of any size, that sucks and it also takes away a huge benefit of source code control in that you cannot really revert to a complete earlier project state just through git.
The .pbxproj file is simply a property list (similar to XML). From experience, just about the ONLY merge conflict you were ever get is if two people have added files at the same time. The solution in 99% of the merge conflict cases is to keep both sides of the merge, which for git at least simply involves removing any >>>>, <<<<, and ==== lines. In fact this is so common that I have created a simple shell script to fix a .pbxproj file in a merge state from git, I run this from within the project directory (at the Classes level):
#!/bin/sh
projectfile=`find -d . -name 'project.pbxproj'`
projectdir=`echo *.xcodeproj`
projectfile="${projectdir}/project.pbxproj"
tempfile="${projectdir}/project.pbxproj.out"
savefile="${projectdir}/project.pbxproj.mergesave"
cat $projectfile | grep -v "<<<<<<< HEAD" | grep -v "=======" | grep -v "^>>>>>>> " > $tempfile
cp $projectfile $savefile
mv $tempfile $projectfile
Worst case if it fails (you ask XCode to load the project and it fails to load), you simply delete the .pbxproj file, check out the master from git, and re-add your files. But I've never had that happen in many months of use with this script, again working full time on iPhone applications with several other developers.
Another option (pointed out in comments below) that you can try using in place of the script, is to add this line to a .gitattributes file:
*.pbxproj text -crlf -diff -merge=union
Then git will always take both sides of a merge for the .pbxproject files, having the same effect as the script I provided only without any extra work.
Lastly, here is my complete .gitignore file, showing what I do have it set to ignore as there are a few things you don't want - in my case really just emacs remnants and the whole build directory:
# xcode noise
build/*
*.pbxuser
*.mode1v3
*~
# old skool
.svn
# osx noise
.DS_Store
profile
This works for me in Xcode 4.6 and Git 1.7.5.
Add and commit .gitattributes file with this:
*.pbxproj binary merge=union
I've tested this with another team member and works great.
Taken from:
http://robots.thoughtbot.com/post/33796217972/xcode-and-git-bridging-the-gap
Frankly, the existing answers are misleading.
If you never delete or rename files, then using the merge=union strategy, which just combines the differences in different commits directly, is a good idea.
However, in the real world, we do need to delete or rename files sometimes. Merging the differences without any modification would make a lot of problems under these situations, and these problems usually lead to the "Workspace Integrity - Couldn't load project" issue, which makes you even not able to run the project.
The best solution I got so far:
1) Design the project well and add all the needed files at the beginning, so you would seldom need to change the project.pbxproj.
2) Make your features tiny. Don't do too many things in a branch.
3) For any reason, if you need to modify the file structure and get conflicts in project.pbxproj, use your favorite text editor to solve them manually. As you make your tasks tiny, the conflicts might be easy to solve.
The short answer is that even if you don't include that line in .gitattributes, you may not be able to easily merge two modified versions of a .pbxproj. It's better for git to treat it as a binary.
See here for details: Git and pbxproj
Update: Even though the git book still agrees with this answer, I no longer do. I version control my .pbxproj just like any other non-binary source file.
I did create a Python script that can handle merge conflicts in XCode Project files.
If you want to try it, you can check it out here: https://github.com/simonwagner/mergepbx
You will have to install it as a merge driver, so it gets called automatically when you have a merge conflict in your project file (the README.md will tell you how to do that).
It should work much better than using merge=union as mergepbx understands the semantics of your project file and therefore will resolve the conflict correctly.
However the project is still alpha, don't expect it to understand every project file that is out there.
Related
I've pushed code on local server manually. Thereafter taken checkout of project using CornerStone.
However, the project contains few file with different versioning states i.e A, M and A+.
But project in CornerStone dosen't shows any of these versioning states.
I tried to fix it by committing files (showed commit success) but it remained same.
I'm worried since this will create confusion at later stage.
How to fix this?
Although I already read similar comments here, in this forum, I haven't found an approach that may be suitable for teamwork in a seamless way.
If you know what I mean, you already may found tricky working with git and the project.pbxproj file in Xcode, even when you are working in a different file.
Say,
A developer: created Foo folder, adding foo.swift to the project.
B developer: created Bar folder, adding bar.swift to the project.
Different paths... but you know, conflict! And as you may also noticed, leaving project.pbxproj out is not an option.
So my question is: How do you handle this in a professional manner, Git flow ready and easiest way.
Thank you all very much.
PS: I'm using currently Bitbucket and SourceTree if matters.
PS2: I'd like to avoid command line and manually file editing if possible.
Create a .gitattributes file and adding the following line:
*.pbxproj merge=union
Merges will happen automatically and without you having to touch anything.
Alternatively, you might try mergepbx, which does a more intelligent merge.
New files are created by only one developer on "main-develop" branch.
Push new files to "main-develop"
Those files are implemented by other developers after pull
I'm one of the maintainers of Kintsugi, a tool that intelligently merges the conflicts and promises to automatically solve 99.9% of the conflicts that occur in project.pbxproj files.
The readme also contains instructions on how to set it up as Git merge driver, so it will be applied automatically whenever a conflict in a *.pbxproj file occurs. I don't know of a way to do that from Sourcetree, but for most conflicts after setup you won't have to touch the command line again.
Xcode deleted my project and everything is gone. The only thing that I have is the app in my iPhone 6. So is there any way that I can retrieve the Xcode project of the app?
.. Update ..
i found all the files now i just need to reassemble them in a new project . but I don't know how .
Let's be clear: Xcode did not delete your project, you did, perhaps inadvertently. This does happen to most of us.
The answer is to recover from your remote Git repository or recover from Time Machine or another backup. If you do not have any backup this is your first warning that you need a backup strategy. Make this your last such warning by immediately, as in right now, creating a backup scheme, preferably two. Little is more important.
There are free remote Git repositories such as BitBucket. Setting up Time Machine is simple, just get an external disk, connect it and you will be prompted. Or use another backup scheme such as BackBlaze.
Without a backup you can recover the assets but not code from the ipa from your phone. If you are using the Asset Catalog that is not easy but can still be done.
Unfortunately,
There is no current way to un-archive an app. You must have the .xcodeproj file in order to make changes. The .ipa is useless in terms of editing or changing your app. And if there was a way to do so, it could and would be abused and many clones/copy's/fakes of popular apps will be published. The only accessible files are things in the Main Bundle which only include, .pngs, .jpg, .txt etc but no source code.
Background: git -- or any other SCM -- can "successfully" merge Storyboards, xib's, and pbxproj files as at their core they are just xml. Sometimes there are conflicts which can be resolved by the usual conflict resolution strategies. But xib's and Storyboards are serialized formats of some pretty complex data structures, so the fun begins.
Just as with other source code, a successful merge doesn't guarantee all the merged changes work correctly together. With the files in question, git can successfully merge but Xcode sometimes displays a "Could not read archive" error when you try to open it - i.e., the merge corrupted the xib.
I've seen suggestions about having git ignore .xibs (not practical), or in .gitattributes disable diff by setting
*.xib -crlf -diff
Technically, that fixes the merge conflict/corrupted xib problem - but now somebody's changes are lost?
Similarly, the best recommendation I've seen for the project file is merge=union in .gitattributes:
*.pbxproj merge=union
Question: I've searched quite a bit and there doesn't seem to be a good solution. Can people with experience tell me what happens in a few use cases?
In the project I rename a file from x to y, and delete fileA. Meanwhile, another programmer committed changes to add fileC and delete fileD. What is the result of merge? I'm sure the actual file system changes will be correct, but in the Xcode navigator panel:
Will I see both x and Y?
Will fileA reappear because it's still in the other programmer's .pbxproj?
Will fileD still be there because it's still in my .pbxproj?
If git is ignoring .xib files - will I at least get a warning that a file was changed and is not being handled?
I wouldn't set any specific .gitattributes for project files or nibs these days.
Your problems merging concurrent changes to Xcode projects and xibs/storyboards exist in every team with more than one developer.
Xcode projects
A few tricks for dealing with Xcode project conflicts:
Take one side of the merge and manually apply the other changes after the merge. If you've deleted files they'll be in red, if you need to add them they'll be available to add.
When adding files to your targets they will go at the bottom of the 'Compile Sources' build phase. Avoid conflicts with other people by dragging them up this list to a random position.
Use .xcconfig files to configure your projects rather than the build settings section. Config files are trivial to merge.
My best advice if in doubt is to take one side of the merge, relax, and replay your additions.
XIBs and Storyboards
The format of XIBs (and therefor storyboards) has change significantly in recent months. I've found that additional objects are appended to the file's internal collections and merges can be done easily. If you're making changes to the same object, you may have to get in there manually.
This post from Itty Bitty Apps highlights the main changes:
The benefits of this new XIB XML format are many fold:
XIBs are much smaller (fewer lines of code).
A developer can easily read the XML and understand what it specifies in the user interface.
Merging XIBs is now much less likely to lead to broken XIBs. Before we would rarely even bother to try and merge a XIB or Storyboard.
I'm at a complete loss as to what I did to cause this:
For the second time since I started using XCode about a month ago (my first time seriously using it after taking one class several years ago) I try to run my project and the next thing I know I have errors because I have duplicate references. I looked at the project and it appeared that most of the files in my project had duplicated themselves, however I discovered that they are not duplicate files just duplicate references. This happened to me today when I tried to build on an actual iphone for the first time but it also happened to me a few weeks ago while using the simulator. Neither time do I recall doing anything unusual. I have built and tested the project probably 100+ times and normally all goes ok. I was able to fix it the first time but I think I have made it worse this time and am probably going to add the files back into a new project. My co-worker also mentioned this happening to him (he has about as much experience with xcode as I do). He told me he ended up with files nested in folders (groups?) nested in other folders about 20 deep.
My question is this: Does anyone know what I may have done to cause this. I would really like to avoid this problem in the future since it is proving to be quite a headache. Any advice would be greatly appreciated.
E.T.A. xcode version 4.6.2 (possibly an earlier version the first time it happened)
Try this instead:
Highlight all the duplicate files
Right click on one of the files and press "Delete"
When prompted for which delete option, click "Remove Reference"
Also you asked for "any advice".
If you aren't already using git source control in your Xcode projects, start now.
You can spot many mistakes like this earlier and fix them more easily using git.
When you add files as a copy, the Xcode project navigator shows added files with an A and modified files with an M.
If the file is inside a closed group folder, the folder shows an A.
If you add a reference without a copy the project navigator won't show an A but MyApp.xcodeproj will show M.
In Xcode you can discard a change before committing it.
In the case below, you would discard changes to all added or modified files.
Typically you review and commit changes frequently.
Using a gui tool such as SourceTree, you have a good chance of spotting an accidental change before you commit. For example, you can see changes to the project file.
If you accidentally commit an unintended change, you can go back later and reverse a commit.
By committing frequently, you have more control over which changes you undo and which ones you keep.
References:
http://www.raywenderlich.com/13771/how-to-use-git-source-control-with-xcode-in-ios-6
http://git-scm.com/doc (scroll down to see videos)
http://www.sourcetreeapp.com
http://gitimmersion.com
I had the same 20 deep nesting of my main folder of images. If its not a bug its very strange behaviour. I just backed it all up !! Then I opened the folder in finder, found the point at which it was starting to nest and deleted it.
I did a rebuild, but I don't think Xcode even noticed. It made no difference to the size of my app so Xcode was not putting unnecessary files in the binary.
This happened to me when I imported a file. Suddenly I had two nested directories containing what looked like copies of all my files. The compiler complained about duplicate classes.
I found a solution, but it's a ball-ache and a time sink.
1: Click on your project in the navigator to open up the project settings in the main view.
2: Open the 'Compile Sources' accordion entry.
(This allows you to see which files are being used in the compilation process.)
3: Find any duplicates in here and delete them.
(At this stage your project should compile again.)
4: In your navigator view, slow-double-click one of the files that's duplicated there. This should allow you to rename it. Change the name (not the extension) slightly.
5: You should notice that the copy becomes red. Select it and hit delete.
(This avoids the delete operation removing the file from the 'Compile Sources')
6: Rename the original file back to its original name again.
7: Repeat from 4 until done, or until bored.
8: Explain to your boss why a simple copy change took half a day.
This process can be optimised up by first renaming all duplicated files, then deleting the duplicates all at once. However this means that you can't test for successful compilation between steps, which allows you to narrow the culprit down to a single file. And takes even more time.
If compilation fails, ensure all the files you need are still in the 'Compile Sources' section, as this process can cause them to be lost from there. The compiler will normally give some reasonable errors about missing classes and variables, but a missing AppDelegate will produce a more confusing error.