Rebasing, Cherry-Pick & Worktrees
Rebase, cherry-pick, and worktrees help Go teams keep linear history, port fixes across release lines, and work on two module versions at once.
Search across all documentation pages
Rebase, cherry-pick, and worktrees help Go teams keep linear history, port fixes across release lines, and work on two module versions at once.
Used carefully, they reduce go.sum conflict pain and speed hotfixes without dirty stashes.
Rebase replays your commits onto a newer base, rewriting SHAs.
Cherry-pick copies individual commits to another branch, common for backports.
Worktrees add a second checkout directory sharing one .git store, ideal for parallel go test runs on different branches.
All three interact with Go module pseudo-versions because those strings embed commit metadata.
Quick-reference recipe card - copy-paste ready.
# Rebase feature branch onto latest main
git fetch origin
git switch feat/my-change
git rebase origin/main
go test ./...
go mod tidy && git diff --exit-code go.mod go.sum
git push --force-with-lease
# Cherry-pick hotfix to release branch
git switch release/v1
git cherry-pick abc1234
go test ./...
# Parallel checkout with worktree
git worktree add ../repo-hotfix release/v1When to reach for this:
main to release/v1.Fix a nil panic on main, backport to v1 release line, keep feature work running:
# On main - fix landed as commit fa1c0ff
git switch main
git pull --ff-only
go test ./...
# Backport to release/v1
git switch release/v1
git pull --ff-only
git cherry-pick fa1c0ff
go test ./...
git tag -a v1.9.4 -m "v1.9.4: fix nil panic in parser"
git push origin release/v1 v1.9.4
# Continue feature branch in a worktree
git worktree add ../widget-feat feat/new-api
cd ../widget-feat
go test ./...What this demonstrates:
main into the release branch.Rebase temporarily removes your commits, fast-forwards to the new base, then reapplies commits one by one.
Conflicts may appear in Go sources and go.sum; resolve, git add, git rebase --continue.
Cherry-pick applies the patch of a chosen commit as a new commit on the current branch.
If the original commit touched go.mod, verify tidy state after pick.
Worktree creates a linked working directory with its own HEAD but shared objects and refs.
Each tree can run go build / go test independently; the module cache is global on the machine.
| Situation | Guidance |
|---|---|
| Personal feature branch before merge | Rebase freely; push with --force-with-lease |
| Branch others pushed to | Coordinate; prefer merge |
| After tag consumers use | Do not rewrite tagged commits |
| Open PR with many reviewers | Rebase early and often, not only at end |
Cherry-pick brings one commit.
Merge brings entire branch history.
For Go patch lines, cherry-pick keeps release branches minimal and changelog-friendly.
~/src/widget/ # main work on feat/new-api
~/src/widget-hotfix/ # worktree on release/v1
List worktrees: git worktree list.
Remove: git worktree remove ../widget-hotfix after branch is done.
# After any history rewrite on a branch you depend on locally
go clean -testcache
go test ./...
# Pseudo-version preview for current HEAD (unpinned)
go list -m -json example.com/widget@masterRewriting SHAs changes pseudo-version strings for untagged commits.
Tagged releases are unaffected once pushed.
git push --force-with-lease.go.mod context differs on release branch. Fix: go test ./... and tidy after every pick.go.sum conflicts - Hand-merging checksum lines is error-prone. Fix: take one side, run go mod tidy, continue rebase.| Alternative | Use When | Don't Use When |
|---|---|---|
Merge main into feature | Shared branch, low rewrite tolerance | You want linear trunk history |
git merge backport | Large divergent release line | Single-commit security fix |
| Stash | Quick context switch, minutes | Parallel long builds on two branches |
| Separate clone | Completely isolated experiments | Wasted disk and fetch time |
Tagged semver releases do not change after rebase unless you move or delete tags.
Untagged commits accessed via pseudo-versions will show new version strings after SHA changes.
When multiple people commit to the same branch or when preserving exact merge context matters for audits.
Yes, if protobuf or stringer outputs differ between branches.
Regenerate with the branch's toolchain, then continue the cherry-pick.
Two or three per repo is typical: trunk, feature, hotfix.
More than that usually signals branch policy problems.
Yes.
Treat force-pushed branches like new pushes; module graphs must re-validate.
Squash WIP commits, reword messages, drop debug commits before a clean PR.
Run before review, not after merge to trunk.
Each worktree is a separate directory.
A go.work file in one tree does not apply to another unless you copy or symlink intentionally.
git cherry-pick --abort during conflict, or git revert on the bad commit if already committed.
Rebasing old commits changes SHAs and can confuse manual bisect notes.
Use tags and merge commits as stable bisect anchors.
Yes: git worktree add ../widget-v1 v1.9.3.
Useful to reproduce a consumer bug at an exact module version.
Helpful if checks rerun reliably.
Ensure go mod tidy and tests run after bot rebase, not just conflict resolution.
Same rules, but conflicts may span multiple go.mod files.
Tidy each affected module root after resolution.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026