This is your brain. This is your brain on computers.

Using Git with Visual Studio 2019: The Ultimate Guide

We’ve written extensively in previous articles about the non-negotiable importance of learning source control to become a software engineer and the most popular tool to accomplish it: Git. Git’s command line has, for lack of a better way of describing it, evolved into somewhat of a conflicting journey. If you’re looking for a better experience to manage your Git repositories, this guide introduces you to using Git with Visual Studio 2019.

Many developers prefer having the ability to manage repositories inline with the development environment to reduce having to context switch between applications. The downside to this is that you lose the flexibility and customization of the command line. We suggest you start with our extensive guide to Git and follow that up with this guide so that you know how things are working under the hood.

And hey, if things start going haywire, you’ll know how to use the backup method!

Install Git & Learn Git

Git works natively on Windows, Mac, and Linux. When using Windows, you’ll most likely be using the tools included in the Git for Windows initiative (Git BASH, Git GUI, and Git Shell Integration). Even though Git is completely cross platform, Visual Studio 2019 only works on Windows.

To get started, go to the download Git page or directly to the download link for Windows since you’re stuck on Windows with Visual Studio.

Don’t know how to use Git? Take a look at our Getting Started with Git guide so that you’re set up for success and ready to contribute to projects with confidence.

Install Visual Studio 2019

Microsoft sometimes has weird ways of naming their products (Azure DevOps, we’re looking at you). There was a period of time when everything was named with the Visual Studio prefix. That said, don’t confuse Visual Studio 2019 with Visual Studio Code. This guide only uses Visual Studio 2019.

Let’s get started.

Download Visual Studio 2019 Community Edition (free). Read our pricing guide for more detailed comparisons between editions. We suggest the Community Edition because you won’t need any of the features offered by the pricier (and they can be pricey) tiers.

Browser window showing where to click to download Visual Studio 2019 community edition.
Visual Studio 2019 Community Edition (not to be confused with Visual Studio Code).

Microsoft recently overhauled the installation process. It’s much, much better than it used to be, so let’s all take a moment of silence to appreciate that.

Anyway, you’re not going to need the thousands of options that are available to you during the initial installation process. This guide only uses the “.NET Core cross-platform development” group and its required dependencies. Feel free to opt in to anything else you think looks interesting but be aware that you will have to download everything. Some of these options can increase the download size by 5+ GB.

Visual Studio installer UI showing to install only .NET Core tooling.
Select what you want but beware the download sizes.

Let the installer do its thing. Sit back, relax, and wait for the magic. While it’s downloading, you can check out our article on 5 Essential Visual Studio Extensions. Used properly, extensions have the potential to boost your productivity and development efficiency.

Create New Git Repository

You’ve got Visual Studio, and you’re ready to roll. If you want to know how the Visual Studio Git UI is interacting with Git under the hood, read our introduction to Git to learn the basics of the command line.

Visual Studio tries to be helpful on launch, but sometimes jumps the gun. In this case, we don’t want to create any projects to start. Instead, we want to create a new repository, but that’s hidden behind the tiny link in the bottom right: “Continue without code.” Click it.

Visual Studio UI showing where to click to skip project creation and create a Git repo first.
Skip project creation since we want a repository first.

To create a new repository:

  1. Click File –> New –> Repository…
  2. The Team Explorer opens on the right
  3. Pick the folder that you want to create the repository in

This is equivalent to running git init from the command line.

Visual Studio UI showing where to create a new Git repository.
Create and confirm where the repository will live.

Create Project In New Git Repository

The repository is ready to go, but it’s empty. Confirm that the repository now shows in the “Local Git Repositories” section of the Team Explorer.

Initiate the Project Creation Wizard by clicking File –> New –> Project. Yes, there are keyboard shortcuts to do this, but they’re not very convenient. You can remap them, but really how often are you going to be creating new projects to justify a handy shortcut?

Visual Studio UI showing where to create a new project.
Confirm successful repository creation. Initiate new project wizard.

There are definitely a lot of project templates to sift through. If you selected more installation options in the first steps of this guide, you’ll be absolutely swimming in them.

Search for “console” to filter down to just console applications. Select “C# Console App (.NET Core)” to create a new console application based on whatever version of .NET Core SDK was installed with Visual Studio 2019. Note that there are templates for other languages (VB and F#) that aren’t relevant to this tutorial.

Click Next.

Visual Studio UI showing where to create a new .NET Core console application.
Create a new .NET Core Console Application.

Enter your project name, select the folder location in which you initialized the Git repository from previous steps. If you get this wrong, you won’t be able to follow along with the rest of the guide.

Click create, and you’re good to go. Your solution, project file, and template classes will be created and placed in your repository folders.

Visual Studio UI showing how to make a new project with caveats.

Commit New Project to Git

Visual Studio has a “Team Explorer” docked sidebar (you can drag it to move it around) which enables you to manage your local Git repository and attached remotes.

Change the Team Explorer section drop down to “Changes” so that you can view changes on your active branch (which is the master branch at the moment).

Even though your project has been added to your local repository folder, you haven’t yet committed those changes. Files that Git recognizes as new are not tracked by default and require you to explicitly add the files to be tracked. If you don’t see any changes listed here, go back to the project creation step and make sure that you created the project in the same folder as the Git repository.

Visual Studio UI showing where to see Git repository code changes.
Use Team Explorer to manage your local and remote repository contributions.

The Changes window in the Team Explorer tab breaks down changes in two ways: “Changes” and “Staged Changes”.

  • Changes is a list of pending file changes that you haven’t acted on. That is, you haven’t run git add on those files to stage them for a commit.
  • Staged Changes is a list of files that have been added to Git’s staged tracking list to be committed. In this step, Visual Studio’s repository creation wizard has automatically staged .gitattributes and .gitignore files based on built in templates.

Specifically, the .gitignore file was sourced from the GitHub gitignore repository.

Visual Studio UI showing where to see staged and pending Git changes.
Staged Changes and “Regular” Changes are split in the Visual Studio UI.

Click the + to stage all changes. In this case, staging everything is fine, but in the real world, you might want to pick and choose exactly which changes to stage. It’s common for developers to make local changes specifically for debugging or testing purposes without the intention of committing those to the repository.

Do yourself and your team a favor by always double checking your changes prior to staging and definitely prior to commitment.

Visual Studuio UI showing how to stage changes.
Confirm your changes prior to staging.

The Team Explorer UI will update with all changes in the Staged Changes section. Confirm that these are as you expect prior to commitment.

If anything looks wrong at this step, you can Unstage by right clicking the file and selecting “Unstage”.

Visual Studio UI showing how to confirm changes are ready to be committed.
Double check staged changes prior to commitment.

Good commits have good commit messages. Good commit messages aren’t too short and nor too long. That’s vague, but the point is that you should be descriptive enough for those who will come after you but without requiring the reader to struggle to the end.

You have three options here:

  • Commit Staged to commit staged changes to the local repository
  • Commit Staged and Push to commit staged changes to the local repository and push to a remote repository (like GitHub or Bitbucket)
  • Commit Staged and Sync to commit staged changes to the local repository, pull changes from a remote repository, and then push your changes to that remote repository

We only care about the first one for this guide because we have no remote repositories setup.

Visual Studio UI showing how to commit to local Git repository.
Write a good commit message and commit to the local repository.

At this point the project is committed to Git and enshrined in the history forever. Let’s work on incremental changes now.

Commit a Change to Git

Any time you add or change a file to the tracked repository, the Visual Studio Team Explorer will automatically detect and display the changes in the Changes tab.

Add a line to the Program.cs file and watch as the change displays automatically.

Visual Studio UI showing how to make a change and have Git recognize it.
Changes are automatically detected and displayed.

Before you commit stage and commit changes, always check to make sure the changes are what you expected. Long development sessions can leave behind unwanted comments and code that you intended to remove prior to commitment.

Right click the file or folder that changed and click “Compare with Unmodified…” to see what changes are pending to be staged or committed.

Use the comparison tool to confirm your changes.

The previously chosen option will launch the Visual Studio Diff Viewer, which displays changes between the HEAD (left, unmodified state of your branch) and the current state (right, pending changes that haven’t yet been committed).

Red lines on the left indicate the previous state. Green lines on the right indicate the current state.

Always confirm that these changes are exactly as you expect.

Double check your changes prior to commitment.

If everything is as expected, just like before, click the + to stage the changes. Enter the commit message (a good one). Click “Commit Staged” to commit to the local repository.

Visual Studio UI showing how to stage and commit a change to local Git repository.
Stage, message, commit is a common workflow.

We encourage all developers to commit early and commit often. Reduce your risk and keep your coworkers sane by maintaining small and frequent changes.

Create and Commit to a Local Branch

As we previously wrote about in 5 Essential Things Every Programmer Should Know, branching is critical to your success, your team’s success, and ultimately your project’s success.

Without the ability to create independent branches of code, team members would be conflicting with each other every time a developer made a commit. Since we also advocate for committing early and committing often, such conflicts would be an immediate deal breaker.

Change the Team Explorer section drop down to “Branches” so that you can view all branches in the local repository.

Visual Studio UI showing how to switch to Git "branches" view.
View branches using the Branches tab in Team Explorer.

The only branch in a new repository is the default branch known as master. Until now, all changes have been committed against that branch.

Right click the master branch, click “New Local Branch From…” to begin creating a branch based on the current state of master.

Visual Studio UI showing how to create a new local branch.
For new repositories, only master will exist as a branch source.

The new branch UI will display in the Team Explorer. Name the new branch, confirm that you are branching from master, and select to checkout the branch so that you don’t have to do that manually after creation. It’s just an option for convenience.

Branch naming is a hot topic and can invoke a lot of opinions. One common naming convention is found in the Gitflow Workflow.

  • feature/ prefix indicates that work committed to the branch represents changes for a new feature. Example: feature/add-new-questions-to-ui.
  • bugfix/ prefix indicates that work committed to the branch represents changes for a bug fix. Example: bugfix/fix-broken-login.
  • hotfix/ prefix indicates the branch will have an escalated release path because of critical fixes included on it. Example: hotfix/2020-14-02-fix-broken-login.
  • release/ prefix indicates a standard release branch which includes tested and ready-to-go features an fixes. Example: release/2020-14-02-new-login-process.

Ultimately the naming convention is up to you and your team to decide. Whatever works best for your flow is fine. Just make sure the names make sense.

Visual Studio UI showing how to name and create a branch.
Good naming conventions for branches helps productivity.

Confirm the branch was created and that it is now the active branch (indicated by bold lettering) in the Branches tab of Team Explorer.

If you didn’t click to checkout the branch upon creation, you’ll have to double-click the branch now to switch to it.

Visual Studio UI showing how to confirm new branch creation.
The Branches tab lets you view and manage all branches in the repository.

After confirming that the new branch is the active branch, it’s time to add some changes and commit to that branch.

Just like in the previous sections, add a new line to Program.cs. You should see changes automatically detected and displayed in the Changes tab.

Again, just like before, use your new skills to confirm your changes, stage those changes, enter a good commit message, and then commit the changes to the new branch.

Visual Studio UI showing how to make changes and commit on a branch.
Committing to a new branch is the same process as committing to master.

There is no difference in the process of committing to a separate branch. In fact, master is considered a branch as well, so the process is exactly the same.

But how do we get our changes back to the master branch so that other coworkers can use our changes? Surely we don’t want our changes isolated in a separate branch forever.

Merge a Branch Into Master

Branches are nearly useless if kept in isolation forever. Team members would be working on features that never get merged together. The application would then have its code split across a ton of different branches!

Branching in Git works by merging from a source branch into an active branch. For example, if you want to merge changes from a feature branch into the master branch, you need to checkout the master branch to make it active and then select the feature branch as the source. You are essentially “pulling” changes from a branch into the active branch.

In the Branches tab of Team Explorer, you can double-click the master branch or right click then “Checkout” to switch to that branch.

Visual Studio UI showing how to checkout a branch.
Double-click the branch to check it out.

Confirm that you successfully checked out the master branch. Right click it, then select “Merge From…” to begin the process of merging into the active master branch.

Visual Studio UI showing how to merge from a branch.
Always merge from a source into the active branch.

The Team Explorer UI will update to allow you to select the source branch (merge from) and confirm the destination branch (master).

Select the feature branch created in the previous sections as the branch to merge from. Check to commit changes after merging. If you don’t check this, you will need to take an extra step to manually commit the merged changes. This is just a convenience option.

Finally, click Merge to complete the operation.

Visual Studio UI showing how to select a branch to merge.
Confirm everything is OK before clicking Merge. It’s difficult to unwind this.

If the merge operation was clean (no conflicts, see below), then you’re good to go. You should still be on the master branch and see the changes from your feature branch available to you.

Good practice dictates a process of branching early, branching often, committing early, and committing often. All of that combined reduces your risk, keeps your changes isolated from massive conflicts, allows you to test in isolation, and keeps your product delivery cycles unblocked.

Resolve Merge Conflicts

This is the part about source control that everyone hates. But it doesn’t have to be insurmountable. Good branching and commit cadence can reduce the size of conflicts.

When multiple people are working on the same lines of the same files in different branches, at some point there will be a collision. That’s because there are sometimes new features and fixes that may overlap with code that was changed by someone else on a different branch.

So what if you add another Console.WriteLine statement to Program.cs on one branch, and your coworker also adds a Console.WriteLine statement on the same line in Program.cs on a different branch? There will be a conflict.

When this happens (it’s a matter of when, not if), the Branches tab in Team Explorer will popup a warning indicating that the merge cannot be automatically completed because manual intervention is required to resolve a conflict.

Either Abort the merge (not recommended unless you have no idea how to resolve the issue) or click the Conflicts link to display which files are in conflict.

In the Conflicts list, select a file in conflict to display resolution options.

  • Merge button will open the diff editor to manually resolve conflicting lines
  • Diff link will show differences between the files for visibility
  • Take Source will ignore changes on the active branch and overwrite with changes on the incoming source branch
  • Keep Target will ignore changes on the source branch and overwrite with changes on the active branch

Click Merge to begin the manual merge resolution editor.

Visual Studio UI showing how to confirm merge conflicts.
Visual Studio UI showing how to choose a file to resolve merge conflicts.

In the diff editor, you will see three windows.

  • Source (left) viewer will show the changes made on the incoming source branch
  • Target (right) viewer will show the changes made on the target active branch
  • Result (bottom) viewer shows what the merge will look like depending on the resolution decisions

Select the highlighted-in-red conflicting line that you want to resolve. At the top toolbar, click the “Take Left” or “Take Right” icons to indicate which change you want to take.

This step might require you to discuss changes with a coworker if you are merging someone else’s changes into your branch. Depending on the decided upon resolution, you may even end up taking both changes!

Visual Studio UI showing how to decide and take left or right merge changes.
Take the left, right, or both changes to resolve the conflict.

Check the bottom window to see what the resulting file will look like after you decided which changes to take.

If everything looks OK, click “Accept Merge” in the upper left to confirm that the file merge conflict has been resolved. If you skip this step, the merge operation on the file will still be marked as pending and in conflict.

Visual Studio UI showing how to confirm and accept merge resolution.
Confirm changes in the bottom window before accepting the merge.

If you selected to commit after merge in the previous step, then the merge conflict has been resolved and automatically committed. Otherwise you’ll need to go back and complete the merge operation as appropriate.

View File Commit History

You will inevitably need to check the history of a file to determine who changed what or where something went wrong. It’s extremely common to need to refer to previous commits for the purposes of debugging or reverting.

Right clicking any file in the Solution Explorer shows an option to View History.

Visual Studio UI showing how to view file history.
Right click –> View History to view file history in Git.

In the file history viewer, you’ll see a list of commits, authors, dates, and commit messages. Use this window to give yourself some context about how the file got to its current state.

Visual Studio UI showing how to view commit history for file.
Use the file history viewer to view all commits in the history.

Right clicking a commit will reveal options:

  • Open to view what the file looked like on that commit
  • View Commit Details to view what the full context of the commit was beyond just this file
  • Compare with Previous… displays a diff between the commit and the immediately preceding commit
  • Blame (Annotate) will show a breakdown of the file per line to show who last altered that line

Click to Compare with Previous to open the diff viewer.

Visual Studio UI showing how to compare commit changes from history.
Right click to view options for a commit in the history.

At this point, you’ll see the diff viewer popup to reveal differences between two commits. The viewer looks the same as it did previously in the “Compare to Unmodified” steps earlier in this article.

Set Up Remote Repositories

While it’s great that you’re now maintaining your code in Git repositories, the problem is that they’re only local. By taking advantage of remote repository services like GitHub, Bitbucket, and Azure DevOps, you can maintain backups and allow others to contribute.

Connect to GitHub

We are strong advocates of using GitHub to build up a public portfolio of your work to support your job and team search adventures.

To connect your repository to GitHub, change the Team Explorer window to “Sync”. For some reason, Visual Studio will display this tab as “Push”. Click “Publish to GitHub” to initiate the login process using your GitHub credentials. Don’t have any? Don’t worry, GitHub is free!

Visual Studio UI showing how to initiate publishing to a remote repository
Publish to either GitHub, Azure DevOps, or other remotes.

As stated just now, login or sign up to GitHub.

Visual Studio UI showing how to sign in to GitHub
Login or signup to GitHub.

If the login process is successful, the UI will update to include your account profile and username. Plus, it automatically fills in the repository name based on whatever you named it locally. You don’t have to have the same name, but it helps for clarity to be consistent.

Enter a name and a description then click “Publish”. We don’t suggest making this a private repository as discussed in our guide to building a portfolio on GitHub.

Visual Studio UI showing how to connect to a remote repository
Name and describe your repository as you want it to appear on GitHub.

And finally, if the remote repository creation was successful, you should see a success message. You can double confirm by checking the Branches tab in Team Explorer to see that a new master branch in the remotes/origin remote repository was created and available now in your local repository.

Visual Studio UI showing how to confirm remote branch
Confirm remotes were added in the branches tab.

Connect to Other Remotes

The process is largely the same for non-GitHub repositories. Instead of clicking “Publish to GitHub” in the first step, click “Publish to Git repo” at the bottom.

When prompted, enter the remote URL (usually ends with a .git extension) to push your changes to. You may be prompted for credentials if pushing to a secured system.

Visual Studio UI showing how to initiate publishing to a remote repository
You can also publish to any remote repository that supports Git.

Push & Pull Changes

What good is connecting your repositories if you don’t know how to push your changes and pull your team’s changes? Fortunately, Visual Studio makes that really easy.

Change to the “Sync” tab in Team Explorer to see the incoming and outgoing commits sections.

Incoming commits are those that you are expected to pull in to your local repository to reconcile against other contributor’s changes. Click the “Pull” link to initiate pulling those changes.

Outgoing commits are those that you have committed locally but don’t yet exist on the equivalent remote branch. If you have commits that meet these criteria, you’ll see a list of them in this section. Confirm and click “Push” to push those changes to the remote repository.

Visual Studio UI showing how to push and pull changes
Push and pull remote changes through the synchronization tab.

Quick Note: if you see an error complaining about not having a matching remote branch when trying to push, that usually means you don’t have any commits in your local repository to push. This is because Git doesn’t create the master branch until you’ve committed at least one time so there are no branches against which Visual Studio can match and push.

Clone Remote Repository

Sometimes you don’t have a local repository to push and instead want to pull an existing repository down locally to begin contributing to it. That’s when you have to clone.

Unfortunately, Visual Studio doesn’t make finding this option very intuitive. Click the little green plug at the top of the Team Explorer window to switch to the Connections tab. We have no idea why this tab is hidden from the normal tab selector drop down.

Under the Local Git Repositories section, click the Clone link to start the process. Enter the URL of the remote repository and where you’d like the clone to end up on your local disk. By default, the clone process will also clone submodules. Don’t uncheck that unless you explicitly know you don’t need it.

Finally, click the Clone button to download and clone the repository to a matching local repository. This process will create the linked remote automatically for you, and you won’t need to go through the previous process of connecting.

Visual Studio UI showing how to clone a remote repository
Clone a remote repository in the connections tab.
Justin Skiles

Justin Skiles

Justin has been developing enterprise application software for over 10 years primarily using Microsoft stacks, Azure, and various open source tools. He has most recently been trying his best as a Manager and Director of Software Engineering in the health care industry.

Share the Knowledge

Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on facebook
Share on twitter
Share on linkedin
Share on pinterest

Follow our updates



Keep Exploring. Choose Your Path.