I have some shared code I want to share among a number of solutions. Most examples use the command line, but I want to do it using Visual Studio 2013 (and/or TortoiseGit)?
- SolutionShared
- .git
- Project1Shared
- Project2Shared
- Solution1
- .git
- ProjectFoo
- ProjectBar
- [SolutionShared]
- [Project1Shared]
- [Project2Shared]
- Solution2
- .git
- ProjectBaz
- ProjectQux
- [SolutionShared]
- [Project1Shared]
- [Project2Shared]
What I did was to create a new solution SolutionShared
, add all my shared code there, and add it to its own git repo. I then used TortoiseGit (as I couldn't figure out how to do it Visual Studio) to add that shared repo as a git submodule to Solution1
and Solution2
.
1. What do I do in Visual Studio?
My two solutions now have a SolutionShared
directory. Do I simply add its two child projects (Project1Shared
and Project2Shared
) in Visual Studio?
2. How do I make changes to the shared code from within the non-shared projects
If I'm in one of the non-shared solutions and make a change to something in the submodule, how do I commit and push it back to the shared solution's repo (SolutionShared
) so that it's available to all solutions that reference it?
A git submodule is a record within a host git repository that points to a specific commit in another external repository. Submodules are very static and only track specific commits. Submodules do not track git refs or branches and are not automatically updated when the host repository is updated.
Open an existing Git repository. If your code is already on your machine, you can open it by using File > Open > Project/Solution (or Folder) and Visual Studio automatically detects if it has an initialized Git repository.
Git submodules may look powerful or cool upfront, but for all the reasons above it is a bad idea to share code using submodules, especially when the code changes frequently. It will be much worse when you have more and more developers working on the same repos.
We have found that the easiest way for us to do this is to move each of our shared units of code into their own Visual Studio Project and put each shared Visual Studio project in its own repo.
We then add each one of those projects as a submodule to any Solution that needs them. This is helpful since many of our projects can be very large in size and share many of the same chunks of code. We have made extensive use of nuget packages for this purpose, as well, but have generally had better success and a much better design/debug experience with submodules.
Much has changed at Microsoft in relation to Git in the last few years. Visual Studio Team Services (TFS Online) and On Prem-TFS (since TFS2015) both now have a good understanding of how submodules work and can now do CI Builds that incorporate submodules right out of the box.
Support in on-prem TFS 2015 can be a bit buggy, however. TFS Build's references to the submodules have a habit of becoming corrupted resulting in builds that stop working without warning until whichever submodule is at fault is completely removed and re-added - not a fun process. For this reason (among a few others), we are now using VSTS (TFS Online) for everything and have had none of those same types of problems. I would assume that this is fixed in on-prem TFS 2017, as well.
As was mentioned, Visual Studio itself (the IDE) does still have a hard time understanding submodule relationships. It really just can't handle them. I have tried a number of standalone Git Tools to find the easiest way to manage an environment like this. Tortoise seems to provide the easiest and most performant experience when pushing, pulling, and checking in to repos containing submodules. I usually use commands to add the submodules, but I suspect Tortoise's add submodule functionality works just fine, too.
When you commit code to a repo using Tortoise, it notices when a submodule is dirty and will prompt you to check-in the submodule before checking in the parent repo. That's really nice. Pulling or Fetching the parent repo can be a little confusing, though. It doesn't actually refresh the submodule from it's remote branch, it only refreshes it to whatever level is currently checked into the main repo remote which is not always the latest. In reality, this is the desired behavior, it's just not immediately intuitive if you're not expecting it.
After much experimenting...
In VS, add the shared projects from the submodule to the solution. They seem to live "outside" the parent solution as far as versioning.
If you make an edit to the submodule's projects, they are local. They need to be committed and pushed to the source repo, and then you need to merge them there. If you make changes at the source, you need to pull them manually into your solution's git submodule.
Problem is VS doesn't do any of this for you, so you need to use something like TortoiseGit or the command line.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With