It seems I whenever I see TFS mentioned on twitter/HN/Reddit it is usually closely followed by mocking or derisive comments. But all these comments lack any real explanation or reasoning, outside of generally hating on MS, from the author. So as someone who works with, and has worked with for the past 3 or so years, TFS on a daily basis I’d like to add on my two cents on how TFS works and what my pain points are.
Bear in mind I’m not an VCS geek, I’m not going to start talking about how the extensionalist index metabear does not quite model that of the intrinsically 4D nature of time and application architecture. This is just how I get on with it while trying to get shit done.
I’m only going to cover the two parts we use, source control and build management.
TL;DR; It has lots promise but sadly missing features and poorly thought functionality severely hamper it.
Let’s cut the crap, working on a file and checking it in is the same in virtually every VCS. And TFS is not exception here, you work away, see your changes, check them in and if there is a conflict you get a diff. Not rocket science and works well enough.
However, this does quickly breakdown if you want edit files outside of Visual Studio (VS). The problem is files need to be “checked out” before you can make edits. If it didn’t happen while it was checked out it, it didn’t happen. I’ve lost count of the number of times I’ve tweaked an XML file, build file, none cs file and done it in Programmers Notepad only to check in and break the CI build because the tweaks have been missed.
Editing and merging csproj or sln files is a complete and utter nightmare and I’ve never understood why. Let’s face it if you’re using TFS you’re fairly invested in the MS ecosystem so you’re using VS and one of TFS’s big features is integration into VS so why oh why, for the love of God why, can’t TFS parse and merge sln and csproj files? They are MS formats, produced by an MS tool and managed in an MS tool W. T. F.
Merging And Branching
Personally I’ve been completely spoilt by local branching in DVCS (Distributed Version Control System) and I sometimes get lost in what branching means in a more centralised context. In TFS and svn branching can only be done on the server allowing multiple people to work on the same branch. Whereas with DVCS and local branching only you can make edits and commits then when you’re ready to integrate your work with your team you pull the upstream, merge it and push it. So it’s in your best interest to keep the two as close as possible to minimise your own pain.
The more centralised models put the onus on nobody to sync the branch with upstream because somebody, IE not you, will have to do the merge. Many teams will try to manage this through policy to varying degrees of success and lets not forget that it is entirely possible to get into the same mess with DVCS.
For me the secret sauce of branching with DVCS is that it moves the emphasis of the responsibility and management of the branch on to the individual developer. No amount of nifty features or tooling can make up for the fact that a branch that hasn’t been synced with its parent for 3 weeks and has lots of code churn is going to be a nightmare to merge.
So I don’t think it’s fair to pick on TFS over branching, yes it doesn’t support local branching but at the same time that has the same issues of good branching requiring proactive syncing, thought about management and discipline.
One area where TFS has massively improved recently is in history across branch. Pre-2010 there was no easy way to follow the history of an item cross branch but thankfully this has now been added.
Checking Out, Moving Files and IDE integration
For those that don’t know when you do a pull in TFS every file is readonly by default if you want to edit a file you have to go source control explorer, find it and check it out. If you have VS integration turned on (and if you don’t you’re a mentalist) it is all quickly taken care of for you when working inside of VS. There is, of course, an option to make files readable on pull but that only introduces a whole new, more annoying, problem, working out what has actually changed. There is no “Hey TFS, I’ve change some things figure out what’s different and list them as pending changes for this checkin”, I’ll run that by you again if you don’t check it out TFS doesn’t know what has changed. This is complete lunacy and is a significant barrier when trying to get shit done. To be fair, it does have this functionality when your connect goes offline and when coming back online it will look for changes and generally find them. But there is no way to do this from the IDE normally.
Checking out files is a completely moronic concept.
I said earlier that if it wasn’t checked out it didn’t happen, let me amend that to if didn’t happen inside source control explorer with the correct verb then it didn’t happen. This is most frustrating with file moves, recently I restructured one of our main solutions splitting several new projects from one monster. I created the new projects then cut and paste the required files via Solution Explorer with TFS integration enabled, expecting TFS to pick up the moves but it did delete/adds and completely f’ed up the merges for everyone else and the history.
For me all this TFS having to be explicitly told what you’re doing shouldn’t be a problem when working in VS, this should be it’s killer feature. It should be don’t worry just work as normal, TFS is watching and will know what to do but nothing could be further from the truth.
Oh and on moving, you can’t multi select files to move them in source control explorer you either do the whole folder or the files one by one :-/ (I think it’s because “moves” are actually “renames” so it needs to know the filename but WTF)
Shelvesets on the surface seem a pretty nice feature, it allows you save a copy of your current changes without checking them in. They get stored centrally so can move between machines and even users, handy if you want a code review or you want to quickly spike something out then share it without checking it in or branching.
Over time I have found the omission of features deeply frustrating. Shelvesets themselves do not have any history, I find this fustrating because the first time I seen them I thought great, I can make changes and have lots and lots of small checkpoints before checking in the finished bits and it doesn’t matter if they don’t build or cause tests to fail. But nope, shelvesets overwrite each other if they have the same name.
The other use case is using them as a stash, so you’re working away on a feature or a bug and you discover you’re working on the wrong branch or something else high priority comes in so you shelve your current changes. Later you go to unshelve them on another branch so you can finish up, nope can’t do that shelves can’t move cross branch for reasons known only to MS.
Again another should be a killer feature but so widely misses the mark.
I work for an MS shop so we use MSBuild for builds and TFS build is all MSBuild based so it integrates nicely. It can schedule builds, run the CI, the build machine setup is a little clunky but it makes sense. Overall running and managing builds it does a good job. The only major frustration is notifications.
Not only is it really difficult to set up a notification, the UI is horrendous and none obvious, but if someone has setup a notification on your behalf then you can’t delete it, see it or see who created it. So if you want to piss someone off you can setup for them to be notified on every build that is done ever and there is nothing they can do about it. Yes, you can go to the TFS database and remove them but that’s a bit extreme and not many developers have that kind of access.
TFS has so much promise but the combination of idiotic concepts, poor integration and lacklustre features really harms productive. A sign of a good tool should be one that doesn’t get in the way and in this respect TFS fails massively. I would even go as far to say it actively promotes bad VCS habits from individual developers.