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
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
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
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
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.