Let's say I have project A and project B. Project A depends on project B. So A would normally have a direct reference to B's DLL.

Then I decided to publish B as a nuget package. Now, A has a reference to B via nuget instead of a local DLL.

The downside to this arrangement is that if I update B, I need to upload a new nuget and wait for it to be available in order to use it from A.

I see that I can point to a local nuget package when updating A's reference to B so that does help a bit. However, if I make a change to B, I do still have to go through the steps of generating a new package and updating A's reference to the package before A will see the change. With the pre-nuget arrangement, I simply built B and A would see the changes.

An alternative is to remove A's reference to B's nuget package and revert to pointing to the local DLL while doing local development. However, if A is published to github, then the reference has to be reverted to a nuget reference before pushing to github.

What's the best practice in a situation like this? Surely many folks are dealing with this sort of thing with github and nuget being widely used.


This topic came up for discussion on the C# subreddit and some interesting approaches were pointed out.

Azure devops - original comment - thanks to B0dona

What we do is use azure devops ( https://azure.microsoft.com/en-us/services/devops/ ) to build and push our nuget packages to our own repository (nuget.org is slow) automatically after a new commit has been pushed.

You set it up once, push project B drink some coffee and enjoy the joy that is updating packages.

git submodules - original comment - thanks to alkrun

You mention GitHub so I'll propose something a bit different:

In my opinion, if work on project A is likely to cause changes in project B, A referencing B as a git submodule is much easier than dealing with nuget. Git Submodules aren't without their headaches, but this is what they were designed for. Some of the benefits:

1) The biggest is that if you say "If I need to change B then I'll just make the change and push to get a new package built then test it out in A" it's not a very fluid model to work with and it's asking developers to push untested code into B. Then that 1-3 minute turn around for CI build/package turns into 3 x 1-3 minute turnarounds and it just feels horrible when I've tried it in the past. It's a massive productivity killer.

2) Any other options around changing csproj files, they can work, but they're very error prone. Developers aren't always great about reviewing all changes before they commit them, you're going to have developers forgetting and checking in the change to a project reference and it's going to cause build failures.

3) Using B as a submodule for A doesn't prevent you from having automated builds on B that produce nuget packages, and maybe other projects which are less likely to change B could/should refer to those

4) At some point in the development of A, if it matures and becomes less likely to cause changes in B, then you can switch A->B to a nuget package reference also

Another option, I remember reading an article years ago where someone had created a tool that generated an msbuild xproj file that would replace package references with project references. They had it set up where the xproj file was on the .gitignore and if the file didn't exist, the nuget package reference was used. In this way, a developer would run a command to switch over to project references, make the changes they need, commit them, push changes, then update the nuget reference. This seemed fairly clean to me, but I can't find the article and it was a bit more complicated than I'm making it sound.

So I'd still go with the git submodule route. There are some quirks with git submodules but they have gotten a lot easier to deal with in the last couple years and it feels like the quirks are easier to explain than the other options. Having used this for a few projects now, it's very intuitive. Understand what a Git Submodule in a detached head state is and how to avoid it, make sure to use the -b option when adding a submodule, and find a good tool that can handle submodules well. For what it's worth, VS Code is the most intuitive interface I've found for working with submodules. Open A in VS Code then switch to the version control tab and you'll see A and any submodules listed up top along with the branches they're tracking. Commit changes to the submodule, then to the parent and you're good to go.

2 Answers

Peska On

If you are using Visual Studio 2017, you can install NuGet Reference Switcher for Visual Studio 2017 extension. Here is a guide how to use it: https://github.com/RicoSuter/NuGetReferenceSwitcher/wiki/Guide

felix-b On

The Node community demonstrates a more robust approach. The npm link command which is available out of the box (see also this blog post), creates symbolic link from distributed package directory to package source directory. In this way:

  • package consumers are transparently redirected to package source project
  • changes in package sources are automatically reflected on the consumer side

The npm link approach has also these advantages over reference switching:

  • no changes are made to consumer's source code -- which can accidentally be committed.
  • works cross-platform, doesn't need a specific IDE
  • can be scripted and shared with the team

This feature is obviously required in the NuGet community, but for some reason, NuGet still lacks it. There is a feature request https://github.com/NuGet/Home/issues/1821, which indicates they have no plans of adding it.

Meanwhile I created a tool, which works similarly to npm link for NuGet packages, you may want to give it a try: https://www.nuget.org/packages/NuLink