I have been using XCode with subversion for some time now, no problem was caused when I was using it as a single developer (I was using 2 commands only, commit and add).
But now I have to share the code with another developer (who has never used any kind of version control) and integrating/merging the code has become a nightmare. No problem occur when we are integrating/merging .h/.m files but as soon as it comes to ".nib", "xcodeproj" and ".xcdatamodeld" files, we really don't know what to do.
Whenever we try to merge "xcodeproj", project was getting corrupt and merging ".xcdatamodeld" was kind of impossible for us.
So I was wondering if someone can share his/her experience on how to effectively use subversion/git/mercurial with XCode 4.0 in multiuser environment? or share a link, which can explain how to use subversion effectively in multiuser environment.
Thanks.
Are you doing this using Subversion? For 90% to 99% of the files in your repository, the standard Subversion workflow of checkout, edit, commit works well. However, for some types of files such as JPEGS and GIFS simply don't merge well. In this case, you'll have to do it the way we use to in the old SCCS and RCS days: Before you can edit and commit a file, you must lock it.
Locking a file prevents others from editing the same file and committing changes while you're doing your work on the file. It's crude, but it works. In Subversion, you can always lock any file you're editing, but if the file has the property svn:needs-lock on it, it will be checked out as read-only. You have to lock the file before editing it to make it writable, and you're not allowed to commit the file unless it is locked.
So, for those files, set the svn:needs-lock property on it.
You can automatically set this property on all newly added files (depending upon suffix) via setting the auto-properties in your Subversion client configuration.
And, if you really, really want to make sure that all .nibs and xcodeproj and all of the other flies of these types have svn:needs-lock set on them, you can use my pre-commit hook which will prevent these files from being committed unless this property is set.
There is no failsafe way to merge these kinds of files that I am aware of. So you will have to
try to ensure that only one person is changing these files at a time. That won't work always, so just log what you changed in the file with the commit message. Then if there is a conflict, you can manually resolve it by taking the version that changed more of the file and redo manually what the other person did.
That's normally not a big deal, like adding a new source file to an .xcodeproject, or changing the alignment of an element in a .nib. It's becoming a problem if your project is huge or your nib is containing the whole interface. For it to work well (which in practice it does), you need to split up your projects into sub-projects if they grow too huge.
I had the same problem with 2 other developers Xcode with git. Unfortunately, Xcode project files are an XML file, tracks file included in the project as well as setting. I'm not certain, but I think .nib files are also XML files as well. Someone can correct me on that.
Git did a great job at merging the Xcode project file, and never really had any problems with our *.nib files either. The only time we did have a problem is when we both added/removed files with the same names, or someone did a lot of heavy removing and adding of a lot of files.
The only way we solved this was to have each other push ann pull as soon as we added/removed files. So that way the person had the latest files, and didn't add them in their own repository then pull the latest commit which had the same file in it. Or they work adding changes to a file that was removed or renamed.
That is the best solution we found, as soon as we added or removed a file have everyone else in the team pull. Not a great solution btw. However, you should be committing often anyways.
Related
I am using Git for Windows (version 2.15, but the same issue occurs in 2.14 and I think older versions as well) and I noticed a rather annoying behavior: When I perform some basic git operations*), the modification date of the .git/objects/pack/pack-*.pack file changes. The file itself remains unchanged, but the last modification date field gets updated, which causes my backup software to think the file was changed and needs to be added to my differential backup. Because my .pack files are rather large, this increases the size of my daily backups significantly. Is there a way to prevent this behavior? That is, keep the pack file completely unchanged, including its metadata, until I perform a git gc or git repack?
Unfortunately, I wasn't able to pinpoint which operation causes this behavior. When it happened today, I only used git status, git log, git add, git mv and git commit and nothing else and the date/time got changed, but when I tried to replicate the behavior on my yesterday's backup, the date change didn't occur. I guess next time I will run Process Monitor and watch accesses to the file, but in the meanwhile, does anyone have an idea of what might be causing this problem? Thanks.
Instead of referencing your Git repo itself for your backup program to process (with the date issue), you could have:
a task which does a git bundle of your repo (that generates only one file)
your backup program would back up only that one file.
That way, you bypass entirely the modification date issue for those pack files.
You can either save and keep only one copy of a full bundle of the repo.
Or make incremental bundles.
In the end it turns out that Edward Thomson's answer explains why no "real" solution is possible. However, to facilitate my needs, I wrote a simple Windows command-line application which scans through a tree of directories, locates possible Git repositories, locates their packfiles and changes the date/time of each .pack file to that of the respective .idx file. So far it seems to run OK. I did not encounter any garbage collection issues yet, anyway. I did not release the tool yet, because I rather suspect no one else cares, but if someone is interested, I can upload it somewhere.
Apparently, someone is interested. So the program is released as of now. Not on GitHub, but still as open source, under the 3-clause BSD license. Download the binaries here: https://www.pepak.net/files/git/gitpacksync-0.01.zip
and the source code here: https://www.pepak.net/files/git/gitpacksync-0.01-source.zip
If you try to disable this then you would be prone to see subtle bugs where objects that are still in use will disappear from your repository.
You had trouble pinpointing the exact operation because every operation that adds files will do it.
This is very much intentional - Git refreshes the timestamps of objects in the database (updating the timestamp on either loose objects or packfiles) to know when an object was last written. Whenever you create a new commit, it will update the timestamp on all the files that contain objects hat were referenced.
This is important as it helps the tools that remove data (like prune) avoid race conditions: an object may be dereferenced and then re-referenced. Prune will also look at the timestamp, so by touching the file, it will not be eligible for garbage collection.
I'm programming in xcode (actually Phone Gap in conjunction with xcode) with git. I'm having a strange issue. When I create two identical branches and try to check out back and fourth between them with out making any changes git is telling me that I need to commit because a change has been made (this same thing is also resulting in merge conflicts). It says the changed file is:
platforms/ios/Butterfli.xcodeproj/project.xcworkspace/xcuserdata/benpearce.xcuserdatad/UserInterfaceState.xcuserstate
Can anyone explain what's going on and how to deal with it.
Yes, .xcworkspaces are simply files that Xcode uses to describe the workspace or projects.
IMHO, There's no need to check these files in at all, unless you share settings with other folks in your projects (and in your case, I suppose other machines that have a user named "benpearce").
In fact, you can safely add them to your .gitignore file.
More info can be seen here
Like many programmers, I'm prone to periodic fits of "inspiration" wherein I will suddenly See The Light and perform major surgery on my code. Typically, this works out well, but there are times when I discover later that — due to lack of sleep/caffeine or simply an imperfect understanding of the problem — I've done something very foolish.
When this happens, the next step is do reverse the damage. Most easily, this means the undo stack in my editor… unless I closed the file at some point. Version control is next, but if I made changes between my most recent commit (I habitually don't commit code which breaks the build) and the moment of inspiration, they are lost. It wasn't in the repository, so the code never existed.
I'd like set up my work environment in such a way that I needn't worry about this, but I've never come up with a completely satisfactory solution. Ideally:
A new, recoverable version would be created every time I save a file.
Those "auto-saved" versions won't clutter the main repository. (The vast majority of them would be completely useless; I hit Ctrl-S several times a minute.)
The "auto-saved" versions must reside locally so that I can browse through them very quickly. A repository with a 3-second turnaround simply won't do when trying to scan quickly through hundreds of revisions.
Options I've considered:
Just commit to the main repository before making a big change, even if the code may be broken. Cons: when "inspired", I generally don't have the presence of mind for this; breaks the build.
A locally-hosted Subversion repository with auto-versioning enabled, mounted as a "Web Folder". Cons: doesn't play well with working copies of other repositories; mounting proper WebDAV folders in Windows is painful at best.
As with the previous method, but using a branch in the main repository instead and merging to trunk whenever I would normally manually commit. Cons: not all hosted repositories can have auto-versioning enabled; doesn't meet points 2 and 3 above; can't safely reverse-merge from trunk to branch.
Switch to a DVCS and "combine" all my little commits when pushing. Cons: I don't know the first thing about DVCSes; sometimes Subversion is the only tool available; I don't know how to meet point 1 above.
Store working copy on a versioned file system. Cons: do these exist for Windows? If so, Google has failed to show me the way.
Does anyone know of a tool or combination of tools that will let me get what I want? Or have I set myself up with contradictory requirements? (Which I rather strongly suspect.)
Update: After more closely examining the tools I already use (sigh), it turns out that my text editor has a very nice multi-backup feature which meets my needs almost perfectly. It not only has an option for storing all backups in a "hidden" folder (which can then be added to global ignores for VCSes), but allows browsing and even diffing against backups right in the editor.
Problem solved. Thanks for the advice, folks!
Distributed Version Control. (mercurial, git, etc...)
The gist of the story is that there are no checkouts, only clones of a repository.
Your commits are visible only to you until you push it back into the main branch.
Want to do radical experimental change? Clone the repository, do tons of commits on your computer. If it works out, push it back; if not, then just rollback or trash the repo.
Most editors store the last version of your file before the save to a backup file. You could customize that process to append a revision number instead of the normal tilde. You'd then have a copy of the file every time you saved. If that would eat up too much disk space, you could opt for creating diffs for each change and customizing your editor to sequentially apply patches until you get to the revision you want.
if you use Windows Vista, 7 or Windows Server 2003 or newer you could use Shadow Copy. Basically the properties window for your files will have a new tab 'previous version' that keeps track of the previous version of the file.
the service should automatically generate the snapshot, but just to be safe you can run the following command right after your moment of "inspiration"
'vssadmin create shadow /for=c:\My Project\'
it has defiantly saved my ass quite a few times.
Shadow Copy
I think it is time to switch editors. Emacs has a variable version-control, which determines whether Emacs will automatically create multiple backups for a file when saving it, naming them foo.~1~, foo.~2~ etc. Additional variables determine how many backup copies to keep.
I hope this qualifies as programming related since it involves how to structure a project.
Because I've always used the web site model with VS.net I never had solution and project files and putting everything into source control worked great. I knew that everything I had in my web site directory was all I needed for the web site.
Now I'm using asp.net MVC and it only has a project model so now I have these solution and project files. If I work on it alone it's fine but once other people start to add/delete files from the project our solution file gets messed up and people end up having to grab the latest solution file, see what got changed and then add back/remove their files and check in the solution file again. It's become sort of a problem because sometimes people don't realize the solution file was changed, they make other changes and then when they check in everything other people do an update on their files they find that their files are gone from the project (although still physically on disk).
Is this normal? Is there a way to structure a project so that we don't need to check in solution and project files?
Your developers are not using TFS correctly. You should have multiple check-outs turned on, and everyone needs to be careful to merge their changes correctly when checking in. TFS will prompt you to do this, and accepting the defaults is nearly always the right thing to do.
It's not uncommon to have one or two developers who never get it, and you might have to help them now and then. But every programmer who works on a team needs to learn how to use source control tools correctly. If they can't manage that, they shouldn't be writing software.
[edit] It occurs to me that you might run into these problems if you check in the *.sln file directly, rather than choosing to "Add Solution to Source Control".
I don't think it's normal - what are you using for source control? It sounds like developers aren't respecting changes that others a making - checking in without merging first.
I know that early on in a project, when lots of files are being added & deleted, it can be a problem to keep up - you need to check out the project file, add your files, then check in the new file & project so other developers can also update it. You'll probably have multiple project files in a solution - perhaps one interim solution would be to have one "holding" project for each developer, then clean them up periodically - though these types of temporary fixes do have a tendency to become permanent.
I don't know of a way to set up a project file that's not in source control, though I suppose you could create a script that would generate them.
Having been through this, the key is respect & good communication between the developers.
This tends to happen with TFS multiple check outs. It can be hard to grasp coming from VSS to TFS as VSS allowed one person to check a file out at one time. Auto-merge should work most of the time for you but a couple of rules should ease the pain:
Check in early and often (if you add remove or rename a file check it in straight away even if it is a blank holder)
Before you check in do a get latest, this will ask you to resolve conflicts locally
Try to get continuous integration set up so that developers always know the state of the buidl and whether it is OK to check in\out.
We had a bit fo pain at the start of our current project but it soon settled down when we followed the rules above.
Personally, I think making changes to project and solution files requires discipline and clear (well understood) rules throughout your development team. These files (.sln, .*proj) are the bottlenecks of your project, and any errors or inconsistencies can cost you in team downtime. Changes need to be well thought out, planned and then executed.
They must be secured by source control (which you're already using, excellent) and your team members should work on the basis of only making the changes they need, and not leaving project or solution files checked out for an extended period.
If you are allowing multiple (shared) checkouts, this could become problematic in terms of overwriting another user's changes. Depending on your source control mechanism, people may be required to manually merge changes. Personally, I'd ask people to negotiate their project/solution changes with each other over merging (this can't always be achieved).
A third option if you are using TFS is the shelve feature. If someone needs to make changes locally, they can shelve the changes and merge later.
Lastly, another strategy is to try to architect your solution to be as modularized as possible - so people are distributed, working on separate projects and do not (ideally) have to overlap on too many common areas.
I'm not sure if you are using TFS, as people have mentioned, but if you are (or if you are using source control with similar capabilities) you can set it such that sln and csproj files are exclusive lockouts and are not able to be merged.
We have done this with quite large teams and while it causes some initial issues as people get used to it in the long run it has resolved many issues that were previously causing problems. Essentially you trade longer term merge issues/complexity for short term compile/checkin issues which we have found to be a good trade off.
Once you have set it to forced exclusive checkout and no merge you then get your dev teams used to the fact they should keep locks on the sln and proj files for as shorter time as possible.
Always check them in.
Always check out latest (merge if possible), make sure your change is there, before checking in a new version.
If your source control doesn't require a special action to check in from an old version, GET A DIFFERENT SOURCE CONTROL.
So you know a lot of Mac apps use "bundles": It looks like a single file to your application, but it's actually a folder with many files inside.
For a version control system to handle this, it needs to:
check out all the files in a directory, so the app can modify them as necessary
at checkin,
commit files which have been modified
add new files which the application has created
mark as deleted files which are no longer there (since the app deleted them)
manage this as one atomic change
Any ideas on the best way to handle this with existing version control systems? Are any of the versioning systems more adept in this area?
Mercurial in particular versions based on file, not directory structure. Therefore, your working tree, which is a fully-fledged repository, doesn't spit out .svn folders at each level.
It also means that a directory that is replaced, like an Application or other Bundle, will still find it's contents with particular file names under revision control. File names are monitored, not inodes or anything fancy like that!
Obviously, if a new file is added to the Bundle, you'll need to explicitly add this to your repository. Similarly, removing a file from a Bundle should be done with an 'hg rm'.
There aren't any decent Mercurial GUIs for OS X yet, but if all you do is add/commit/merge, it isn't that hard to use a command line.
For distributed SCM systems like git and mercurial shouldn't be a problem as Matthew mentioned.
If you need to use a centralized SCM like Subversion or CVS, then you can zip up (archive) your bundles before checking them into source control. This can be painful and takes an extra step. There is a good blog post about this at Tapestry Central:
Mac OS X bundles vs. Subversion
This article demonstrates a ruby script that manages the archiving for you.
An update from the future:
If I recall, the problem with managing bundles in SVN was all the .svn folders getting cleared each time you made a bundle. This shouldn't be a problem any more, now that SVN stores everything in a single .svn folder at the root.
Bringing this thread back to daylight, since the October 2013 iWork (Pages 5.0 etc.) no longer allows storing in 'flat file' (zipped), but only as bundles.
The problem is not the creation of version control hidden folders inside such structures (well, for svn it is), but as Mark says in the question: getting automatic, atomic update of files added or removed (by the application, in this case iWork) so I wouldn't need to do that manually.
Clearly, iWork and Apple are only bothered by iCloud usability. Yet I have a genuine case for storing .pages, .numbers and .keynote in a Mercurial repo. After the update, it blows everything apart. What to do?
Addendum:
Found 'hg addremove' that does the trick for me.
$ hg help addremove
hg addremove [OPTION]... [FILE]...
add all new files, delete all missing files