Explicit Microsoft.SourceLink.GitHub PackageReference silently disables SourceLink on .NET 8+ SDKs
- Dominant language
- C#
- Stars
- 1.4k
- Forks
- 148
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
On SDKs that bundle SourceLink as implicit SDKs (.NET 8+), adding an explicit `` **silently disables** SourceLink rather than enabling or replacing it. Build succeeds with no warnings, but resulting packages have:
- No SourceLink JSON in the PDB
- No PathMap normalization (paths remain non-deterministic)
- `Reproducible` debug entry is still set, so the PE looks deterministic by header, but embedded source paths are not mapped
The docs (both the [README](https://github.com/dotnet/sourcelink#using-source-link-in-net-projects) and many blog posts/templates) still instruct users to add this package. On a modern SDK, following that guidance breaks SourceLink.
## Environment
- .NET SDK: `10.0.202` (also confirmed in `11.0.100-preview.2`)
- `Microsoft.SourceLink.GitHub` NuGet package: `10.0.202`
- Central Package Management via `Directory.Packages.props` with `GlobalPackageReference`
- Strong-named, multi-targeted library (`netstandard2.0;net8.0;net9.0;net10.0`)
## Reproduction
`Directory.Packages.props`:
```xml
true
```
`Directory.Build.props`:
```xml
true
true
true
```
Then `dotnet build -c Release`. Inspect the produced PDB — no SourceLink custom debug information entry (`CC110556-A091-4D38-9FEC-25AB9A351A6A`), no `obj/*/*.sourcelink.json` file.
## Root cause trace
1. NuGet restores `Microsoft.SourceLink.GitHub` directly and imports its `build/Microsoft.SourceLink.GitHub.props/.targets`.
2. Its transitive deps (`Microsoft.SourceLink.Common`, `Microsoft.Build.Tasks.Git`) resolve in `project.assets.json` as `\"buildTransitive/_._\": {}` — the empty-assets marker — because `developmentDependency=true` packages don't flow their build assets through a `PrivateAssets=all` parent. Common's `InitializeSourceControlInformation.targets` / `Microsoft.SourceLink.Common.targets` never get imported via NuGet.
3. NuGet still generates the `PkgMicrosoft_SourceLink_Common` path property (from restore), even though its build assets are `_._`.
4. The SDK-bundled `Microsoft.NET.Sdk.SourceLink.props` contains:
```xml
true
...
```
Because `PkgMicrosoft_SourceLink_Common` is now set, `SuppressImplicitGitSourceLink=true` fires → SDK's bundled `Common` and `Microsoft.Build.Tasks.Git` imports are skipped.
Net result: `GitHub.targets` is imported alone, without the `LocateRepository` task or the `InitializeSourceControlInformationFromSourceControlManager` target. `@(SourceRoot)` is never populated → `_GenerateSourceLinkFile` does nothing → `/sourcelink:` switch is never passed to csc → no SourceLink CDI in PDB → paths are not PathMap-normalized.
Full preprocess (`msbuild -pp`) and PE-debug-directory verification available in [thomhurst/TUnit#5579](https://github.com/thomhurst/TUnit/pull/5579).
## Fix that worked for us
Remove the explicit `Microsoft.SourceLink.GitHub` PackageReference entirely. The SDK then auto-imports Common + Build.Tasks.Git + GitHub from `$(DotnetRoot)/sdk//Sdks/Microsoft.SourceLink.*`, and everything works.
## Suggested improvements
Any one of these would have made this far easier to diagnose:
1. **Docs**: Update the README to say \"on .NET SDK 8+, don't add `Microsoft.SourceLink.GitHub` — it's implicit; add it only for older SDKs or custom hosts.\"
2. **Warning**: Have `Microsoft.SourceLink.GitHub.targets` emit a warning if it's imported but `Microsoft.SourceLink.Common.targets` hasn't been imported (detectable by a well-known property set in Common's targets). This would catch the `buildTransitive/_._` scenario.
3. **Suppression condition**: Narrow the SDK's `SuppressImplicitGitSourceLink` check so it only fires when Common's build assets actually imported, not merely when the `Pkg*` path property is set (since NuGet sets that even for `_._` assets).
Happy to contribute a docs PR if helpful.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.