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
feat(push): allow --force to override behind-remote skip
When a repo is strictly behind the remote (toPush=0, toPull>0),
arb push now respects --force instead of unconditionally skipping.
The push uses --force-with-lease to overwrite remote-only commits,
matching user expectations and the command's documented behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a repo is strictly behind the remote (`toPush=0, toPull>0`), `arb push` skips it with "behind origin (pull first?)". This skip is unconditional — `arb push --force` has no effect because the `--force` flag only gates the "diverged" case (`will-force-push` outcome) via `applyForcePushPolicy()`, not the "behind remote" case which is classified as a hard skip in `assessPushRepo()`.
8
+
9
+
The command's own help text says "Use --force when the remote has genuinely new commits that you want to overwrite", which users naturally expect to cover the behind-remote case. The real-world scenario: a collaborator force-pushed to your branch, or commits were added to the remote that you want to discard — you want to restore the remote to your local state.
10
+
11
+
## Options
12
+
13
+
### Keep the hard skip, require `arb pull` first
14
+
Leave the behind-remote skip unconditional. Users must pull (incorporating the remote commits) before they can push.
15
+
-**Pros:** Prevents accidental loss of remote-only commits.
16
+
-**Cons:** Makes `--force` misleading — it promises to override but doesn't. Forces users to pull commits they intend to discard. No workaround within `arb push`.
17
+
18
+
### Allow `--force` to override the behind-remote skip
19
+
When `--force` is passed and the repo is behind remote, classify it as `will-force-push` with `ahead: 0` instead of skipping. The push uses `--force-with-lease` (same as other force pushes).
20
+
-**Pros:** Matches user expectations and the command's documented behavior. Consistent with how `--force` works for diverged branches. `--force-with-lease` still protects against concurrent pushes.
21
+
-**Cons:** The `ahead: 0` case is unusual — requires special plan display text ("force push (overwrite N on origin)") and result text ("force pushed (overwrote remote)") to avoid confusing "0 commits" messages.
22
+
23
+
## Decision
24
+
25
+
Allow `--force` to override the behind-remote skip. Handle it in `assessPushRepo()` at the skip point, matching the existing pattern used by `--include-wrong-branch` and `--include-merged`.
26
+
27
+
## Reasoning
28
+
29
+
The fix follows the established pattern: options that override skips are checked at the skip point in `assessPushRepo()`. The alternative — converting skips back to pushable assessments in `applyForcePushPolicy()` — conflates two responsibilities (gating vs. ungating) and would require reconstructing assessment data that the skip discards.
30
+
31
+
The `--force-with-lease` safety net applies here just as it does for diverged pushes. If someone else pushes between fetch and push, the lease check rejects it.
32
+
33
+
## Consequences
34
+
35
+
-`arb push --force` now works for repos that are behind remote, overwriting remote-only commits.
36
+
- The plan display shows "force push (overwrite N on origin)" for this case, clearly communicating the consequence.
37
+
- Without `--force`, the behavior is unchanged — behind-remote repos are still skipped with "pull first?".
38
+
- The `--force-with-lease` protection applies, preventing accidental overwrites if the remote changes between fetch and push.
After a rebase, amend, or squash, `arb push` detects that all remote commits are outdated (already reflected in your local history) and pushes automatically with `--force-with-lease` — no `--force` flag needed. Use `--force`only when the remote has genuinely new commits from someone else.
32
+
After a rebase, amend, or squash, `arb push` detects that all remote commits are outdated (already reflected in your local history) and pushes automatically with `--force-with-lease` — no `--force` flag needed. Use `--force` when the remote has genuinely new commits that you want to overwrite — including when your local branch is strictly behind the remote and you want to roll it back to your local state.
33
33
34
34
When a collaborator force-pushes a rebased branch and you have no unique local commits to preserve, `arb pull --merge` shows a **safe reset** action in the plan and resets to the rewritten remote tip instead of attempting a three-way merge.
0 commit comments