feat(update): updates.parked_branch_strategy gates the in-place merge; switch stays the default
Adapts the in-place branch update from PR #89507 (@willfrombr) onto the switch-by-default behavior: the deterministic switch path remains the default so non-interactive updates (desktop, gateway, cron) never dead-end on a merge conflict, and deliberate custom-branch users opt in with updates.parked_branch_strategy: update_in_place. --switch-branch overrides the in-place strategy for one run (deep feature branches that must not accumulate update merge commits). Docs + config comments + tests cover all three routes. Co-authored-by: Willian Santos <285090322+willfrombr@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
willfrombr
|
||||
@@ -3265,6 +3265,25 @@ DEFAULT_CONFIG = {
|
||||
# checkout stayed days behind main on a stale branch). Set false to
|
||||
# never auto-switch.
|
||||
"auto_switch_parked_branch": True,
|
||||
# HOW a clean parked branch with unmerged commits is handled:
|
||||
# "switch" (default) — switch to the update target; the commits
|
||||
# stay on the branch (git checkout never
|
||||
# discards committed work) and a loud notice
|
||||
# names the branch + count. Deterministic —
|
||||
# never conflicts — so desktop/gateway/cron
|
||||
# updates always land on current code.
|
||||
# "update_in_place" — for a deliberately maintained custom branch
|
||||
# (local patches on top of main): merge
|
||||
# origin/<target> INTO the branch instead.
|
||||
# The checkout never moves and local commits
|
||||
# survive; a conflict stops the update
|
||||
# cleanly with nothing changed. A safety tag
|
||||
# (pre-update-<stamp>) is left before the
|
||||
# merge. `hermes update --switch-branch`
|
||||
# overrides back to the switch path for one
|
||||
# run (e.g. a deep feature branch that must
|
||||
# not accumulate update merge commits).
|
||||
"parked_branch_strategy": "switch",
|
||||
# Refresh an already-installed cua-driver during `hermes update`.
|
||||
# The refresh is best-effort and macOS-only. Turn this off if the
|
||||
# upstream installer is not appropriate for the machine, for example
|
||||
|
||||
@@ -89,14 +89,14 @@ def build_update_parser(subparsers, *, cmd_update: Callable) -> None:
|
||||
action="store_true",
|
||||
default=False,
|
||||
help=(
|
||||
"When the checkout sits on a branch carrying unmerged commits, "
|
||||
"switch to the update target and update THERE instead of merging "
|
||||
"the target into the branch in place. The branch is left exactly "
|
||||
"as it was — no merge commit is written into its history. Use on "
|
||||
"long-lived feature branches where an update-driven merge commit "
|
||||
"would pollute the branch; the default in-place behaviour suits "
|
||||
"branches that track the target with a small patch set. Still "
|
||||
"refuses to touch a dirty tree."
|
||||
"With updates.parked_branch_strategy: update_in_place configured, "
|
||||
"override it for this run: switch to the update target and update "
|
||||
"THERE instead of merging the target into the checked-out branch. "
|
||||
"The branch is left exactly as it was — no merge commit is written "
|
||||
"into its history. Use on long-lived feature branches where an "
|
||||
"update-driven merge commit would pollute the branch. No effect "
|
||||
"under the default strategy (switch), which already switches. "
|
||||
"Still refuses to touch a dirty tree."
|
||||
),
|
||||
)
|
||||
update_parser.add_argument(
|
||||
|
||||
@@ -49,6 +49,8 @@ If the source checkout was left sitting on a feature branch (by tooling, a workt
|
||||
- **Branch fully merged** (every commit already contained in `origin/main` — `git cherry` reports nothing unmerged): the update says so — `Checkout was parked on '<branch>' (fully merged) — switched back to main` — and stays on `main` afterwards.
|
||||
- **Branch has unmerged commits** but the tree is clean: the update still switches to `main` so the update can proceed — this is what non-interactive callers (the desktop update button, gateway `/update`, cron) rely on, since they have no way to resolve a skip. Your commits are untouched: `git checkout` never discards committed work, and the update prints a loud notice naming the branch and commit count, plus the `git checkout <branch>` command to pick the work back up later.
|
||||
|
||||
If you *deliberately* run a custom branch (local patches maintained on top of main), set `updates.parked_branch_strategy: update_in_place` in `config.yaml`. The update then merges `origin/main` **into** your branch instead of switching away from it — the checkout never moves, your commits survive, and the running code advances. Fast-forward when possible; on divergence a true merge behind a `pre-update-<stamp>` safety tag, stopping cleanly (nothing changed) on conflict. `hermes update --switch-branch` overrides back to the switch path for one run — useful on a deep feature branch that must not accumulate update-driven merge commits.
|
||||
|
||||
When the parked branch has **uncommitted changes** (dirty tree), Hermes does **not** touch it. The code update is marked **SKIPPED** with a loud warning naming the branch, how far behind `origin/main` it is, and the exact commands to resolve — instead of pretending the update succeeded. The completion line always shows the actual branch and HEAD (`✓ Update complete! [main @ 30fcf9580]`) so drift is visible at a glance. Set `updates.auto_switch_parked_branch: false` in `config.yaml` to disable the auto-switch entirely (the skip warning still fires).
|
||||
|
||||
### Local changes on non-interactive updates
|
||||
|
||||
Reference in New Issue
Block a user