Merge Upstream
Merge a specific upstream tag from DataDog/dd-trace-dotnet into the fork.
The user will provide the upstream tag to merge (e.g. v3.35.0). If not provided,
determine it automatically:
- •Find previously merged upstream versions:
code
.claude/skills/merge-upstream/find-previous-versions.sh
- •Take the highest version found and increment the minor version (e.g.
v3.34.0→v3.35.0). Then check upstream for the latest patch of that minor version by listing remote tags:Pick the highest patch version available (e.g. ifcodegit ls-remote --tags upstream 'refs/tags/v<major>.<next_minor>.*'
v3.35.0andv3.35.1both exist, suggestv3.35.1). If no tags exist for that minor version, the tag doesn't exist yet — abort. - •Always confirm with the user before proceeding — show the previous version found and the proposed next version, and ask the user to confirm or provide a different tag.
- •Ask the user which branch to base the merge on. Suggest
main(recommended) but also offer the current branch (git branch --show-current) as an option. Use the chosen branch as<base>in step 3 below.
Fork context
The upstream project (dd-trace-dotnet) contains both a tracer and a profiler. Our fork only uses the profiler — the tracer is completely removed.
What we strip from upstream on every merge:
- •
tracer/— we don't use the Datadog tracer at all - •
profiler/src/Demos/,profiler/test/,profiler/src/Tools/— upstream demo/test code we don't need - •
shared/test/— upstream shared test code - •
.azure-pipelines/,.gitlab/— upstream CI configs; we use GitHub Actions only - •
.github/additions from upstream — we keep only our own pyroscope-specific workflows - •
.claude/additions from upstream — we keep only our own claude configuration - •
.gitlab-ci.yml— upstream CI config; we use GitHub Actions only - •
docs/— upstream documentation - •
shared/src/Datadog.Trace.ClrProfiler.Native— not used in our fork - •
build/cmake/FindSpdlog.cmake,shared/src/native-lib/spdlog,build/cmake/FindManagedLoader.cmake— we use git submodules for these instead
When resolving conflicts, keep this context in mind: if a conflict involves code paths related to the tracer, Azure CI, upstream demos, or upstream .github workflows, our side (deletion/absence) is correct.
IMPORTANT — git safety rules:
- •Never create PRs or push to the upstream DataDog repo. All PRs must target
grafana/pyroscope-dotnetwith--base main. - •Never rebase or rewrite history. The only allowed destructive operations are
--amendand--force-pushon the merge commit of the branch created in step 2. - •Only push to the
kk/fork-update-*branch created for this merge — never tomain.
The scripts bellow should be executed as is, as executable, without passing it to the bash. .claude/skills/merge-upstream/find-previous-versions.sh instead of bash .claude/skills/merge-upstream/find-previous-versions.sh
Steps
- •
Ensure upstream remote exists and fetch tags
codegit remote add upstream https://github.com/DataDog/dd-trace-dotnet.git
Skip if already present. Fetch upstream tags:
codegit fetch upstream --tags
- •
Verify the target tag exists on the upstream remote
codegit ls-remote --tags upstream refs/tags/<tag>
If the output is empty, the tag does not exist upstream — abort and inform the user. Do not rely on
git tag -las it only checks local refs which may be stale or wrong. - •
Create a merge branch from the chosen base
codegit checkout -b kk/fork-update-<version> <base>
If the branch already exists, delete it first and recreate:
codegit branch -D kk/fork-update-<version> git checkout -b kk/fork-update-<version> <base>
- •
Start the merge (no commit, no fast-forward)
codegit merge <tag> --no-commit --no-ff
- •
Remove directories we don't carry in the fork
codegit rm -rf tracer git rm -rf profiler/src/Demos/ git rm -rf shared/src/Datadog.Trace.ClrProfiler.Native git rm -rf shared/test git rm -rf .azure-pipelines git rm -rf .gitlab git rm -rf docs git rm -rf profiler/test git rm -rf profiler/src/Tools git rm -f .gitlab-ci.yml
- •
Remove files we replace with git submodules
codegit rm -rf build/cmake/FindSpdlog.cmake git rm -rf shared/src/native-lib/spdlog git rm -rf build/cmake/FindManagedLoader.cmake
- •
Clean up files deleted by us but modified upstream (DU conflicts)
code.claude/skills/merge-upstream/resolve-du-conflicts.sh
- •
Remove any upstream .github and .claude files that were added
code.claude/skills/merge-upstream/remove-upstream-github.sh
- •
Resolve
.github/CODEOWNERS— always keep the fork version If.github/CODEOWNERShas a conflict, always resolve it to the fork (grafana/pyroscope) version. The upstream CODEOWNERS contains DataDog-specific team ownership rules that are irrelevant to the fork. Check out our side and stage it:codegit checkout --ours .github/CODEOWNERS git add .github/CODEOWNERS
- •
Resolve conflicts in CMake files first
- •List all conflicted files:
git diff --name-only --diff-filter=U - •Resolve CMake-related conflicts first (
CMakeLists.txt,*.cmakefiles) - •Then verify cmake configures successfully:
Fix any cmake errors before proceeding to other conflicts.code
.claude/skills/merge-upstream/cmake_configure.sh
- •Resolve remaining conflicts
- •For version conflicts in binary/DLL/package references (e.g. NuGet versions, library versions, dependency pinning), always pick the higher version
- •Prefer our fork's changes for pyroscope-specific code
- •Ask the user when unsure which side to keep
- •
Verify the build (only the targets we use)
Note: The build may take significant time (several minutes). Use a generous timeout (e.g. 600000ms). The script always removes the old build directory first.
code.claude/skills/merge-upstream/build.sh
Report any build errors and fix them before committing.
- •
Commit the merge
- •
git add -A && git commitwith message:merge upstream <tag>
- •
- •
Push and create a draft PR
codegit push -u origin kk/fork-update-<version> gh pr create --draft --repo grafana/pyroscope-dotnet --base <base> --label "upstream-merge" --title "merge upstream <tag>" --body "Merge upstream dd-trace-dotnet <tag> into the fork."
- •
Generate PR summary After the PR is created, invoke the
merge-upstream-summaryskill to generate a detailed summary and update the PR description.