Quick disclaimer: This article in no way gives negative ill will towards TFS, anyone that knows me personally knows that for an ALM I truly love TFS and would not give up on it for anything.
So the situation I ran into is probably similar to other development teams. Source control is in Team Foundation Server or TFS. When a developer modifies a files that file is automatically checked out of TFS (as long as they are in online mode).
In some shops there is a rule of not leaving the project file checked out for any length of time. In fact any file that is checked out for a long time is frowned upon. I have never really dealt with this style of restriction and asking around this seems to be either a growing trend or best practice.
Doing what I do best, researching the topic I came across git which lead me to git-tfs.
What is git? It stands for GNU Interactive Tools that was created by Linus Torvalds. Git is a free and open source distributed version control system. A distributed control system is where every clone is a full-fledged repository that contain history and revision tracking. The difference between git and TFS is that there is no dependency of a central server.
Git-tfs is a bi-directional bridge between TFS and a git repository.
Why use git-tfs?
- A developer is no longer in constant communication with TFS
- Developer is basically in constant offline mode
- No file locking
- No TFS checkouts except when pushing changes
- Merges are conducted via Git’s algorithms and merge tools which may or may not be better.
- Check-in history sent to TFS is visible in TFS and workflows can still be maintained.
What does this offer up to a developer?
- The freedom to hold files opened, because the developer will be opening their local git repository.
- Not having to mess around with moving between online/offline mode.
Here is what you need installed (Visual Studio is a given):
- Git Extensions – Great for windows folks, it also does installation and configuration for you. Contains some great links to videos on using Git.
- git-tfs – Git to TFS bridge
- Posh-Git – Git in PowerShell (optional but highly recommended: all my examples will be utilizing PowerShell, if you skip this just replace all references for the PowerShell window with Git Bash)
Once everything is install, run Git Extensions. This runs a self check to verify that git is setup correctly. Once everything is in the green close it out and open up PowerShell, execute ‘git’. You should see something like this:
If you do not see the above something is not setup correctly, let me know if you need any help.
First thing that needs to be done is to create a new git repository that is initialized from a TFS source repository. Run the following command of course replace with the location of your server connection info and projectname.
git tfs clone http://servername:8080/tfs/DefaultCollection $/projectname
Depending on how many check-ins this project has associated with it this could take some time so be patient.
Once this is complete this next step is optional but it does make life easier. Go to the root of your project and create a file .gitignore. This file tells git to ignore any file/folder listed. Add the following lines to the file. (if you are having issues creating this file you can use the new git menu in Visual Studio to edit.gitignore.
#ignore thumbnails created by windows Thumbs.db #Ignore files build by Visual Studio *.obj *.exe *.pdb *.user *.aps *.pch *.vspscc *_i.c *_p.c *.ncb *.suo *.tlb *.tlh *.bak *.cache *.ilk *.log [Bb]in [Dd]ebug*/ *.lib *.sbr obj/ [Rr]elease*/ _ReSharper*/ [Tt]est[Rr]esult*
From here the developer is free to follow two paths. The clone process initialized a local git repository called master.
Option one: (considered best practice) create a clean branch of the master. Work from the branch and when work is completed, push that to the master, re-fetch from TFS, then push changes to the TFS server. To create a branch you can run the following:
git checkout -b BranchToDoWork
Option two: Can cause some problems because you are working off the local master branch. This has the potential to cause problems if the developer is not keeping tabs on his own master repository, then again this option is probably not much different then what developers are use to. Also in my opinion if this is a clone of a TFS project; this is a branch anyways. This is the option I will be showing because it is simple to demonstrate.
Now that this has been explain, once the clone is completed, use PowerShell to navigate to the project folder.
You will now notice that the folder displays the branch. Go ahead and do some work. Go back to your PowerShell window and type in:
The output will look similar to this:
The first number represents how many files are ready to be committed, the second number is modified, and the third number is how many files to delete. If you notice it says “no changes added”. This is because none of your work so far has been committed to the git repository. When the developer is ready to commit the changes locally they can flag them ready to be added by either:
Single File at a time
git add SingleFileName
All files at a time
git add -A
Then commit the changes
git commit -m "check in message"
Now that source is ready to be checked into the Team Foundation Server. Commits do not need to be checked into TFS in a one to one ratio. Multiple git commits can be pushed to TFS at one time. I personally like using the TFS check-in tool because of workflow and ALM stuff. Run the following:
git tfs checkintool
What will happen by default all the commit messages (from the last push) will be rolled up and placed in the comments area. From here the the developer can associate work items and check-in their changes.
If commits are successful all changes will be merged into the master repository.
Now the final step is optional but will assist in minimalizing possible sync issues between the master repository and TFS. I found this suggestion on Jeremy Skinner’s blog. In his suggestion add an alias to the.git config file that looks like this:
[alias] tpull = !git tfs fetch && git rebase tfs/default
From the PowerShell window if you enter git tpull it runs the following commands
git tfs fetch git rebase tfs/default
This will check TFS for any other updates and then (in a very minimal description) resets the master branch if something has been changed on the remote server.