mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-09-24 10:58:09 +08:00
chore(claude): harden the rebase-onto-main skill against losing work (#28368)
The skill force-pushes over the only copy of the pre-rebase head without ever checking that the rebase preserved it, and says nothing about the two things that most often go wrong around it. Adds a git range-diff gate before the push, the worktree collision that makes git checkout fail mid-loop, and the --onto follow-up a stacked child branch needs once its base moves. Assisted-by: Claude:claude-opus-5 Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
This commit is contained in:
@@ -17,6 +17,16 @@ When a parent branch is squash-merged, its individual commits become a single ne
|
||||
|
||||
1. **Identify the branch.** Use `$ARGUMENTS` if provided, otherwise use the current branch.
|
||||
|
||||
Check `git worktree list` first. A branch checked out in another worktree cannot be checked out here — `git checkout` fails with `fatal: '<branch>' is already used by worktree at ...`. Rebase it in place instead: `git -C <worktree-path> rebase main`.
|
||||
|
||||
When rebasing several branches in a loop, test the checkout's exit status explicitly:
|
||||
|
||||
```
|
||||
git checkout -q "$b" || { echo "SKIP $b (worktree?)"; continue; }
|
||||
```
|
||||
|
||||
Without that guard the loop rebases whatever is *currently* checked out, once per failed iteration, and reports success — the rebase really did work, just on the wrong branch. `set -e` is not a substitute: it is ignored in a Claude Code Bash tool call (it only takes effect when bash runs a script file).
|
||||
|
||||
2. **Fetch and update main:**
|
||||
```
|
||||
git fetch origin main:main
|
||||
@@ -62,10 +72,29 @@ When a parent branch is squash-merged, its individual commits become a single ne
|
||||
```
|
||||
Confirm only the expected commits are present.
|
||||
|
||||
Then prove no content changed, because the next step overwrites the only copy of the old head:
|
||||
```
|
||||
git range-diff <old-merge-base>..<old-head> main..<branch>
|
||||
```
|
||||
Every line must be marked `=` (identical patch). `!` means a commit's diff changed, `<` means one was dropped, `>` means one appeared. Anything but `=` is a rebase that lost or altered work — stop and look before pushing. Scripted:
|
||||
```
|
||||
rd=$(git range-diff --no-color <old-merge-base>..<old-head> main..<branch>)
|
||||
tot=$(echo "$rd" | grep -cE '^ *[0-9]+:')
|
||||
eq=$(echo "$rd" | grep -cE '^ *[0-9]+: +[0-9a-f]+ = ')
|
||||
[ "$tot" = "$eq" ] && echo CLEAN || echo REVIEW
|
||||
```
|
||||
|
||||
11. **Ask the user** before force-pushing. When approved:
|
||||
```
|
||||
git push origin <branch> --force-with-lease
|
||||
```
|
||||
Use `--force-with-lease`, never a bare `--force`. Push to the remote that holds the branch's PR head.
|
||||
|
||||
If this branch is the base of a stacked PR, the branch above it still points at the pre-rebase commits. Rebase it onto the new head and force-push it too:
|
||||
```
|
||||
git rebase --onto <branch> <old-head-of-branch> <branch-above>
|
||||
```
|
||||
Skipping this makes the upper PR show every commit on `main`.
|
||||
|
||||
12. **Clean up** the old branch:
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user