Assume PR A branches off master and PR B branches off PR A.
We squash-merge PR A into master.
PR B must now be "restacked" before merging.
A squash-merge collapses all of A's commits into one new commit on master
with a new SHA. A's original commits are not ancestors of this new
commit.
But branch B still contains A's original commits in its history. So:
master (as the squash commit) and in B (as the
original commits).
git rebase master will attempt to replay A's original commits onto a
master that already has the same changes, producing conflicts.
The fix is git rebase --onto, which lets us replay only B's own commits
and drop A's.
git checkout <branch-B> git fetch origin git rebase --onto origin/master <old-A-tip> <branch-B> git push --force-with-lease
origin/master — the new base (now contains the squashed A).
<old-A-tip> — the commit that was the tip of A, i.e. the last A commit in
B's history. This is the boundary: everything after it is B's own work;
everything up to and including it is A's redundant copy. git rebase --onto
replays the range <old-A-tip>..<branch-B> onto origin/master.