| name | fix-vendor-conflicts |
| description | Resolve vendor/ conflicts during a merge, rebase, or dependency upgrade on main or release branches |
| allowed-tools | Bash Read Grep Edit |
Fixing Vendor Conflicts
Use this skill when resolving conflicts in vendor/ during a merge, rebase, or dependency upgrade.
Before starting
Ask the user: are you working on the main branch or a release branch? The answer changes what kinds of fixes are acceptable (see below).
What this skill does
Guides the process of diagnosing and resolving vendor directory conflicts caused by dependency changes — whether a direct bump or a transitive cascade.
Core principles
Never patch vendor/ files manually. CI runs go mod vendor and will overwrite any manual patches. All fixes must come from upgrading or pinning the upstream dependency to a version that has the fix already.
Always run the pre-commit checklist before committing anything:
go mod tidy
go mod vendor
go build -mod vendor ./...
go test -mod vendor -run ^$ ./...
go run pkg/docsgen/generate_manifest.go
All must pass with no errors. If generate_manifest.go produces changes, commit them:
git add docs/sources/tempo/configuration/manifest.md && git commit -m "manifest.md"
go build catches compile errors in production code; go test -run ^$ catches compile errors in test and integration files. Run these after every change — dependency upgrades, cherry-picks, and manual fixes alike — before staging and committing.
Step-by-step process
1. Understand what changed
git diff go.mod
Note which module(s) were bumped. A single bump (e.g. grpc) often cascades into failures in transitive dependencies.
2. Check what main did
Main branch has almost always already solved the problem. Find relevant commits:
git log --oneline main | grep -i "<module-name>"
git show <commit-sha>:go.mod | grep -E "<module-name>|<related-module>"
git show <commit-sha>:vendor/<path/to/file.go>
Use main as the source of truth for what versions to target and what code changes are needed.
3. Run tidy to surface errors
go mod tidy
This will either succeed or tell you exactly what is missing or mismatched. Read the error trace carefully — it shows the import chain that led to the conflict.
4. Fix each error
For each error go mod tidy surfaces:
- If it's a missing package in a module: a transitive dep requires a version of that module that doesn't have the package. Upgrade (or pin) the module to a version where the package exists or is no longer needed.
- If it's a compile error from an interface change: a dependency updated an interface. Find the implementing type in this repo and update it to match. Check main for the exact fix.
- If it's a call-site mismatch (wrong number of args, wrong signature): the upstream library changed a function signature. Update all callers, mocks, and test helpers.
Always check main at the relevant commit before writing new code:
git show <commit-sha> -- <path/to/file.go>
5. Re-run tidy, then vendor
go mod tidy
go mod vendor
Both must exit 0. If go mod vendor fails with a missing package, try go mod download first, then re-run vendor.
6. Verify fixes came from upstream
After vendoring, confirm that your fixes are present in vendor/ as real upstream code — not patches:
grep -A5 "<relevant symbol>" vendor/<path/to/file.go>
If you only see a stub or Unimplemented* type, the module version is too old. Upgrade to a newer one.
7. Build to confirm no remaining compile errors
go build -mod vendor ./...
This compiles every package in the repo, not just the main binary entrypoint. make tempo only builds cmd/tempo and will miss compile errors in other packages (e.g. modules/distributor). Always use ./... to catch issues across the full project.
8. Check test files compile
go build does not compile _test.go files. Run this to catch errors in test code too:
go test -mod vendor -run ^$ ./...
The -run ^$ flag matches no test names, so no tests execute — it only compiles. Test files often contain mock types that implement interfaces, and a dependency upgrade that adds a method to an interface will break those mocks without showing up in go build.
If new failures appear, find the commit on main that introduced the fix and evaluate whether to cherry-pick or fix manually (see below).
Also run this specifically for integration test directories, which are often missed:
go test -mod vendor -run ^$ ./integration/...
Ask the user if they want to run broader test coverage (e.g. make test, make test-e2e). These take a long time and are not required for every commit, so only run them if the user confirms.
If new errors appear after any step, loop back to step 3 (go mod tidy) and work through the errors again. Cascading dependency conflicts often require multiple passes.
Cherry-pick vs manual fix
Prefer cherry-pick when:
- The commit on main is small and targeted (e.g. "fix interface X", "add missing method")
- The commit touches only the files you need changed
- Cherry-picking it won't pull in unrelated new files, new dependencies, or feature code
Prefer a manual fix when:
- The only commit on main that has the fix is a large feature commit — it adds new production code, new integration tests, or upgrades additional dependencies as side effects
- Cherry-picking would require follow-up work (reverting unwanted files, upgrading more deps) that outweighs the benefit
- The fix itself is trivial (e.g. a one-line method stub on a mock type)
When making a manual fix on a release branch, keep it to the absolute minimum needed to satisfy the compiler. This only applies to test mock types in _test.go files — never to production code. Typically a stub that panics, matching the pattern of other unimplemented methods in the same mock type:
func (r mockRing) GetSubringForOperationStates(_ ring.Operation) ring.ReadRing {
panic("implement me if required for testing")
}
If you cherry-picked a commit and later discover it brought in too much, revert cleanly and apply the manual fix instead:
git revert --no-commit <cherry-pick-sha> [<follow-up-sha> ...]
git commit -m "revert: undo cherry-pick of <sha> (<reason>)"
9. Regenerate the config manifest
After all changes are in, regenerate the configuration manifest so the docs stay in sync with the actual config:
go run pkg/docsgen/generate_manifest.go
This updates docs/sources/tempo/configuration/manifest.md. Commit the result if anything changed:
git add docs/sources/tempo/configuration/manifest.md && git commit -m "manifest.md"
Common patterns of cascading conflicts
When one module is bumped, look for these patterns:
- Interface additions: a core library adds a method to an interface your code implements → add the method to your type
- Signature changes: a library changes the signature of a function → update all callers, including mocks and test helpers
- Replace directive staleness: a
replace directive in go.mod pins a fork to an old version that's incompatible with the new dep → update the replace directive
- Test-only import conflicts:
go mod tidy resolves test dependencies too; a module's tests may import an internal package that was removed in a newer version → upgrade that module to a version where its tests no longer import the removed package
Main vs release branch
Main branch
Manual code changes are acceptable — if a dependency upgrade requires updating an interface implementation, a function signature, or call sites in this repo, go ahead and make those changes directly.
Release branch
Do not make manual production code changes. A release branch should only receive targeted backports, not new hand-written source changes driven by dependency upgrades. Instead, find the commit on main that already contains the fix and cherry-pick the relevant source file changes from it.
The one exception is a minimal test-only compatibility stub in a _test.go file when no suitable fix exists on main and the change is required solely to satisfy the compiler for test code. Keep it to the absolute minimum — avoid changing runtime behavior.
Finding the right commit to cherry-pick
For each module that requires a code fix:
-
Identify which module is causing the issue and what version change triggered it (e.g. github.com/grafana/gomemcache v0.0.0-20250228 → v0.0.0-20251008 added ctx to GetMulti).
-
Use git log -L to trace commits on main that touched that module's line in go.mod:
git log --oneline -L '/github.com\/grafana\/gomemcache/,+1:go.mod' main
-
Walk backwards through the commits. The most recent commit touching that line may not have the fix — go one or two commits earlier. Look for a commit whose description mentions an interface or signature change (not just a version bump).
-
Verify the commit has the fix you need:
git show <commit-sha> -- <path/to/file.go>
Applying the cherry-pick on a release branch
Commit the go.mod/vendor changes first, then do a regular git cherry-pick (no --no-commit). This preserves the original commit message and author, making it clear to PR reviewers that the source code changes were cherry-picked from main rather than written manually.
git add -A && git commit -m "chore(deps): update <modules>"
git cherry-pick <commit-sha>
The cherry-pick will conflict on go.mod, go.sum, and vendor/ — because we already have the newer versions from step 1. Keep ours for all of those. The source file changes (interface implementations, call sites) will usually auto-merge cleanly.
For any new doc or config files added by the dep upgrade (e.g. a generated config manifest), take theirs — these reflect the new capabilities of the upgraded dependency.
git checkout --ours go.mod go.sum vendor/modules.txt vendor/<affected-module>/
git checkout --theirs docs/sources/tempo/configuration/manifest.md
git add go.mod go.sum vendor/modules.txt vendor/<affected-module>/ docs/...
git diff --name-only --diff-filter=U
git cherry-pick --continue --no-edit
The resulting commit will carry the original message and author from main, e.g.:
Update dskit and adjust memcached interface signature (#5604)
Author: Zach Leslie <zach.leslie@grafana.com>
Notes for release branch backports
- Always check main first — it has already solved the problem, usually at a specific commit
- A single module bump can require changes to several related modules; fix them together
- The
go mod tidy error trace is the best guide to what needs fixing — read it fully before acting