You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In a repo with ~30 merges/day into main, gh stack sync occasionally reports a conflict when rebasing the bottom branch onto main, even though a manual git rebase origin/main succeeds cleanly. Following the CLI's advice to run gh stack rebase to resolve the conflict makes the situation worse: it builds a git-rebase-todo against a stale base, including commits from other features that are already in main (with different SHAs after squash/rebase), causing false conflicts in unrelated files.
Steps to reproduce
Have a stack of ~5 branches rooted at main, where the bottom branch was created from a main that is now ~6-10 commits behind.
Run gh stack sync.
gh stack sync reports ✗ Conflict detected rebasing <bottom-branch> onto main and advises Run gh stack rebase to resolve conflicts interactively.
Run gh stack rebase as advised.
gh stack rebase opens an interactive rebase whose todo list includes commits from other teams' features (e.g., an API service fix, a notifications refactor, a UI change) that are already present in origin/main (just with different SHAs).
The rebase stops with conflicts in files completely unrelated to the stack — e.g., a backend service's internal/.../service.go or a frontend component file.
Evidence
After aborting the broken rebase, a manual git rebase origin/main on the bottom branch succeeds with zero conflicts and replays only the stack's own commits:
git rebase --abort
git rebase origin/main
# Rebasing (1/7)... Successfully rebased
The git-rebase-todo from the broken rebase listed commits like:
All of these are already ancestors of origin/main (verified with git merge-base --is-ancestor), so they should never have been included in the rebase.
Root cause hypothesis
Both gh stack sync and gh stack rebase rely on a trunk.head stored in .git/gh-stack stack metadata. In repos with high merge velocity, this trunk.head becomes stale quickly. The stale value causes gh stack sync to compute a wrong merge-base, triggering a false conflict, and gh stack rebase inherits the same stale base, constructing a rebase todo that includes already-merged commits.
Expected behavior
gh stack sync should use the latest origin/main tip (fetched in step 1 of sync) to compute the rebase base, not a cached trunk.head.
gh stack rebase should also refresh the trunk tip before building the rebase todo.
Commits that are already ancestors of onto should be excluded from the rebase todo (git's --onto mode should handle this).
Workaround
# When gh stack sync reports a conflict on the bottom branch:
git rebase --abort # if a rebase got started
git checkout <bottom-branch>
git rebase origin/main # manual rebase (clean)
git push --force-with-lease origin <bottom-branch># Then rebase each higher branch onto its parent:
git checkout <next-branch>
git rebase <parent-branch>
git push --force-with-lease origin <next-branch># ...repeat for all higher branches
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary
In a repo with ~30 merges/day into main,
gh stack syncoccasionally reports a conflict when rebasing the bottom branch onto main, even though a manualgit rebase origin/mainsucceeds cleanly. Following the CLI's advice to rungh stack rebaseto resolve the conflict makes the situation worse: it builds agit-rebase-todoagainst a stale base, including commits from other features that are already in main (with different SHAs after squash/rebase), causing false conflicts in unrelated files.Steps to reproduce
gh stack sync.gh stack syncreports✗ Conflict detected rebasing <bottom-branch> onto mainand advisesRun gh stack rebase to resolve conflicts interactively.gh stack rebaseas advised.gh stack rebaseopens an interactive rebase whose todo list includes commits from other teams' features (e.g., an API service fix, a notifications refactor, a UI change) that are already present inorigin/main(just with different SHAs).internal/.../service.goor a frontend component file.Evidence
After aborting the broken rebase, a manual
git rebase origin/mainon the bottom branch succeeds with zero conflicts and replays only the stack's own commits:git rebase --abort git rebase origin/main # Rebasing (1/7)... Successfully rebasedThe
git-rebase-todofrom the broken rebase listed commits like:All of these are already ancestors of
origin/main(verified withgit merge-base --is-ancestor), so they should never have been included in the rebase.Root cause hypothesis
Both
gh stack syncandgh stack rebaserely on atrunk.headstored in.git/gh-stackstack metadata. In repos with high merge velocity, thistrunk.headbecomes stale quickly. The stale value causesgh stack syncto compute a wrong merge-base, triggering a false conflict, andgh stack rebaseinherits the same stale base, constructing a rebase todo that includes already-merged commits.Expected behavior
gh stack syncshould use the latestorigin/maintip (fetched in step 1 of sync) to compute the rebase base, not a cachedtrunk.head.gh stack rebaseshould also refresh the trunk tip before building the rebase todo.ontoshould be excluded from the rebase todo (git's--ontomode should handle this).Workaround
Versions
gh stack version 0.1.0All reactions