How to do Revision Control for Project Files? [duplicate] - version-control

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/

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.
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.
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.
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.
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.
Define a common "Source Tree" for your code, and a second for 3rd party sources.
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.

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.

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

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!

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.

Related

Buildfile with trunk/branch or separate

The issue that I am trying to figure out is whether it is best to keep the buildfile together with the source code, i.e. trunk and branches, or in some separate location (obviously still under SCM).
The question: (to keep in mind while reading the rest of the text) Buildfile that ensures branch re-buildability at any time (at expense of maintenance), or one that ensures latest bugfixes/improvements (to build process) are quickly used by multiple branches and different projects (at expense of backward compatibility with older branches)
It doesn't matter what we are building, or what technologies are used, but just for the sake of completeness: making a mobile application, building/packaging with ANT, using SVN for SCM.
Buildfile = instructions for your builder/compiler/packager to compile and package an application from source.
Buildfile with code
This is what we have right now. Ant's build.xml is stored alongside the main code in SVN. A number of other supporting "packaging" files (Apple's provisioning profiles and certs) are stored there as well.
Pros:
Single checkout from DEV perspective. When developers checkout the trunk or one of its branches, the buildfile is right there. They don't need to search for it elsewhere. A simple ant build after checkout is all they need.
When changes to the build/packaging process are done on trunk that require some reorganization in code (different file locations, support for compiler constants, etc), I need not worry about breaking existing branches, since each branch gets its own revision.
Cons:
When changes to the build/packaging process are done on trunk that improve the process and fix bugs, I now need to worry about merging those changes to all active branches, which means having to keep track of all dev/feature branches in addition to release branches.
No reusability. A technologically identical project, that only requires a few switches/property changes to the buildfile should be able to use identical buildfile. But because they are spread across multiple project locations (in addition to multiple branches, as from the point above), it becomes a nightmare to do a generic improvement that affects all those locations. Mainly due to the fact that no matter what, these files end up with little "patch-works" here and there, and eventually with conflicting merges and ever-so-slightly different processes that cannot be resolved without putting one of the projects on hold and modifying that process to "catch up" with the other.
Buildfile separate from code
To address the cons of the previous scenario in regards to re-using a single file and avoid a plethora of small fixes all over the place, I was thinking of keeping the build file separate. Shareable between the trunk, branches and other similar projects.
Pros:
Single file to modify, improve and bugfix, reusable by multiple other projects.
Cons:
No "single checkout" for DEVs (but it can be solved with svn externals or other linking solution
Breaking old/existing builds. Since there is only one version of the file now, introducing an improvement that requires code restructuring would make it incompatible with older branches. When that older branch needs to be rebuild (urgent fix to already released software), the build file will no longer work. Yes, it's solvable by getting a previous revision of the file, however:
It is not directly obvious which previous revision had worked with this branch
The older revision may be missing some other critical bugfixes to the build process.
Toss up question
So for me it is a toss up between making my life easier and only maintaining one file for bugfixes and improvements, and thus ensuring that projects use identical processes, latest bugfixes to the build process, etc. Or making developer's life easier by providing a single point of checkout, and ensuring branch "stability/re-buildability" because the buildfile that's checked in with the branch is guaranteed to work with that branch.
Is there a proper way for this? What is the proper way for this? Am I approaching this wrong?
I would suggest tagging your code with a version number every time you build. IF you ever want to roll back to a revision , you can always create a new branch from the tag of that revision and use the build.xml from that revision
You can also publish all your artefacts into a revision named directory. If you want to rollback you can just use the artefacts from this directory instead of going through the build process again .
Your build file should always be part of your code . That way a developer can check out his/her code into an IDE and start building from there for his local testing.
If you have env related configurations that are different per environment you should separate it out into a deployment configuration that is used when the code is deployed.
If you want to reuse your build files across projects , you can create a master build file with macros that is fetched prior to starting a build. The only thing you need to do is override the macros in your local project if you want to override the default behaviour

Eclipse projects and branches/trunk

I already have a repository with the classical structure
/branches
/current
/beta
/tags
/1.0
/2.0
/trunk
I would like to switch from my current editor to Eclipse but how many projects should I create ?
One for the whole repository ?
But the auto-completion will find multiple occurrences in the /trunk or /branches/* folders.
One in /trunk and one in each /branches/* ?
In that case how can I keep the hierarchical structure of the repository in my workspace ? Is there an other solution than :
/workspace/trunk
/workspace/beta
/workspace/current
Thanks.
I suggest having a separate eclipse project for the trunk and each of the branches.
I found it's much easier to merge & tag when the branches are separated. Also, updating a single project will take longer than having separated projects as you will have to checkout the new tags you're creating each time.
Another note is that Eclipse is java based. Checking out the entire codebase as a single project will significantly effect your system performance. When the projects are separated, you can just close the branches you're not working.
#aporat has good advice, though sometimes switching workspaces is pretty slow. I tend to check out multiple branches in the same workspace, overriding he name in te .project file at checkout- usually by appending the branch name.
Be sure to close any copies you're not actively working on- will save resources on your workstation.
I use a mix of thi approach and having 3 to 5 workspaces.

Project files under version control?

I work on a large project where all the source files are stored in a version control except the project files. This was the lead developer's decision. His reasoning was:
Its to time consuming to reconcile the differences among developers' working directories.
It allows developers to work independently until their changes are stable
Instead, a developer initially gets a copy of a fellow developer's project files. Then when new files are added each developer notifies all the rest about the change. This strikes me as far more time consuming in the long run.
In my opinion the supposed benefits of not tracking changes to the project files are outweighed by the danger. In addition to references to its needed source files each project file has configuration settings that would be very time consuming and error prone to reproduce if it became corrupted or there was a hardware failure. Some of them have source code embedded in them that would be nearly impossible to recover.
I tried to convince the lead that both of his reasons can be accomplished by:
Agreeing on a standard folder structure
Using relative paths in the project files
Using the version control system more effectively
But so far he's unwilling to heed my suggestions. I checked the svn log and discovered that each major version's history begins with an Add. I have a feeling he doesn't know how to use the branching feature at all.
Am I worrying about nothing or are my concerns valid?
Your concerns are valid. There's no good reason to exclude project files from the repository. They should absolutely be under version control. You'll need to standardize on a directory structure for automated builds as well, so your lead is just postponing the inevitable.
Here are some reasons to check project (*.*proj) files into version control:
Avoid unnecessary build breaks. Relying on individual developers to notify the rest of the team every time the add, remove or rename a source file is not a sustainable practice. There will be mistakes and you will end up with broken builds and your team will waste valuable time trying to determine why the build broke.
Maintain an authoritative source configuration. If there are no project files in the repository, you don't have enough information there to reliably build the solution. Is your team planning to deliver a build from one of your developer's machines? If so, which one? The whole point of having a source control repository is to maintain an authoritative source configuration from which you build and deliver releases.
Simplify management of your projects. Having each team member independently updating their individual copies of your various project files gets more complicated when you introduce project types that not everyone is familiar with. What happens if you need to introduce a WiX project to generate an MSI package or a Database project?
I'd also argue that the two points made in defense of this strategy of not checking in project files are easily refuted. Let's take a look at each:
Its to time consuming to reconcile the differences among developers' working directories.
Source configurations should always be setup with relative paths. If you have hard coded paths in your source configuration (project files, resource files, etc.) then you're doing it wrong. Choosing to ignore the problem is not going to make it go away.
It allows developers to work independently until their changes are stable
No, using version control lets developers work in isolation until their changes are stable. If you each continue to maintain your own separate copies of the project files, as soon as someone checks in a change that references a class in a new source file, you've broken everyone on the team until they stop what they're doing and carefully update their project files. Compare that experience with just "getting latest" from source control.
Generally, a project checked out of SVN should be working, or there should be tools included to make it work (e.g. autogen.sh). If the project file is missing or you need knowledge about which files should be in the project, there is something missing.
Automatically generated files should not be in SVN, as it is pointless to track the changes to these.
Project files with relative path belong under source control.
Files that don't: For example in .Net, I would not put the .suo (user options) web.config (or app.config under source control. You may have developers using different connection strings, etc.
In the case of web.config, I like to put a web.config.example in. That way you copy the file to web.config upon initial checkout and tweak what settings you'd like. If you add something that needs to be added to all web.config, you merge those lines into the .example version and notify the team to merge that into their local version.
I think it depends on the IDE and configuration of the project. Some IDEs have hard-coded absolute paths and that's a real problem with multiple developers working on the same code with different local copies and configurations. Avoid absolute path references to libraries, for example, if you can.
In Eclipse (and Java), it's fine to commit .project and .classpath files (so long as the classpath doesn't have absolute references). However, you may find that using tools like Maven can help having some independence from the IDE and individual settings (in which case you wouldn't need to commit .project, .settings and .classpath in Eclipse since m2eclipse would re-create them for you automatically). This might not apply as well to other languages/environments.
In addition, if I need to reference something really specific to my machine (either configuration or file location), it tend to have my own local branch in Git which I rebase when necessary, committing only the common parts to the remote repository. Git diff/rebase works well: it tends to be able to work out the diffs even if the local changes affect files that have been modified remotely, except when those changes conflict, in which case you get the opportunity to merge the changes manually.
That's just retarded. With a set up like that, I can have a perfectly working project containing files that are subtly different from everyone else. Imagine the havoc this would cause if someone accidentally propagates this mess into QA and everyone is trying to figure out what's going on. Imagine the catastrophe that would ensue if it ever got released to the production environment...!

Managing multiple branches in Eclipse, or getting a VS-like setup for Eclipse

In VS, it's simple. Everything the project needs is stored in the project folder and all VS settings are stored in one place. Eclipse, however, stores Eclipse settings with the project and keeps a .metadata at the workspace level which is needed to detect the projects in the workspace. Thus, I can't simply branch a project and then open it in Eclipse. I need to set up a workspace, branch it into that workspace, copy over all my workspace settings (settings import/export doesn't even work right in Eclipse) so I have the same Eclipse settings, then do some kind of import to get the project in the workspace. This is what I generally refer to as a pain in the freaking neck, and it causes me to not branch any Java projects and to keep them all in one folder. This is also a pain.
Is there any way I can get a setup where I can just branch a project and open it in Eclipse, while maintaining the same Eclipse settings?
UPDATE: The current state of the question is expressed by the comment to soru's post.
Pretty sure you want to:
Keep the same workspace for all projects (or maybe a few, at the level of say 'hobby' and 'work').
switch between different branches in the same project by using the features of your version control tool/plugin
if you want to work on multiple branches at the same time, just create two projects, and manage them both as above.
if you want to temporarily hide the inactive version, use the 'working set' feature.
The main limitation is that you might want to have projects with the same name, but you can't. So sometimes you have to make up a project name different from the underlying folder name.
In general, mapping between VS and Eclipse:
Installation <-> workspace
Solution <-> working set
Project <-> project or folder or VC system branch or working set node
Refs:
VS object model
using working sets in Eclipse
working with branches in subclipe
Well, I'm not a fan of keeping any IDE specific settings in the repo, but when I do I keep only .project, .classpath and .settings.
You can also keep you settings at the workspace level (Windows->Preferences),and not on the project level (Project->Properties).
Also why do you create a seperate workspace for branches? You can keep it in one workspace, no need to create another one.
You could also use "switch" in subversion (I don't know if that's what you are using, but other revision systems should have something similar) and go to the branch you have created.
(of course if you wan to work concurrently on more than one branch then it doesn't help)
I can't speak to the Eclispe problem, as i'm only a n00b user, but I can speak to the secondary question.
I've been working in systems for a number of years that ended up needing to have various branches of the same code done for a variety of reasons.
One of the best reasons for keeping specific settings in project-specific locations is that so the various compiler / sdk / etc. settings & files can be specific per-branch and not collide between branches.
This allows, for example, for the work to upgrade a code set to a newer sdk/compiler to be done without impacting the ability to work on the existing "main line" code set with the previous sdk/compiler should the need arise.
In my experience in the computer game industry as a core technology wog, this happens a LOT.
I'm sure the same situations occur outside the computer game industry, maybe just not at the same pace.

TFS - Branching for experimental development: Solution fails to load

Disclaimer: I'm stuck on TFS and I hate it.
My source control structure looks like this:
/dev
/releases
/branches
/experimental-upgrade
I branched from dev to experimental-upgrade and didn't touch it. I then did some more work in dev and merged to experimental-upgrade. Somehow TFS complained that I had changes in both source and target and I had to resolve them. I chose to "Copy item from source branch" for all 5 items.
I check out the experimental-upgrade to a local folder and try to open the main solution file in there. TFS prompts me:
"Projects have recently been added to this solution. Would you like to get them from source control?
If I say yes it does some stuff but ultimately comes back failing to load a handful of the projects. If I say no I get the same result.
Comparing my sln in both branches tells me that they are equal.
Can anyone let me know what I'm doing wrong? This should be a straightforward branch/merge operation...
TIA.
UPDATE:
I noticed that if I click "yes" on the above dialog, the projects are downloaded to the $/ root of source control... (i.e. out of the dev & branches folders)
If I open up the solution in the branch and remove the dead projects and try to re-add them (by right-clicking sln, add existing project, choose project located in the branch folder, it gives me the error...
Cannot load the project c:\sandbox\my_solution\proj1\proj1.csproj, the file has been removed or deleted. The project path I was trying to add is this: c:\sandbox\my_solution\branches\experimental-upgrade\proj1\proj1.csproj
What in the world is pointing these projects outside of their local root? The solution file is identical to the one in the dev branch, and those projects load just fine. I also looked at the vspscc and vssscc files but didn't find anything.
Ideas?
#Ben
You can actually do a full delete in TFS, but it is highly not recommended unless you know what you are doing. You have to do it from the command line with the command tf destroy
tf destroy [/keephistory] itemspec1 [;versionspec]
[itemspec2...itemspecN] [/stopat:versionspec] [/preview]
[/startcleanup] [/noprompt]
Versionspec:
Date/Time Dmm/dd/yyyy
or any .Net Framework-supported format
or any of the date formats of the local machine
Changeset number Cnnnnnn
Label Llabelname
Latest version T
Workspace Wworkspacename;workspaceowner
Just before you do this make sure you try it out with the /preview. Also everybody has their own methodology for branching. Mine is to branch releases, and do all development in the development or root folder. Also it sounded like branching worked fine for you, just the solution file was screwed up, which may be because of a binding issue and the vssss file.
#Nick: No changes have been made to this just yet. I may have to delete it and re-branch (however you really can't fully delete in TFS)
And I have to disagree... branching is absolutely a good practice for experimental changes. Shelving is just temporary storage that will get backed up if I don't want to check in yet. But this needs to be developed while we develop real features.
Without knowing more about your solution setup I can't be sure. But, if you have any project references that could explain it. Because you have the "experimental-upgrade" subfolder under "branches" your relative paths have changed.
This means when VS used to look for your referenced projects in ..\..\project\whatever it now has to look in ..\..\..\project\whatever. Note the extra ..\
To fix this you have to re-add your project references. I haven't found a better way. You can either remove them and re-add them, or go to the properties window and change the path to them, then reload them. Either way, you'll have to redo your references to them from any projects.
Also, check your working folders to make sure that it didn't download any of your projects into the wrong folders. This can happen sometimes...
A couple of things. Are the folder structures the same? Can you delete and readd the project references successfully?
If you create a solution and then manually add all of the projects, does that work. (That may not be feasable - we have solutions with over a hundred projects).
One other thing (and it may be silly) - after you did the branch, did you commit it? I'm wondering if you branched and didn't check it in, and then merged, and then when you tried to check-in then, TFS was mighty confused.
#Kevin:
This means when VS used to look for your referenced projects in ....\project\whatever it now has to look in ......\project\whatever. Note the extra ..\
You may be on to something here, however it doesn't explain why some projects load and others do not. I haven't found a correlation between them yet.
I think I'll try to re-add the projects and see if that works.
#Cory:
I think that's what I'm going to try... I have about 20 projects and 8 or so aren't loading. The folder structures are identical from root... ie: there aren't any references outside of DEV.