Introduction

It’s that time again – that time where the development industry has decided for us that what we were using before isn’t good enough anymore and everyone needs to change what they are doing dramatically. This isn’t the first time and it won’t be the last time, so let’s get on with it. However before I begin I just want to say, I resisted writing this article because I felt like using Git was clear enough after a few trials by fire, but I can understand how it is still very jarring for some people. I looked for guides myself when I was getting started and I didn’t like any of the guides I found, I think they are all terrible.

That being said, here are some precursory reminders to learning something new that you don’t really want to learn:

  1. Git uses a very different methodology than TFS does – so understand that it is totally different, just like MVC is different from WebForms. Eventually you learn to like it because it actually is better.
  2. Git is far easier to use than TFS – I know it won’t seem that way at first, but it is. Just be open to learning something new.
  3. In order to make room for Git in the TFS world, the original TFS has been renamed to TFSVC. This way when we refer to TFS, we are talking about the product and not just the technology. Therefore there are now two flavors of TFS source control:
    1. TFS Git – which uses the Git technology
    2. TFS VC – which uses the original Microsoft developed TFS Version Control (hence VC) – formerly known as Source Safe long ago

Differences between Git and TFS VC

There are some blatant differences between Git and TFSVC, but honestly after using it for a while you start to see that it isn’t that drastically different in what it is doing, it is just a different means to the same end. What is totally different is the methodology, but that’s it.

What I am not going to do in this guide

I feel like it is pretty obnoxious to start throwing Git commands in people’s faces when you are trying to explain to them how to use Git. As a veteran TFS VC user myself, I didn’t feel like this was helpful at all and it just added to the frustration of moving over to GIT. Therefore I won’t be doing that, especially since everything you can do with Git commands, you can do with the Visual Studio UI or directly in the TFS web portal. It’s not fair to TFS VC users to strip them of their familiar GUI and try to forcefully replace it with Git commands. Thanks – but no thanks.

Now what I will say though is, eventually you should consider using the Git commands as it just makes life easier – but not in this guide. Learn Git first and get used to it, then use the Git commands. When you are ready, you can read up on that here, but don’t feel obligated to do so yet:

A very basic guide to Git commands

Terminology

I think the largest source of confusion for people making the transition is the terminology, so let’s go through that first.

Where are my Team Projects?

Using TFS VC for such a long time I got used to the following structure:

Server > Collection > Team Project

Well in Git things changed a bit and now your “Team Projects” have been replaced with the notion of a “Repository

Therefore in Git you have:

Server > Collection > Repository > Sub-Repository

Don’t worry about the Sub-Repositories right now, that’s not a mandatory thing, it is just something you can do. I’m honestly not sure if you could do this in TFS VC, but I sure don’t remember it being an option.

Repository versus Team Project

Here is where the fundamental difference between TFS VC and Git are very apparent. TFS VC is server centralized, Git is not. The whole point of Git is that it is decentralized. This means everyone has a copy of the Repository (Team Project) that they are collectively working on. This may seem insane, but there is a lot more to go through before thinking that. Remember keep an open mind.

How do I download the source code?

  1. Almost like you would for TFS VC, just use Visual Studio and look at your “Team Explorer”.
  2. Click on the green plug or select “Manage Connections”
  3. Connect to a server – I know it says Project, but really it’s a TFS server
    1. If you want practice with this, use a visualstudio.com account and use “Azure DevOps” for free. It’s essentially the same thing.
    2. You can practice against GitHub.com as well, but it is a slightly different experience than how TFS does things.
  4. After you connect to your server you need to connect to a Repository (Team Project). However in this case because it is a Repository we have to download it and work on it locally.

This isn’t totally different from how TFS VC operates, but with respect to Git, fundamentally there isn’t a reason for your repository to be “connected” to a server when using Git. This is the difference in experience that I was mentioning above.

Local Git repositories versus what?

When you are working on a repository you will always have a local copy, that’s just how Git works. However, in Visual Studio and the world of the TFS product there is a notion of being connected to the server. This falls outside the dogma of Git, therefore this is strictly a Microsofty thing – don’t think this is normal. This is exactly why, when you use Visual Studio to connect to a non-TFS repository it doesn’t act the same way.

As you can see in the above image, these are real and practical examples.

  • I have a private repository on my visualstudio.com account which uses Azure DevOps (essentially TFS online) which is “connected” to my local repository
    • There are times where the connection between my local repository and the server get lost – this happens it’s not a big deal, just double click on the server connection to re-establish a link.
  • I have two local GitHub repositories which aren’t “connected” because GitHub doesn’t recognize this notion of being connected to a server (for now… because Microsoft bought GitHub on June 04th 2018)

From this point on, let’s refer to a Repository as its accepted shorthand “Repo”.

Why should I keep my Local Git Repo connected to the server?

Honestly you don’t have to. This is merely a convenience feature of TFS, hence this being a Microsofty thing to do. By keeping your local repo connected to the server you:

  • Have access to your Work Items and to some minor capacity your queries in order to find your Work Items.
  • Additionally you can do branch management
  • There are other things, but it isn’t something I am going to credit TFS with, because other GUI Git programs do the same thing which makes it pretty standard, such as reviewing history etc.

Where do I do my work?

There isn’t a concrete definition for how to do this because it all comes down to preferences, best practices and how you and your team handle things already. Just like when people give advice about how to lose weight – it comes down to “Bro-Science” – do what works for you, no one is 100% right about this. Anyhow, here is my bias on how to handle the matter:

Git Flow

Largely this depends on how your repository is being administered and what I mean by this is what branching strategy are you using? I won’t get into this because honestly this is no different from the problems everyone would run into with TFS VC – same problem different technology. Therefore for argument’s sake we are going to say we are using GitFlow (you should really use GitFlow, please consider it):

You should recognize this, it doesn’t matter that it is for Git, it’s the same basic idea you have always seen: How do we organize our code for releases? Well I am not going to go that deep, I just want to get you – the reader – developing. All that other stuff will have to be in a different future article.

Okay, then where should development happen?

Development should happen in the development branch to over simply it, however we know it won’t be that simple. Therefore on to branching!

Branching

I can’t speak for everyone when saying this, but creating branches in TFS VC was a total pain in the ass. Therefore we were always careful to not create branches unnecessarily because it was a painful process. Well congratulations, in Git it is the exact opposite. Everything in Git is about branching – branching is encouraged and there isn’t a time where you aren’t branching. This feels very awkward and strange at first, but trust me it makes more sense once you start doing it.

Key and protected branches

You have three key and protected branches which really should have Branch policies on them in order to protect them. Those branches are:

  1. master
  2. develop
  3. release branches
    1. Understand that release branches are transient and temporary
    2. Branch policies should still be put on a release branch to stop people from “sneaking” items into a release
    3. No one should be developing against a release branch – however that’s a topic for another time

Branch policies and Pull Requests

Without branch policies, you cannot create pull requests. Therefore let’s put this into context and explain what that means in terms a TFS VC user will understand.

  • When branch policies are mentioned just think about it as Team Project settings that prevent developers from working against a key branch directly.
  • The effect of this forces developers to create a pull request which can be thought of as a Gated Check-In.

Therefore to review use these loose comparisons:

  • Git Branch policies are kind of like TFS VC Team Project settings
  • Git Pull Requests are kind of like TFS VC Gated Check-ins

Even if you don’t have policies setup on your key protected branches, let’s pretend that you do in order to start creating your first branch properly

Creating your first branch

Therefore in order to start doing some development, you need to branch off of the “develop” branch. In order to do this, you have two choices:

  1. Do it locally
  2. Do it on the server

There isn’t a preferred method here – each way has its purpose. Therefore consider these two different tools to get the same job done.

Creating branches locally

Eventually, when you get used to using Git – this might actually be your preferred method, but don’t feel obligated to do it this way. I am going to list the steps then explain what it all means.

  1. Perform a fetch on the repository
  2. Perform a pull on the develop branch
  3. Create a new branch from your develop branch
  4. You are ready to work
Explaining that in TFS VC terms
  • Performing a “fetch” isn’t really a thing in TFS VC, but the best way to explain it is to “get latest” without actually downloading any of the changes.
    • You can think of this as a preview of what changes are available on the server.
    • Think of it as “peeking” at the next available item in an iterator, enumerable or queue. Same idea.
    • This is convenient so that you know what is coming and it won’t mess up what you are working on – it gives you a chance to say “no”.
    • It is important to run a “fetch” because Git has a habit of not getting everything on the first go, if you just use a “pull”. Therefore do a “fetch” before a “pull” when you haven’t gotten latest in a long time.
    • The “fetch” command actually does more than just get you new code, it also will pull down the latest available branches on the server for download.
    • Therefore in essence “fetch” can be thought of as keeping you in sync with the server’s metadata.
  • Performing a “pull” can be thought of as “get latest” – that’s pretty much all there is to it. You are getting the latest available code for a branch.
  • Creating a new branch does exactly what it sounds like – you are creating a new branch from your current branch.
    • Understand that whether you are “creating” a branch or “switching” between branches – you are actually doing what is called a “checkout” in Git.
    • Therefore in TFS VC terms, it is fundamentally no different from using a different branch in TFS VC.

Creating branches on the server (remote)

From this point forward let’s refer to the “server” as “remote”. In Git the term “server” isn’t used, it is actually “remote” which basically mean the same thing. The reason from what I have seen is to keep the terminology in alignment with the term “local”. Therefore the following should make sense now:

  • Remote branch – a branch on the central Git server
  • Local branch – a copy of a branch from the central Git server or a branch that you created on your own that the Remote has no knowledge of

When you are working with branches in the TFS portal (or Azure DevOps) branches can be created in a number of ways, however I feel (more Bro-Science) that you should never be doing work without a Work Item to relate your work to. Therefore we are going to use my bias on this to explain how to do this:

  1. Go to your work item, for argument’s sake let’s say you have a Task 123 you are working against.
  2. In the top right of your task body under the heading of “Development” there is literally a link that says “Create a new branch”
    1. Just as a word of caution, make sure your task is saved before doing this.
    2. After the branch is created you will be redirected to the branch’s page.
  3. From the dialog that pops up you should do the following:
    1. Enter a name for your branch. You have the opportunity to put your branch in a “folder” at this moment by using the forward slash character.
      1. Example: tasks/123_exampleBranch
      2. I use this format to show the ticket number and give a short description of what it is for
    2. Make sure that your branch is being branched off of the right repository and branch
    3. Attach any work items to this branch at this time. The current work item is already referenced.
    4. Press the “Create branch” button
  4. Go to Visual Studio
  5. Open up the Team Explorer pane
  6. Click the home icon
  7. Click on “Sync”
  8. Press either “fetch” link – won’t matter which
  9. Click the home icon
  10. Click on “Branches”
  11. Expand “remotes/origin”
  12. Checkout the branch by double clicking on the branch you just created Ex: “tasks/123_exampleBranch”
  13. Done

Working with your branch

What’s nice about Git is that you don’t have to deal with checking out, locking files or any of that stuff. You just do whatever you want (within reason of course). It’s very liberating actually and far less stressful to deal with. Alright let’s say you made your changes and you are ready to get your branch “tasks/123_exampleBranch” merged back into the develop branch on the remote. I am going to explain what happens, then re-explain it in TFS VC terms.

  1. Make your changes. You can make as many or as little as needed. You can “commit” your changes as often as you need or want to – there isn’t a limitation here. It doesn’t affect anyone else because you are working locally!
  2. When you are finished working it is time to “push” your changes. This simply means – put my changes on the server’s copy of my branch. This still won’t affect anyone as long as you aren’t sharing your branch.
  3. Before you proceed to a Pull Request, you should merge the parent branch (develop in this case) back into your branch to avoid introducing any regressions. This is a very critical step because things could have changed since you made your branch. This is important.
Explaining that in TFS VC terms

I can’t explain this exactly in TFS VC terms because fundamentally this is where Git and TFS VC vary greatly, but I will try.

  1. You created a branch in TFS VC which makes a whole separate copy of your files – Git does not do this, the oversimplified explanation is it uses pointers for everything
  2. You you made changes to your files by checking them out – Git doesn’t care what you change and won’t ask
  3. When you are finished making changes you check your files back in which is immediately on the server – Git doesn’t do this at all, your changes are local only via “commit”. Your changes only make it to the server when you perform a “push”.
    1. Git commit can be thought of as the first half of a TFS VC check-in. This is a check-in to your local repo.
    2. Git push can be thought of as the second half of a TFS VC check-in. This is a check-in to your remote repo.
  4. Before you proceed to a Gated Check-In, you should merge the parent branch (develop in this case) back into your branch to avoid introducing any regressions. Same as before.

A closer look at commits – staging changes

I have to pause for a moment to point out a subtlety that Microsoft has kind of screwed up with respect to the dogma of Git. They did another Microsofty thing here that confuses veteran Git users, but this is very familiar to TFS VC veterans. I like this “feature”, if you will, but it does go against Git methodology and it only works inside of Visual Studio that I know of.

When you are performing a commit you may have noticed that you can “stage” your files. In visual studio this is optional, in Git though it is NOT optional. Therefore let’s get into why this is a thing and why you will more than likely need to do this at one point. This is best explained with an example:

  1. You made changes to some code files, like C-Sharp or whatever language you want.
  2. You made changes to some SQL files, from a SQL project or what have you.
  3. It is usually a very good idea to commit these things separately just in case you have to roll back or undo your changes
  4. Therefore you can commit these things separately via staging:
    1. Stage your code changes and commit them – this makes commit A
    2. Stage your sql changes and commit those – this makes commit B

Now just know that if you forget to “stage” your changes, everything you have changed will be committed all together whether you like it or not if you commit by accident. Thanks Microsoft! Not how that is supposed to work – which is why it pisses off Git veterans because they don’t expect this.

Promoting your changes into the parent branch

Git embraces Peer Review of your changes. Hence the existence of the Pull Request. In TFS VC it kind of felt like an afterthought, I know it could be done, but it felt optional kind of.

In order to get your “tasks/123_exampleBranch” branch’s changes into the parent branch which is the develop branch in this case you have to perform a Pull Request which is something you must do via the TFS Portal (or Azure DevOps). The most important two things to highlight here are:

  1. Your changes must be checked into the appropriate branch – be cognizant of this because the Pull Request form won’t automatically know, you must know this information.
  2. Your changes must pass all of the Branch Policies. I can’t predict what those are for you because it is configurable, but at least make sure your changes build.

The whole point of the Pull Request is so that your peers will review your changes and so that when your Pull Request is accepted the merge of your code into the parent branch happens automatically.

Peer review

Your changes will be peer reviewed and can be rejected by your peers which prevents the completion of your Pull Request. You must work with your Peers to resolve their comments and concerns until your changes are 100% accepted and all of the branch policies are met.

Completing a Pull Request

At this point there are a few decisions that should be made about what happens to your branch, some of these decisions have been made by your administrator, but I would like to explain them to you. When you press the complete button at the top left of the Pull Request page you are given the following options:

  1. Complete linked work items after merging
    1. This is a Microsofty thing again because Work Items are a TFS product feature
  2. Delete <your branch name here> after merging
    1. This is a good idea just to keep your remote clean, when you are finished with a branch get rid of it and don’t dare reuse branches!
  3. Squash changes when merging
    1. This option should be chosen for you already. This literally takes all of your commits and combines them into a single commit so that it can be put into your parent branch as just one commit.
Explaining that in TFS VC terms

There isn’t a great comparison here between Git and TFS VC but again I will try to make it clear. When you are finished with your branch in TFS VC you merge it back into its parent, end of story. When you are finished with your branch in Git you have to perform a Pull Request like explained above. Therefore:

Git Pull Requests are kind of like TFS VC Gated Check-ins however the main goal here is that you are merging YOUR branch’s changes back into the parent branch. That’s it.

Conclusion

I know this is a long guide, but I hope it explains Git well enough for a TFS VC user who is new to Git.

Enjoy