Resolving merge conflicts in large csproj file - visual-studio

.csproj file is in a xml format and it seems Visual Studio is adding there elements in random order. Perforce merge treats .csproj file as text file (order matters). This leads to a merging nightmare. Is there a way how to either:
(Preferred) Force perforce merge to treat .csproj file like xml file (order of nodes doesn't matter)
Force Visual Studio to keep some sort of ordering of xml elements inside .csproj (plugin perhaps?)
UPDATE
There seems to be feature request for it already - http://p4ideax.com/ideas/585/intelligent-support-for-xml-when-doing-merges though it doesn't have enough votes (yet).
UPDATE 2
Seems perforce folks have moved their voting system, new url is
https://perforce.ideas.aha.io/ideas/P4D-I-77

I just created a project on GitHub called CsProjArrange. I created it to fix the merging issues in my git repository. There are still some kinks which need to be ironed out, so I am open to some pull requests if you see anything that can be improved.
You just set it up as a clean filter in git for the .csproj files.

I have seen a known VS issue posted about supporting file patterns in project files. Are you referring to this issue? http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/4512873-vs-ide-should-support-file-patterns-in-project-fil
Yes, in Perforce you can designate what type of file types you want per file using the typemap table, but I am not sure if this is what you are looking for. For example:
http://answers.perforce.com/articles/KB_Article/Perforce-File-Type-Options
http://www.perforce.com/perforce/doc.current/manuals/cmdref/p4_typemap.html
EXAMPLE
If you wanted your .csproj file to be treated like a Perforce binary file,
you would add the following line to the typemap table:
binary //....csproj
This will ensure on a go-forward basis your typemap table sets all
files on the server to binary.
For all current files, here is the command you need to run:
p4 edit -t binary //....csproj
p4 submit -d "Changing all of csproj to binary etc"
You can change a filetype with the 'edit', 'reopen' and 'add' commands:
-- p4 edit
http://www.perforce.com/perforce/doc.current/manuals/cmdref/edit.html#1040665
-- p4 reopen
http://www.perforce.com/perforce/doc.current/manuals/cmdref/reopen.html#1040665
-- p4 add
http://www.perforce.com/perforce/doc.current/manuals/cmdref/add.html#1040670

Related

Xcode Project file git merge conflict

In Xcode, what's the best way to avoid Git conflict in the project file? (I am in manual git, not using Xcode interface for git)
I've cloned mapbox-ios-sdk from Github, hacked it, and now the remote master has changed. When I tried to pull the remote changes into my local, after merging there would be merge conflict in the project file. (Specifically, I mean the project.pbxproj in the .xcodeproj)
I do not really think project file should be put into the ignore, since if there are any new files the project file, the .pbxproj file seems to be changed. (Or am I just plain wrong and this file should be put to ignore? But obviously it wasn't on ignored in the mapbox-ios-sdk to begin with. People need the project file after all.) But I've also ran into this conflict before in my collaboration project with another collaborator and it's keeping me from using Git altogether.
Should I figure out how to manually resolve conflict or is there a better way to deal with this?
A lot of websites simply suggest to use a .gitattributes file with:
*.pbxproj merge=union
We're gonna try this approach before trying to use scripts. If we find any issues I'll be sure to update this post. Also if anyone else has comments to this approach please include.
.pbxproj will change when you add new files to the project. There will be conflicts if two or more collaborators add files at the same time (without getting one another's changes first). We are avoiding this in my project by following these steps before and after adding new files:
Before adding a file, commit your changes, then pull from the master so that you have the latest.If someone has added a file, you now have the latest .pbxproj
Add your file(s).
Immediately commit and push your changes up to the master (hopefully, before another collaborator has added another file).
It's wimpy, but we don't relish manually resolving .pbxproj conflicts.
Also, see this Stack Overflow question with excellent responses: How to use Git properly with XCode?
You should check my script xUnique, it is now the best solution to merge Xcode project file before Apple takes action on it.
What it does & How it works
convert project.pbxproj to JSON format
Iterate all objects in JSON and give every UUID an absolute path, and create a new UUID using MD5 hex digest of the path
All elements in this json object is actually connected as a tree
We give a path attribute to every node of the tree using its unique attribute; this path is the absolute path to the root node,
Apply MD5 hex digest to the path for the node
Replace all old UUIDs with the MD5 hex digest and also remove unused UUIDs that are not in the current node tree and UUIDs in wrong format
Sort the project file inlcuding children, files, PBXFileReference and PBXBuildFile list and remove all duplicated entries in these lists
see sort_pbxproj method in xUnique.py if you want to know the implementation;
It's ported from my modified sort-Xcode-project-file, with some differences in ordering PBXFileReference and PBXBuildFile
With different options, you can use xUnique with more flexibility
Check README file for more details.
In most case, you can fix the merge by following code, remove the lines which git adds:
#!/bin/bash
FILE={PRODUCT_NAME}.xcodeproj/project.pbxproj
sed '/======/d' $FILE | sed '/<<<<</d' | sed '/>>>>>/d' > temp
cat temp > $FILE
rm temp
but if you rename the group of your project and it leads to conflicts, you will manually delete the extra lines of your original group.
When this is caused by adding files from two or more collaborators/branches (which in my experience has always been the case to date and can be checked by looking at the diff) I do this:
Resolve the conflict by "use ours" or "use theirs" (whichever has added the most files).
Commit (this produces a repo that contains all the added files but some are not in the project).
Within Xcode use "Add Files To..." to add the missing files from the other collaborator/branch (they are easy to find as they are in the project directory and Xcode usefully highlights them for you).
Commit.
(I am not convinced step 2 is really necessary - but feels neater to me).
You can also use Mergepbx manually do it as follows
Install Mergepbx using brew.
brew install mergepbx
Run a command each time you have conflicts in your project file to automatically resolve them.
git mergetool --tool=mergepbx PROJECT.pbxproj
I need to get master code in my branch So, I was taking pull from master and I have a change in my .pbxproj file and master has different configuration. So, It was showing conflict in .pbxproj file. Follow these steps to resolve it
Open .pbxproj in Finder->
Right click on file Choose Show Package Contents->
Choose .pbxproj file and open it with TextEdit->
It will show conflict lines as below.
<<<<<<< HEAD"
// head changes
===========
// Your changes
>>>>>>>>
You have choose the right one from head Changes and your changes and Delete the rest.
Now commit you code
git add .
git commit -m"conflict resolved"
git status // Check you files status
If everything is fine the push you code.
git push
I made an app for fixing things in Xcode project files when these sort of things go wrong. You'd still have to do some manually merging first though, unfortunately.
https://itunes.apple.com/us/app/xsaviour/id1449886415?mt=12
If all else fails, while tedious. you can open your pbxproj in your git client, then manually, go file by file and ensure each one is either removed or has 4 lines (6 occurrences).
I had the same problem, so I wrote a tool in Swift that will resolve conflicts due to adding, deleting, moving, and renaming files and groups. You can set it up as a git merge driver so the script runs automatically when you merge a branch.
You can check it out here: XcodeMergeDriver

Subversion svn:ignore on update

I'm working in Visual Studios 2010 and Ankhsvn.
I need to exclude a few of my files from being Committed (which I did through ignore-on-commit in the Change log.)
How do I exclude the files from being changed when I update?
I've tried adding the svn:ignore property, but I keep getting errors thrown. Maybe I'm using it wrong... It shouldn't be this hard to completely exclude files.
svn:ignore is a property on a directory that you set to specify that the given resources shouldn't be in version control - which doesn't sound like what you want. If the file is already under version control, SVN will always try to process it. The effect you're after (restricting svn operations to a given subset of files) can be achieved using the --changelist option. You can use svn changelist to create lists of files, then suboptions to add and remove files from that list, then you can pass that changelist to svn up to limit which files get processed.

Git Merging of Binary Files (in particular Xcode project files)

I've got an Xcode project under git and I've got a "experimental" branch off of my "master" branch. Both branches have diverged since the branch (so no fast-forwarding!), and I am merging "experimental" into my "master" branch.
I've setup a .gitattributes file to treat a particular Xcode file (project.pbxproj) as binary, as it should be treated as such. However, I'm not sure exactly how to merge it. I'm not sure what that particular file does, but if for example it handled which files were added to the project there's no way I can merge them, and therefore I'd have to manually add certain files back to the project (possibly not remembering them all). How do others handle this situation?
Also, I've read that you have to manually update binary files (obviously) or copy over different versions. However, once I'm into the merge process the file in my working copy is the "master" version. How can I access the "experimental" version? I can't check it out as it would disrupt the merging process.
Thanks for your time!
In general, for binary files, I recommend a copy-merge type of .gitattribute directive.
That is, I just copy the file coming from the remote end of a merge.
For .pbxproj files however, that may not be a good option, as described here.
Wrapping these files would only make the problem worse as far as I can tell - as you wold be completely unable to merge changes.
While you can merge project files in some cases, it's not something that you should
count on being able to do. The basic recommendation is to avoid editing the project files at the same time as someone else.
I like versionning projects files (like the ones for Eclipse), only if I know they are:
not modified that often (certainly not by each developers)
only using relative paths
no data specifics to one workstation
In short, if those files are not to be merged (or will only be trivial to merge), I want them in a VCS. In your case, that may not be so useful to have them in said VCS in the first place.
Note: as mentioned in the Git manual:
During the merge, the index holds three versions of each file. Each of these three "file stages" represents a different version of the file:
$ git show :1:file.txt # the file in a common ancestor of both branches
$ git show :2:file.txt # the version from HEAD.
$ git show :3:file.txt # the version from MERGE_HEAD

Git and pbxproj

I was looking at an open source Mac application, and they gave some suggested values for .gitignore. They were what I would expect...
However, they also suggested an entry into a .gitattributes file:
*.pbxproj -crlf -diff -merge
I'm not the most knowledgable in terms of git, so I was wondering - what exactly are the benefits of adding this line? What does do in particular? I've only seen this suggested in this one project, and if it was normal practice I would have expected to see it elsewhere right now. So I was curious about how it applies to the pbxproj file specifically.
The pbxproj file isn't really human mergable. While it is plain ASCII text, it's a form of JSON. Essentially you want to treat it as a binary file.
Here's what the individual flags do:
-crlf: don't use crlf <=> cr conversion
-diff: do not diff the file
-merge: do not attempt to merge the file
From the Pro Git book by Scott Chacon
Some files look like text files but
for all intents and purposes are to be
treated as binary data. For instance,
Xcode projects on the Mac contain a
file that ends in .pbxproj, which is
basically a JSON (plain text
javascript data format) dataset
written out to disk by the IDE that
records your build settings and so on.
Although it’s technically a text file,
because it’s all ASCII, you don’t want
to treat it as such because it’s
really a lightweight database — you
can’t merge the contents if two people
changed it, and diffs generally aren’t
helpful. The file is meant to be
consumed by a machine. In essence, you
want to treat it like a binary file.
A diff is oftentimes useful at commit time to check what has been changed. So I find it useful to keep the diffing ability but just prevent merging. So I use this in my .gitattributes file:
*.pbxproj -crlf -merge
On another note, has anybody tried using merge=union for pbxproj files? See: Should I merge .pbxproj files with git using merge=union?
I faced the problem of corruption *.pbxproj file after resolving merge conflicts manually. Or, more often, my files just 'disappeared' from the working tree after the merge. It drove me mad because we work in a team, so you can imagine how messy it can become very fast.
So, I have tested merge=union and it works well so far. I know that it can't help if files were deleted or renamed at the same time, but for adding new files it works as expected: there is no conflicts and files don't disappear after the merge. And it also saves quite a bit of time.
If you want to try it out, here is what I did.
1) Create a global .gitattributes file. Run in terminal:
touch ~/.gitattributes
git config --global core.attributesfile ~/.gitattributes
2) This command should open it in a text editor:
open ~/.gitattributes
3) When the file opens, add this line and save the file:
*.pbxproj binary merge=union
Done. Hope this will help new readers like it helped me.
I wrote a python script named xUnique to solve this merge conflicts problem.
This script do following things:
replace all 24 chars UUID to project-wide unique 32 chars MD5 digests, and remove any unused UUIDs(usually caused by careless merge before). This would prevent duplicate UUIDs because different machines/Xcode generate different UUIDs in this file. Xcode does recognize it and the project could be opened. During this process, remove all invalid lines in project file
sort the project file. I wrote a python version of sort-Xcode-project-file from Webkit team with more new features:
support to sort PBXFileReference and PBXBuildFile sections
remove duplicated files/refs
avoid creating new file even if no changes made, this makes less commits after using this script
More details and updates of xUnique, please refer to README

Should I add the Visual Studio .suo and .user files to source control?

Visual Studio solutions contain two types of hidden user files. One is the solution .suo file which is a binary file. The other is the project .user file which is a text file. Exactly what data do these files contain?
I've also been wondering whether I should add these files to source control (Subversion in my case). If I don't add these files and another developer checks out the solution, will Visual Studio automatically create new user files?
These files contain user preference configurations that are in general specific to your machine, so it's better not to put it in SCM. Also, VS will change it almost every time you execute it, so it will always be marked by the SCM as 'changed'.
I don't include either, I'm in a project using VS for 2 years and had no problems doing that. The only minor annoyance is that the debug parameters (execution path, deployment target, etc.) are stored in one of those files (don't know which), so if you have a standard for them you won't be able to 'publish' it via SCM for other developers to have the entire development environment 'ready to use'.
You don't need to add these -- they contain per-user settings, and other developers won't want your copy.
Others have explained why having the *.suo and *.user files under source control is not a good idea.
I'd like to suggest that you add these patterns to the svn:ignore property for 2 reasons:
So other developers won't wind up
with one developer's settings.
So when you view status, or commit
files, those files won't clutter the code base and obscure new files you need to add.
We don't commit the binary file (*.suo), but we commit the .user file. The .user file contains for example the start options for debugging the project. You can find the start options in the properties of the project in the tab "Debug". We used NUnit in some projects and configured the nunit-gui.exe as the start option for the project. Without the .user file, each team member would have to configure it separately.
Hope this helps.
Since I found this question/answer through Google in 2011, I thought I'd take a second and add the link for the *.SDF files created by Visual Studio 2010 to the list of files that probably should not be added to version control (the IDE will re-create them). Since I wasn't sure that a *.sdf file may have a legitimate use elsewhere, I only ignored the specific [projectname].sdf file from SVN.
Why does the Visual Studio conversion wizard 2010 create a massive SDF database file?
No, you should not add them to source control since - as you said - they're user specific.
SUO (Solution User Options): Records
all of the options that you might
associate with your solution so that
each time you open it, it includes
customizations that you
have made.
The .user file contains the user options for the project (while SUO is for the solution) and extends the project file name (e.g. anything.csproj.user contains user settings for the anything.csproj project).
This appears to be Microsoft's opinion on the matter:
Adding (and editing) .suo files to source control
I don't know why your project stores the DebuggingWorkingDirectory in
the suo file. If that is a user specific setting you should consider
storing that in the *.proj.user filename. If that setting is shareable
between all users working on the project you should consider storing
it in the project file itself.
Don't even think of adding the suo file to source control! The SUO
(soluton user options) file is meant to contain user-specific
settings, and should not be shared amongst users working on the same
solution. If you'd be adding the suo file in the scc database I don't
know what other things in the IDE you'd break, but from source control
point of view you will break web projects scc integration, the Lan vs
Internet plugin used by different users for VSS access, and you could
even cause the scc to break completely (VSS database path stored in
suo file that may be valid for you may not be valid for another user).
Alin Constantin (MSFT)
By default Microsoft's Visual SourceSafe does not include these files in the source control because they are user-specific settings files. I would follow that model if you're using SVN as source control.
Visual Studio will automatically create them. I don't recommend putting them in source control. There have been numerous times where a local developer's SOU file was causing VS to behave erratically on that developers box. Deleting the file and then letting VS recreate it always fixed the issues.
No.
I just wanted a real short answer, and there wasn't any.
On the MSDN website, it clearly states that
The solution user options (.suo) file contains per-user solution
options. This file should not be checked in to source code control.
So I'd say it is pretty safe to ignore these files while checking in stuff to your source control.
I wouldn't. Anything that could change per "user" is usually not good in source control. .suo, .user, obj/bin directories
These files are user-specific options, which should be independent of the solution itself. Visual Studio will create new ones as necessary, so they do not need to be checked in to source control. Indeed, it would probably be better not to as this allows individual developers to customize their environment as they see fit.
You cannot source-control the .user files, because that's user specific. It contains the name of remote machine and other user-dependent things. It's a vcproj related file.
The .suo file is a sln related file and it contains the "solution user options" (startup project(s), windows position (what's docked and where, what's floating), etc.)
It's a binary file, and I don't know if it contains something "user related".
In our company we do not take those files under source control.
They contain the specific settings about the project that are typically assigned to a single developer (like, for example, the starting project and starting page to start when you debug your application).
So it's better not adding them to version control, leaving VS recreate them so that each developer can have the specific settings they want.
.user is the user settings, and I think .suo is the solution user options. You don't want these files under source control; they will be re-created for each user.
Others have explained that no, you don't want this in version control. You should configure your version control system to ignore the file (e.g. via a .gitignore file).
To really understand why, it helps to see what's actually in this file. I wrote a command line tool that lets you see the .suo file's contents.
Install it on your machine via:
dotnet tool install -g suo
It has two sub-commands, keys and view.
suo keys <path-to-suo-file>
This will dump out the key for each value in the file. For example (abridged):
nuget
ProjInfoEx
BookmarkState
DebuggerWatches
HiddenSlnFolders
ObjMgrContentsV8
UnloadedProjects
ClassViewContents
OutliningStateDir
ProjExplorerState
TaskListShortcuts
XmlPackageOptions
BackgroundLoadData
DebuggerExceptions
DebuggerFindSource
DebuggerFindSymbol
ILSpy-234190A6EE66
MRU Solution Files
UnloadedProjectsEx
ApplicationInsights
DebuggerBreakpoints
OutliningStateV1674
...
As you can see, lots of IDE features use this file to store their state.
Use the view command to see a given key's value. For example:
$ suo view nuget --format=utf8 .suo
nuget
?{"WindowSettings":{"project:MyProject":{"SourceRepository":"nuget.org","ShowPreviewWindow":false,"ShowDeprecatedFrameworkWindow":true,"RemoveDependencies":false,"ForceRemove":false,"IncludePrerelease":false,"SelectedFilter":"UpdatesAvailable","DependencyBehavior":"Lowest","FileConflictAction":"PromptUser","OptionsExpanded":false,"SortPropertyName":"ProjectName","SortDirection":"Ascending"}}}
More information on the tool here: https://github.com/drewnoakes/suo
Using Rational ClearCase the answer is no. Only the .sln & .*proj should be registered in source code control.
I can't answer for other vendors. If I recall correctly, these files are "user" specific options, your environment.
Don't add any of those files into version control. These files are auto generated with work station specific information, if checked-in to version control that will cause trouble in other work stations.
No, they shouldn't be committed to source control as they are developer/machine-specific local settings.
GitHub maintain a list of suggested file types for Visual Studio users to ignore at https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
For svn, I have the following global-ignore property set:
*.DotSettings.User
*.onetoc2
*.suo .vs PrecompiledWeb thumbs.db obj bin debug
*.user *.vshost.*
*.tss
*.dbml.layout
As explained in other answers, both .suo and .user shouldn't be added to source control, since they are user/machine-specific (BTW .suo for newest versions of VS was moved into dedicated temporary directory .vs, which should be kept out of source control completely).
However if your application requires some setup of environment for debugging in VS (such settings are usually kept in .user file), it may be handy to prepare a sample file (naming it like .user.SAMPLE) and add it to source control for references.
Instead of hard-coded absolute path in such file, it makes sense to use relative ones or rely on environment variables, so the sample may be generic enough to be easily re-usable by others.
If you set your executable dir dependencies in ProjectProperties>Debugging>Environment, the paths are stored in '.user' files.
Suppose I set this string in above-mentioned field: "PATH=C:\xyz\bin"
This is how it will get stored in '.user' file:
<LocalDebuggerEnvironment>PATH=C:\xyz\bin$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
This helped us a lot while working in OpenCV. We could use different versions of OpenCV for different projects. Another advantage is, it was very easy to set up our projects on a new machine. We just had to copy corresponding dependency dirs. So for some projects, I prefer to add the '.user' to source control.
Even though, it is entirely dependent on projects. You can take a call based on your needs.

Resources