Blog - GIT for .NET developers—part one

  • Share
  • Share

GIT for .NET developers

Part one

Stephen Weinrich | November 18, 2016

I’ve been a .NET developer since it was first released by Microsoft in 2002. From the days of Visual SourceSafe and then TFS (Team Foundation Server), source control has been pretty painful. Since the introduction of integrated Git support into the Visual Studio IDE, I've heard .NET developers complain about having to adopt a new source control tool. While Git may be new to the .NET community, it’s been around for over a decade. It’s also the preferred distributed source control choice for the open source community, which Microsoft is now a part of.

In this two-part series, we’ll explore using both the Visual Studio IDE and the GitBash Console.

Assuming you have Visual Studio 2013 or newer, go ahead and install GitBash for Windows—and let’s get started!

Creating a GitHub account and repository

There are many Git repository providers that we use at Slalom: VSO (Visual Studio Online), GitHub, BitBucket, GitLab, etc. For the purposes of this blog post, I’ll be using GitHub.

First, create a free GitHub account. Once you have an account, you can create a new repository here:

Create a new repository screenshot
  • Public vs. private repository: I selected public, because it's free. If you want to control access and protect your source code, you can select private and pay for it.

  • Initialize with a README.md file: I recommend adopting this, since it’ll provide a way for your development team to get instructions on setting up their local environments once they’ve downloaded your code from the repository. This file has its own wiki-style language known as Markdown.

  • Add .gitignore VisualStudio: This file is used to ignore certain files from being committed, such as those in the /bin or /obj folder. These shouldn’t be stored in source control since they’re constantly being recompiled. BitBucket has kindly provided an out-of-the-box template for Visual Studio projects, but feel free to edit and change this file as needed. You can read more about the .gitignore file here.

You now own your own repository hosted in GitHub. Mine looks like the image below:

New GitHug repository screenshot

I’ve highlighted the URL that represents the repository—you’ll use this next to do something in Git called cloning.

Cloning

Cloning is creating an exact copy of the remote repository on your local machine. This is different from how TFS works, because it’s a copy of the entire repository history, not merely a copy of the files from the server. It contains the history of the code and branches currently on the server as well as the files—making it distributed, and enabling you to work offline.

Open up Visual Studio. Select connect under the GitHub tab in the Team Explorer and enter your GitHub credentials to sign in.

GitHub team explorer screenshot

Now it’s time to clone the repository to your local machine. Click on the clone link. Select the repository you’d like to clone and the local directory where you’d like to store the repository files. Once it’s copied successfully, it’ll appear in your Local Git Repositories section of the Team Explorer—Connect window.

GitHub team explorer screenshot

Using Windows Explorer, browse your local repository directory to see the README.md and .gitignore files previously specified. You’ll also notice a hidden ".git" directory. I’d advise not modifying the files in this folder, since they’re used by Git to control the repository.

Creating branches

Branching in Git is different than branching in TFS. In TFS, you branch and then check-in/check-out code from a server branch. Using Git, you’ll do everything on a local branch that you create based on a server branch, and other developers will do the same. There’s a concept of root branches, typically develop and master, often used to represent code still under development and production respectively. I recommend reading more about GitFlow as a potential branching strategy.

There’s a local branch and a remote or server branch (called origin by default). A branch called master under the remote/origin folder is on the GitHub server; the other "master" is on your local machine. Next, we’ll create a develop branch on your local machine and then publish it to the server.

GitHub branches screenshot

Right-click the Repository and select New Local Branch From… Enter develop as the new destination branch name, and select origin/master as the source branch. I’d recommend not checking Track remote branch. This will track changes made to develop and will automatically apply them to master. This is not ideal since we want to control changes, through code reviews, into the master branch. For some reason, Visual Studio will tick this box by default. Coincidentally, if you create a branch from local instead of origin, the check box won’t be there, which is our preference. The problem with creating new branches based on local branches is that they could be stale, so you need to remember to pull or sync before you create a new branch.

GitHub branches screenshot

Now that we have a develop branch on our local machine, we need to publish the branch to the server. Right-click develop and select publish. You’ll then see develop appear under the remotes/origin folder, indicating that it now exists on the server. Whenever you create a new branch locally, you’ll need to publish it before you can push changes to the server.

GitHub branches screenshot

You can now create branches based on existing root branches. If you navigate to your GitHub repository, you’ll see the new develop branch there:

Each development team has a preference for branch naming and branching strategy depending on its project requirements. I recommend GitFlow for most projects, however there are cases where other strategies are better suited. Let’s create another branch that we can do some work in. Let’s call it "feature/12345-create-console-project," and let’s branch from "origin/develop" this time. After publishing this branch your branches window should look like this:

GitHub branches screenshot

Notice that Visual Studio has created a folder called feature and put your branch within that folder. This is only conceptual from a UI point of view but very useful for organizing branches by simply using a clever naming strategy. Other possible names are:

  • bug/12345-some-bug-name
  • story/12345-some-story-name
  • task/12345-some-task-name

Or something like this will keep branches grouped under a feature number:

  • 12345/story/67890-some-story-name
  • 12345/task/67890-some-task-name
  • 12345/bug/67890-some-bug-name

The number used is often a TFS/VSO Work Item Number, a JIRA Issue Number, or the ID of whatever system you’re using to manage developer tasks. Do not create branches with your user names in them, for example:

  • stephens-branch
  • user/stephenw
  • stephenweinrich-branch

Naming branches with user names implies that your intention is to reuse this branch for multiple changes required by the system. This is the TFS way of thinking and should not be applied to a Git repository. Each change to the system warrants the creation of its own branch, since it’s linked to a feature/story/task/bug. Once the code has been merged, the assumption is that the branch can be deleted and shouldn’t be reused.

If you take a look at your directory in Windows Explorer, you’ll see the same files we saw before when we only had a master branch. We have subsequently created two new branches, develop and feature/12345-create-console-project. As a .Net Developer using TFS, I’m used to seeing multiple copies per branch in my directory. This isn’t how Git works. The directory will contain the files for the branch that you’re currently working on, highlighted in bold in your branch window. In my case, it’s feature/12345-create-console-project. You can switch branches by double-clicking on them. Okay, enough about branches—let’s write some code.

Committing code

In TFS, you “check-in” code changes or keep them on a shelve-set. In Git, you commit work and it’ll then compare branches based on your—and other developers’—commits.

Create a new Console Project called HelloSlalom.proj. Create it into the directory where your repository is stored on our local machine. Put some code in the Program.cs, compile, and click on the Team Explorer—Changes window.

Github new project window screenshot
GitHub branches screenshot
GitHub branches screenshot

You can see a list of changed files that’ll be committed to your local branch.

Notice that other files like /bin /obj aren’t there. This is because of the .gitignore file we added earlier. To view what Git will ignore, select Team Explorer—Settings and then Repository Settings. Click Edit to see a list of all the directories/files that will be ignored when committing code.

GitHub repository settings screenshot

To commit changes, select Changes from the Team Explorer window, and enter a commit message. This should be a description of the commit you’re currently busy with. You can do as many commits as you like on your branch since they serve as a checkpoint of code on your local machine. Click the Commit button. There are other options if you click on the down arrow in the drop list but let’s simply Commit the code to our local repository for now. VS will notify you of the success and give you a generated commit hash number to represent your commit. Next, we’ll push/sync our changes to the server. If you’re using TFS or VSO (Visual Studio Online) you can put a number and the work item number to associate this commit with a specific work item. This is useful when generating release notes.

Github synchronization screenshot

Push vs pull vs fetch (aka sync)

Let’s get our Git terminology correct first:

  • Push: Copies all pending commits from my local machine to the server for the branch that I’m working on. In our case, we only did one commit above for the feature/12345-create-console-project branch.

  • Pull: Copies and commits from the server branch down to my local branch. In our case, we have no commits on our server branch yet.

  • Fetch: Fetches information about any new branches that have been created on the server. In our case, we have all the branches since we’re the only ones working in the repository at the moment. If another developer had created and published a branch, fetch would get the details about that branch and make you aware of it, if you needed to use it.

  • Sync: Sync is something Microsoft came up with. The sync keyword does not exist in Git. It performs multiple Git command—namely, fetch, pull, and then push, for your convenience. If we wanted to get our changes onto the server branch, we could select either push or sync, and both would achieve the same objective for us.

Do this, and then go to GitHub and take a look at your feature branch to see the new files on the server:

Github new files screenshot

Conclusion

That’s it for part one! In part two, we’ll cover:

  • Pull requests
  • Merge conflicts
  • Using the console
  • Useful GitBash commands
Computer screen with lines of code

Looking for more engineering tips?

Our engineers have a whole lot to say about custom software. They’re in the trenches every day, building, breaking, re-building, and sharing their hard-won wisdom along the way. Find their latest and greatest discoveries on Slalom’s new software engineering blog.

Read our engineering blog
Slalom Consulting Stephen Weinrich

Stephen Weinrich is a solution principal in Slalom’s Chicago office. He’s been delivering software and building teams for over 16 years, and is a Microsoft certified professional, agile evangelist, and novice blog writer. Connect with him on LinkedIn.

            

Start a conversation

What’s on your mind? Let’s explore the possibilities.