I recently started using Team Foundation Server, and am having some trouble getting it to work the way I want it to.
I've used Subversion for a couple years now, and love the way it works. I always set up three folders under each project, Trunk, Tags, and Branches.
When I'm working on a project, all my code lives under a folder called "C:\dev\projectname". This "projectname" folder can be made to point to either trunk, or any of the branches or tags using Subversion (with the switch command).
Now that I'm using TFS (my client's system), I'd like things to work the same way. I created a "Trunk" folder with my project in it, and mapped "Project/Trunk/Website" to "c:\dev\Website".
Now, I want to make a release under the "tags" folder (located in "Project/Tags/Version 1.0/Website", and TFS is giving me the following error when I execute the branch command:
"No appropriate mapping exists for $Project/tags/Version 1.0/Website"
From what I can find on the internet, TFS expects you to have a mapping to your hard drive at the root of the project (the "Project" folder in my case), and then have all the source code that lives in trunk, tags and branches all pulled down to your hard drive. This sucks because it requires way too much stuff on your hard drive, and even worse, when you are working in a solution in Visual Studio, you won't be able to pull down "Version 2.0" and have all your project references to other projects work, because they'll all be pointing to "trunk" folders under the main folder, not just the main folder itself.
What I want to do is have the root "Project/Website" folder on my hard drive, and be able to have it point to (mapped to) either tags, branches, or trunk, depending on what i'm doing, without having to screw around with fixing Visual Studio project references.
Ideas?
The first thing to understand is that the TFS model of the version tree is different from what you may be used to. It's at an extreme end of the spectrum.‡
I've used Subversion for a couple years now, and love the way it works. I always set up three folders under each project, Trunk, Tags, and Branches.
What you think of as "tags, branches, and trunks" are all represented by folders in TFS. A "trunk" is a folder that was created by a simple add, not as a branch of another folder. A "branch" is a folder that's derived from (and henceforth related to) another folder elsewhere in the system via the Branch & Merge operations. TFS doesn't have "tags" per se; the closest analogue is to create a branch based off of a historical version (via changeset number or label). Once again, this becomes yet another folder.
When it comes to managing your local workspace, the concept that "everything's a folder" is good news. If you want to create arbitrarily complex views on tags/branches/trunks, in the TFS world that task reduces down to the very simple problem of mapping local paths <-> server paths.
Of course, that doesn't mean you should. Disk space is a lot cheaper than network bandwidth or server CPU cycles. More importantly: the more complex your mappings, the more likely you are to accidentally commit the wrong file to the wrong place. My usual recommendation is:
This strategy provides:
What I want to do is have the root "Project/Website" folder on my hard drive, and be able to have it point to (mapped to) either tags, branches, or trunk, depending on what i'm doing, without having to screw around with fixing Visual Studio project references.
This is possible too. As mentioned you're just trading disk space for bandwidth/CPU. No big deal if your infrastructure supports it. I personally would find it too limiting in terms of parallel development, plus a higher chance of screwups -- but it's only natural a person raised on SVN might feel differently.
Here are the steps:
‡In TFS, when you create a branch, it appears to the user as a brand new folder hierarchy. Put another way: when you look at the repository a priori, there's no clear way to distinguish "real" files/folders from branches. And frankly there isn't much difference. A "branch" is just another item, one that happens to have >=1 pieces of merge history metadata associated with it. Plenty of TFS commands depend on said metadata, and you can certainly query for it directly, but it won't show up in a simple tf dir. Meanwhile, because every branch occupies a unique position in path space, that means it's no more or less complex to uniquely specify a branched versionspec. $/path;changeset is sufficient, just like any other item.
CVS takes the opposite approach. When you branch, the path doesn't change. What you've done instead is bifurcate the versions along another dimension. This makes simple cases very easy to visualize: there's just one tree. Of course, you've only shifted the complexity elsewhere. When you want to uniquely specify a version of an item, knowing a path and a revision number isn't enough anymore; you need to know the branch too. And what if you rename a file in one branch but not another? In TFS nobody would care until it was time to merge the branches; in CVS just viewing the repository raises the issue. I'm sure you can think of other subtleties -- I'm not familiar enough with it to know how it handles every edge case.
Most SCC systems lie somewhere between these extremes. Let's call TFS 2005/2008 the far "left" and CVS the opposite "right."
Subversion sits basically atop TFS at the "left" pole. While the implementations are very different, the user's view of branching is almost identical now that merge tracking is finally implemented. (One could argue that prior to v1.5, it was even a little bit farther left than TFS. Branches were simply copies with low-level optimizations; the user had no way to query for relational metadata. SourceSafe falls into this same category, if not even farther left due to lack of systemwide version numbers.) Users coming from the SVN world shouldn't have a hard time once they understand the client/server workspace model and rejigger their terminology. (SVN has a lot of CVS baggage in its terms, eg the word "tag"; in fairness TFS inherits some verbal crud from VSS, eg the pervasive use of "checkin/checkout" despite being edit-merge-commit by default.)
Perforce is one notch to the right of TFS. Their underlying model is identical. They have the additional concept of branch specifications which meet some common user scenarios -- eg quickly knowing "which folders represent branches", shortcuts for specifying branched versionspecs w/o needing the full path -- but it's just syntax sugar.
TFS 2010 lies another couple notches to the right. Like Perforce they've created a store of "branch objects" that exist independently from (but map back to) the repository tree. Each branch also knows its relationships (eg parent, child, baseless) within a user defined branch hierarchy.
I'd place ClearCase about 2/3 of the way to the right. Complex branching scenarios fundamentally happen in version space from the server's point of view. However they have an extremely powerful system of "views" layered on top. As a result, the structure the user actually sees might be manipulated to resemble path space, or some hybrid. A similar level of customizability applies to their local workspace mappings.
Most other "enterprise" SCMs are about 3/4 of the way to the right. (eg AccuRev, MKS, StarTeam) Users can typically view the repository + branch tree in a variety of powerful ways, but can't configure system itself as flexibly as CC. This is probably a good thing :)
CVS is on the far right as described earlier. Ditto its ancestors RCS and SCCS.
Classifying distributed systems like Monotone, BitKeeper, and their derivatives is beyond the scope of this answer :)
§A couple newer operations in TFS can be done without a workspace at all:
A few others require mappings into a workspace, but don't require you to download any files:
A few more require partial mappings and/or partial downloads:
I prefer to do these kinds of operations in their own "maintenance" workspace, isolated from my day-to-day development. Having their own workspace also means I can map huge parts of the repository in one fell swoop without actually downloading them. (On the contrary, in your "development" workspaces it's a best practice to run Get w/o any restrictive path scopes.) And as I've mentioned a few times now keeping the local <-> server mapping broad & simple means relative paths stay constant, references don't break, files don't get accidentally committed or committed to the wrong place; everyone is generally happier.
YMMV.
You could map the root folder to a location on your hard drive and not do a get latest version. Then in addition to the root being mapped you can map the sub folder to the location you want. When you do the branch just be sure to uncheck Create local working copies for the new branch.
$/Project -> C:\temp
$/Project/trunk -> C:\dev\projectname
When you switch the workspace bindings you have to manually do a get latest version. for the new folder and then TFS will update the old folder to not downloaded and the new folder to latest.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With