Rebase the current branch.
Arguments: $ARGUMENTS
Behavior:
- No arguments: rebase on local main
- "origin": fetch origin, rebase on origin/main
- "origin/branch": fetch origin, rebase on origin/branch
- "branch": rebase on local branch
Steps:
- Check for uncommitted changes:
- Run
git status --porcelain
- If there are changes, run
git stash push -m "rebase-temp"
- Remember to pop the stash after rebase completes
- Parse arguments:
- No args → target is "main", no fetch
- Contains "/" (e.g., "origin/develop") → split into remote and branch, fetch
remote, target is remote/branch
- Just "origin" → fetch origin, target is "origin/main"
- Anything else → target is that branch name, no fetch
- If fetching, run:
git fetch <remote>
- Detect already-merged commits (see below)
- Run:
git rebase <target> (or git rebase --onto if stale commits found)
- If conflicts occur, handle them carefully (see below)
- Continue until rebase is complete
- If workmux-base was used and pointed to a merged branch, update it to the
target branch (strip remote prefix for the config value):
git config branch.<branch>.workmux-base main
- If changes were stashed in step 1, run
git stash pop
Detecting already-merged base branches:
When a branch was based on another branch that was squash-merged into the
target, the old commits still appear in the branch history but their changes are
already in the target. A plain git rebase will try to replay them all, causing
repeated conflicts that need to be skipped one by one.
Before rebasing, detect this situation and use --onto to skip stale commits:
- Check if workmux stored a base branch for the current branch:
base=$(git config --get branch.$(git branch --show-current).workmux-base)
- If a base branch is found and it's NOT the rebase target (e.g. base is
analytics-app-detail but we're rebasing onto origin/main):
- Check if the base branch has been merged into the target:
git merge-base --is-ancestor <base> <target>
- If it HAS been merged (exit code 0), find where our branch diverged from
the base branch:
fork_point=$(git merge-base <base> HEAD)
- Then find the last commit on our branch that was part of the base branch
(i.e. the last commit before our own work started):
# The tip of the old base branch in our history
last_stale=$(git rev-list --ancestry-path $fork_point..HEAD \
--not <target> | tail -1)^
Or more simply: the merge-base between the base branch tip and HEAD gives
the fork point, and all commits between that and the first commit unique to
our branch are stale. Use:git rebase --onto <target> <base> HEAD
This replays only commits after the base branch tip onto the target.
- If the base branch has NOT been merged, fall through to a normal rebase.
- If no workmux base is found, fall back to heuristic detection: walk commits
oldest-to-newest and check if each commit's file changes already match the
target using
git diff --quiet. Find the last stale commit and use
git rebase --onto <target> <last-stale-commit>.
- If no stale commits are detected by either method, use a plain
git rebase <target>.
Handling conflicts:
- BEFORE resolving any conflict, understand what changes were made to each
conflicting file in the target branch
- For each conflicting file, run
git log -p -n 3 <target> -- <file> to see
recent changes to that file in the target branch
- The goal is to preserve BOTH the changes from the target branch AND our
branch's changes
- After resolving each conflict, stage the file and continue with
git rebase --continue
- If a conflict is too complex or unclear, ask for guidance before proceeding
1---2name: rebase3description: Rebase the current branch.4---56Rebase the current branch.78Arguments: $ARGUMENTS910Behavior:1112- No arguments: rebase on local main13- "origin": fetch origin, rebase on origin/main14- "origin/branch": fetch origin, rebase on origin/branch15- "branch": rebase on local branch1617Steps:18191. Check for uncommitted changes:20 - Run `git status --porcelain`21 - If there are changes, run `git stash push -m "rebase-temp"`22 - Remember to pop the stash after rebase completes232. Parse arguments:24 - No args → target is "main", no fetch25 - Contains "/" (e.g., "origin/develop") → split into remote and branch, fetch26 remote, target is remote/branch27 - Just "origin" → fetch origin, target is "origin/main"28 - Anything else → target is that branch name, no fetch293. If fetching, run: `git fetch <remote>`304. Detect already-merged commits (see below)315. Run: `git rebase <target>` (or `git rebase --onto` if stale commits found)326. If conflicts occur, handle them carefully (see below)337. Continue until rebase is complete348. If workmux-base was used and pointed to a merged branch, update it to the35 target branch (strip remote prefix for the config value):36 ```37 git config branch.<branch>.workmux-base main38 ```399. If changes were stashed in step 1, run `git stash pop`4041Detecting already-merged base branches:4243When a branch was based on another branch that was squash-merged into the44target, the old commits still appear in the branch history but their changes are45already in the target. A plain `git rebase` will try to replay them all, causing46repeated conflicts that need to be skipped one by one.4748Before rebasing, detect this situation and use `--onto` to skip stale commits:49501. Check if workmux stored a base branch for the current branch:51 ```52 base=$(git config --get branch.$(git branch --show-current).workmux-base)53 ```542. If a base branch is found and it's NOT the rebase target (e.g. base is55 `analytics-app-detail` but we're rebasing onto `origin/main`):56 - Check if the base branch has been merged into the target:57 ```58 git merge-base --is-ancestor <base> <target>59 ```60 - If it HAS been merged (exit code 0), find where our branch diverged from61 the base branch:62 ```63 fork_point=$(git merge-base <base> HEAD)64 ```65 - Then find the last commit on our branch that was part of the base branch66 (i.e. the last commit before our own work started):67 ```68 # The tip of the old base branch in our history69 last_stale=$(git rev-list --ancestry-path $fork_point..HEAD \70 --not <target> | tail -1)^71 ```72 Or more simply: the merge-base between the base branch tip and HEAD gives73 the fork point, and all commits between that and the first commit unique to74 our branch are stale. Use:75 ```76 git rebase --onto <target> <base> HEAD77 ```78 This replays only commits after the base branch tip onto the target.79 - If the base branch has NOT been merged, fall through to a normal rebase.803. If no workmux base is found, fall back to heuristic detection: walk commits81 oldest-to-newest and check if each commit's file changes already match the82 target using `git diff --quiet`. Find the last stale commit and use83 `git rebase --onto <target> <last-stale-commit>`.844. If no stale commits are detected by either method, use a plain85 `git rebase <target>`.8687Handling conflicts:8889- BEFORE resolving any conflict, understand what changes were made to each90 conflicting file in the target branch91- For each conflicting file, run `git log -p -n 3 <target> -- <file>` to see92 recent changes to that file in the target branch93- The goal is to preserve BOTH the changes from the target branch AND our94 branch's changes95- After resolving each conflict, stage the file and continue with96 `git rebase --continue`97- If a conflict is too complex or unclear, ask for guidance before proceeding