In the previous four parts
of this article (start with Part I here), I covered the theory behind branching and the three main patterns that use in our projects. The only detail to wrap up is how to share common library code between projects. We do this with a combination of build events and branching. Note that this method only works if both projects are in the same collection. You can't branch between two projects if they are in separate collections. So plan accordingly.
Sharing Common Code
In order to share common code, we need to take care of a few preliminaries first. The common library project needs to contain a "Deploy" folder that contains the final binary assembly. This assembly will be stored in the TFS source control repository. We'll make use of pre-build and post-build events to help automate the process of keeping this assembly up-to-date. Then, each End-User project will have a "Lib" folder. When a project needs a common assembly, we will branch from the "Deploy" folder of a particular release branch into the "Lib" folder of the referencing project. TFS keeps track of all this in the file history, so we can see who branched what assembly to what project and when. This is also handy when something needs to be rolled back.
This is how the folder structure looks for the common library, showing the "Deploy" folder:
Once the folder structure is set up, the build events need to be set up. Right-click on the project and choose "Properties". In the Properties window, select the "Build Events" tab. In the "Post-build event command line:" box, enter the following:
copy /Y "$(TargetPath)" "$(SolutionDir)Deploy"
It looks like this:
Make sure you have the "Deploy" folder created, and then build the solution once and make sure it copies the assembly correctly. If not, check your paths and make sure everything is in the right place. Once you get it built, create a solution folder in your solution, and add assembly into it. This will ensure that the assembly gets stored in TFS. Then check everything in.
Now at this point, if you try to build again it will fail because the assembly in the "Deploy" folder is read-only, since it's stored in TFS and checked in. One solution is to remember to check out the assembly each time before you build, but honestly....who wants to do that? Instead, we can automate that task, too.
For this, we're going to use a pre-build event. Into the "Pre-build event command line:" box, enter the following:
For 64-bit Windows, use:
"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe" checkout "$(SolutionDir)Deploy\$(TargetFileName)"
For 32-bit Windows, use:
"C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe" checkout "$(SolutionDir)Deploy\$(TargetFileName)"
It should look like this (this screenshot is from the 64-bit version):
This pre-build event will now check out the assembly from TFS before each build, which will allow the post-build event to copy over it after the build is done. It's still up to you to remember to check it in once you're finished.
This is all that's needed on the common library side of things. You do your releases as I've described in the previous parts of this article, and each release branch will then contain the "Deploy" folder with the binary assembly.
On the other side, make sure each project that needs a reference has a "Lib" folder in its solution and references all shared libraries from there. All that's left now is to get the assembly from the "Deploy" folder of the common library project to the "Lib" folder of the End-User project.
Note that you can put your "Lib" folder at the project level, or at the solution level. The choice is yours. Putting it at the solution level will keep you from having duplicate assemblies in each project's separate "Lib" folder. On the other hand, having a "Lib" folder per project gives you the added flexibility of allowing you to have a different version of the same assembly for each project. You need to decide which approach works best for your needs.
Once the "Lib" folder is set up, the only thing left is to branch a specific version of the common library into that "Lib" folder. Do that by right-clicking on the actual assembly (the .dll file) from the "Deploy" folder of a particular release, and branching it into the "Lib" folder of the other project.
Note below that the Source and Target are two different projects. This is the key to this type of sharing.
This method of sharing is superior to simply copying the assemblies manually as needed, because it allows tracking and rolling back of changes through TFS. The version history of the files will show what projects a specific assembly has been branched into, and what versions of various assemblies are included in a given project.
Here is a slideshow that contains the information in this article:
That concludes my overview of branching and sharing code in TFS. I hope it is useful, and feel free to leave feedback on how I can improve this, or future, articles.