Operations 19 min read

Implementing DevOps with TFS: From Git Migration to Automated Release Management

Over nearly two years, the author chronicles the transition of their development team from using TFS 2010 and manual processes to adopting Git, automated build and release pipelines, QA branch workflows, and Release Management in TFS 2015 Update 2, highlighting the resulting improvements in collaboration, deployment speed, and overall DevOps maturity.

DevOps
DevOps
DevOps
Implementing DevOps with TFS: From Git Migration to Automated Release Management

As a developer, after nearly two years of effort, the main DevOps pipeline based on TFS has been largely implemented. This article reflects on the various experiences along the way.

Before we start, a brief introduction to what TFS (Team Foundation Server) is.

TFS is a Microsoft Application Lifecycle Management (ALM) tool.

Through TFS you can get a full suite of software lifecycle features—from source control, project management, continuous integration, automated deployment, to automated testing; it also has a cloud version called VSTS.

VSTS/TFS = Github + Trello/TeamBition/Tower/Jira/Rally/RTC + QC/TestLink + Jenkins.

TFS is not just a code repository.

Important things are said three times. Using TFS only to store code is like buying a 6000‑yuan iPhone and using it as a 200‑yuan Nokia; it wastes the potential.

This article will discuss the role TFS has played in improving our team's DevOps and the various experiences.

This article will NOT discuss how to configure TFS specifically.

Hope this article can help teams or individuals who are using or considering using TFS.

Chapter 0 – History

When I first joined the company in 2015 as a junior developer, the company was using TFS 2010 with TFVC for source control, Jira for project management, and had no automatic build/release or testing.

As a motivated newcomer in an era where centralized version control like SVN was fading and Git was rising, I was skeptical of TFVC, which is a descendant of SVN.

Moreover we were still using a five‑year‑old TFS 2010… its UI:

It looks outdated and not user‑friendly.

And the contemporary TFS 2015:

Clearly more modern and better UX.

Later we used VSTS (then called Visual Studio Online) with Git for source control, which was not compliant for our company, but it was a temporary solution for a new project.

At the same time we asked management to get a TFS 2015 instance to keep up with the times.

Chapter 1 – Promoting Git

With management’s help we finally obtained our own TFS 2015, migrated the code from VSTS, and started happy coding.

Subsequent projects were gradually migrated to the new TFS server.

Because the new project collections were based on Git, several issues arose:

① How to convince colleagues accustomed to TFVC to use Git;

② How to manage code with Git.

First, we should avoid choosing a tool just because it is popular; we must understand what problem it solves.

I am a BYOD advocate; my company machines are slow, while my personal SSD is fast, and BYOD lets me work flexibly.

Git’s offline commit is a powerful feature for me.

Unlike centralized check‑in policies, I prefer to keep policy enforcement to the pull‑request stage.

Git branches make branching easy.

These reasons led me to choose Git.

Then we had to educate colleagues; one pain point is that people confuse commit and push.

We also enabled pull requests for code review, requiring at least one reviewer besides the author:

Because Git branches are convenient, collaborative development became smoother, each developer working on their own branch.

After each release we create a backup branch based on the release date for hot‑fixes:

Stage summary: introducing Git gave us:

① More convenient collaborative development, each person has their own feature branch;

② Easier creation of backup branches, making hot‑fix handling smoother;

③ Introduction of Pull Request and basic code review.

Chapter 2 – Introducing the First Automated Release

As described in Chapter 0, we originally had no automated release tools; the manual process was to develop, use Visual Studio’s ‘right‑click → Publish’ to generate a package, then commit it to SVN and ask QA to update the test environment.

This process was cumbersome, time‑consuming, error‑prone, and often caused issues such as missing code merges, so automated release became a priority.

The first version of automated release simply automated the VS ‘right‑click → Publish’ step.

We knew VS publish can target a remote server:

If we fill the target location with a shared folder on the server and have permission, VS can publish directly:

In TFS’s Build Solution step we only need to specify the appropriate configuration file to automate this.

However this approach had several problems:

① The target machine must have a shared folder configured;

② The Build Agent must have access permissions to that shared folder;

③ Each deployment rebuilds the code, causing DLL version mismatches across environments.

Thus configuring both the target machine and the Build Agent became cumbersome, especially as we added more agents or servers.

Also, our policy forbids committing DLLs, so local DLL references caused issues during automated release.

Therefore we introduced NuGet as a mandatory package manager; before that NuGet was optional.

Because of automated release, we stopped allowing local DLL references and required all external dependencies to be managed via a NuGet server.

QA also demanded that deployments to the test environment require their approval, not just developer discretion (otherwise I would set up a CI trigger).

We introduced a QA branch.

Only QA members have pull‑request approval rights on the QA branch, as shown:

Once the QA branch is approved, it automatically triggers deployment to the Demo environment; subsequent testing and pre‑release environments also use the QA branch code.

After a trial period, projects with automated release showed far fewer deployment issues, and QA spent less time updating packages.

Stage summary:

① Introduced automated release;

② Introduced a QA branch to clarify the release workflow;

③ Made NuGet the sole method for external DLL management, unifying dependency handling.

Chapter 3 – Optimizing Automated Release

At this time Microsoft released TFS 2015 Update 2; see the update log.

The most important addition was Release Management, previously a separate product, now integrated into TFS.

Also TFS got its own Store for extensions.

My understanding of Release vs Build: Build compiles code into DLLs and stores them; Release copies those DLLs plus configuration to each environment, ensuring identical binaries across environments.

A typical Build step looks like this:

And a typical Release step looks like this:

For details refer to Microsoft documentation for Build for ASP.NET and Deploy to Windows VM.

Our current automated release pipeline looks like this:

Grey boxes mean the environment was not deployed, green means successful, yellow partial success, red failure.

Now we can instantly see which stage the release has reached without asking QA.

During this, I noticed the ‘IIS Web App Deployment’ task in Release has a feature that can replace parameters during deployment (similar to VS Transform).

Previously we excluded web.config from deployment because connection strings differ per environment, so we kept environment‑specific web.config ready and omitted it during publish.

When updating a NuGet package, web.config would change, and we had to write a txt for QA to manually edit the XML, which was painful.

Later ops extracted environment‑specific settings into separate config files, keeping web.config as a deployable file.

I wanted a more automated solution, so I investigated Web Deploy Parameter Files.

By specifying an XML file, Web Deploy can replace any specified configuration files on the target site, not just web.config.

After adoption, developers now publish web.config together, and during deployment the parameters are automatically injected (e.g., connection strings, appSettings).

Thus we no longer need to send txt instructions to QA.

Stage summary:

① Upgraded TFS to gain Release Management and Store support;

② Split automated release into Build and Release steps, creating a more structured pipeline;

③ Through Release we can clearly see the current testing stage;

④ Automated handling of web.config and other deployment configuration.

Big Summary

After all this effort, we have moved from a feudal‑era setup to an industrial‑revolution stage, introducing Git (especially its branching) and automated deployment.

Overall our team has entered an initial modernisation phase.

Future articles will cover code analysis, monitoring integration, .NET Core support, etc., stay tuned.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

ci/cdDevOpsGitTFSAutomated Release
DevOps
Written by

DevOps

Share premium content and events on trends, applications, and practices in development efficiency, AI and related technologies. The IDCF International DevOps Coach Federation trains end‑to‑end development‑efficiency talent, linking high‑performance organizations and individuals to achieve excellence.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.