Azure DevOps Server 2019 is here!

Azure DevOps Server 2019 (the successor of #TFS) is available now! I can assist in upgrading from any TFS version or we can migrate your data to @AzureDevOps in the #cloud. Let us know @DeltaNBV ! #DrivingDevOps

“Azure DevOps Server 2019 is available now if you want to self-host on-premises. Time to plan your TFS upgrades to get all the latest bits. To learn more see:

I just upgraded my existing 2019 RC to the final product version without any problems…next, next, finish…Cool!

Team Foundation Server Security Updates – Microsoft DevOps Blog

For everybody who is on TFS 2017 or 2018.

“Today, we are releasing updates for a cross site scripting (XSS) vulnerability and an issue where in some instances task groups may incorrectly show variables that are marked as secret. Team Foundation Server 2017 and 2018 are impacted. We have released patches for TFS 2017 Update 3.1 and TFS 2018 Update 1.2. We have also released TFS 2018 Update 3.2, which is a full install that includes these fixes.”

If you need help or looking for advice, please contact me.

Source: Team Foundation Server Security Updates – Microsoft DevOps Blog

Consolidating TFVC repositories to Azure DevOps Git

During the past months I have been working on a project for a client which had a main goal, that consisted of consolidating a lot of old TFVC repositories from different old and new TFS and VSTS versions. When I finished the project, the client had only one Azure DevOps environment with only Git repositories. In this article I would like to share my approach.

TFS2008 and TFS2013

The oldest repositories were TFVC in either TFS2008 or TFS2013 and had to be converted to Git repositories. In Azure DevOps you can import TFVC repositories into Git but there are some limitations in size and days of history (changesets). So, I searched the web for some other solutions and came across some older tools and projects that could help me import repositories into Git.

The problem here is that these toolseither didn’t support the older TFS and TFVC versions anymore or simply didn’t work that great due to complex branch architecture in all the repositories. Eventually I used the well-known tool git-tfs:

So, no problem, you would think.Wrong! The support for TFS2008 was dropped in some version of the tool simply because the underlying architecture of TFS had changed a lot, and it was not possible to be backwards compatible anymore, and besides: who still uses TFS2008 these days,right?! Luckily all the older versions are kept as a reference and are downloadable from the GitHub page, so I downloaded the “latest” version which still had the TFS2008 assemblies and support.

As the documentation stated I had to install git-tfs, and I did so by using Chocolatey. This created a folder on my PC in C:\tools\gittfs. The install also added a PATH entry to my computer environment variable so the command “git tfs” could be used from any command or PowerShell prompt.

I created a simple PowerShell script that I executed for every repository, which created a new Git repository in Azure DevOps:

//Create an empty folder to put the source files in from TFVC
Remove-Item –path c:\temp –recurse -force
mkdir c:\temp

//Do the actual “clone” of the old TFVC repository path
cd c:\temp
git tfs clone “http://teamserverURL:8080” "$/COMPLETE_PATH_TO_SOURCEFOLDER"

//Upload the new Git repository to Azure DevOps
git remote add origin https://AZURE_DEVOPS_URL/PROJECTNAME/_git/REPONAME
git push -u origin --all

This was one hurdle I took. I converted a lot of repositories from TFVC to Git. But with one thing in mind: I didn’t include all the branches created in TFVC. I only included one direct “path” from the source repository. In this case not a big problem, but something to keep in mind.

I did something similar for the TFS2013, but first I had to use a newer version of the git-tfs tool. So, I changed the path of the previously used older C:\gittfs to C:\gitstfs_OLD because maybe I had to use the old one again if something went wrong along the way. And it did! So, I was happy to be able to switch between the old version of the tool and the newer one.

For TFS2013 repositories I use a similar script but with some small changes:

//Create an empty folder to put the source files in from TFVC
Remove-Item –path c:\temp –recurse -force
mkdir c:\temp

//Do the actual “clone” of the old TFVC repository of a specific branch
mkdir c:\temp\TFS2013
cd c:\temp\TFS2013
git tfs clone "http://teamserverURL:8080/tfs/COLLECTIONNAME" "$/COMPLETE_PATH_TO_SOURCEFOLDER" .

//Upload the new Git repository to Azure DevOps
git remote add origin https://AZURE_DEVOPS_URL/PROJECTNAME/_git/REPONAME
git push -u origin --all

Existing Azure DevOps Git repositories

Besides the old TFS2008 and TFS2013 repositories the organization was already using Azure DevOps mainly for work item management and some building and releasing of newer software products.

With the existing import functionality within Azure DevOps of importing Git repositories without limitations it was easy to “move” the repositories, with complete history and branches, from different projects to the one big project with all the new and old repositories together, existing side by side. This was a side goal to get all the repositories in one Azure DevOps project to be able to get some trace-ability between code changes and work items.

Combining Git repositories

The last step involved combining some Git repositories into new ones, because the number of repositories was to big to handle, and some code needed to be shared between products. After making a list of repositories which should be combined, which was a very hard task, I created the following script to combine two (or more) repositories into one new one.

//Create an empty folder to create a new repository in
Remove-Item –path c:\temp –recurse -force
mkdir c:\temp
cd c:\temp
mkdir c:\temp\NEWrepoNAME
cd c:\temp\NEWrepoNAME

//Initialize a new Git repository and do an initial commit because else you cannot //merge some other repository files into it, which will be done in the next step
git init
dir > deleteme.txt
git add .
git commit -m “Initial dummy commit”
git rm .\deleteme.txt
git commit -m “Clean up initial file”

//Clone the first old repository and move to a subfolder in the new repository
git remote add -f repoNAME1 https://AzuerDevOpsURL/PROJECTNAME/git/repoNAME1git merge repoNAME1/master --allow-unrelated-histories
mkdir repoNAME1_Migrateddir –exclude repoNAME1_Migrated | %{git mv $.Name repoNAME1_Migrated}
git commit -m “Move repoNAME1 files into subdir”
git remote remove repoNAME1

//Clone the second old repository and move into subfolder in the new repository
git remote add -f repoNAME2 https://AzuerDevOpsURL/PROJECTNAME/git/repoNAME2git merge repoNAME2/master --allow-unrelated-histories
mkdir repoNAME2_Migrateddir –exclude repoNAME2_Migrated, repoNAME1_Migrated | %{git mv $.Name repoNAME2_Migrated}
git commit -m “Move repoNAME2 files into subdir”
git remote remove repoNAME2

Optionally: manually insert a .gitignore file in de root folder
Optionally: Rename migrated subfolders to original folder names

//Do the commit with some sensible comment
git add .
git commit -m “Combined repoNAME1 and repoNAME2 into NEWrepoNAME”

//Add an origin to the newly created combined repository and push changes
git remote add origin https://AzuerDevOpsURL/PROJECTNAME/_git/NEWrepoNAME
git push -u origin --all

Things to keep in mind here:

  • The new repository NEWrepoNAME needs to be created first, and be empty, in Azure DevOps.
  • We move the old repositories into subfolders of the new repository.
  • We do a merge of two (or more) repositories, therefore history viewing is more complex. An extra click is needed to view the history before the rename/move into subfolder action.
  • With the second (and third and fourth) repository you want to merge into the new one, you must exclude all the previous ones when moving to a subfolder.
  • We use different names (repoName2_Migrated) for the subfolders because if in the folder a child folder with the same name exists (in a lot of cases it will!) the moving of files will not move all the right files. The subfolder names can be renamed, after the move, to the original folder names again.
  • Don’t forget to delete the original two or more repositories you combined to prevent users making changes in the “old” repositories.

Feel free to contact me if this article was helpful of if you have questions or remarks.

%d bloggers like this: