Skip to content

feat(update): rebase local commits instead of discarding on update - #4142

Closed
GratefulDave wants to merge 1 commit into
NousResearch:mainfrom
GratefulDave:feat/update-rebase-local-commits
Closed

feat(update): rebase local commits instead of discarding on update#4142
GratefulDave wants to merge 1 commit into
NousResearch:mainfrom
GratefulDave:feat/update-rebase-local-commits

Conversation

@GratefulDave

Copy link
Copy Markdown
Contributor

Problem

When hermes update is run and the local branch has commits ahead of origin/main (e.g. cherry-picked patches, local plugin hooks, config customizations), the update flow does git reset --hard origin/main — silently destroying all local commits.

This is especially painful for users who:

  • Maintain local patches on top of Hermes (plugins, hooks, provider fixes)
  • Cherry-pick features from PRs before they merge
  • Have any local customization committed to their main branch

Fix

Detect local commits before pulling. When fast-forward fails:

  1. Local commits existgit rebase origin/main to replay local commits on top of the new upstream
    • If rebase hits conflicts → abort cleanly, report which commits are affected, and give manual resolution instructions
    • Never silently discard or auto-resolve
  2. No local commits (pure divergence from upstream force-push) → git reset --hard origin/main (same as before)
  3. ff-only succeeds → show notification if local commits were preserved alongside upstream updates

Before / After

Before: hermes update with 1 local commit → commit silently destroyed, user confused

After: hermes update with 1 local commit → rebase preserves it, user sees:

→ Found 12 new commit(s)
→ Pulling updates...
  ⚠ Fast-forward not possible (have 1 local commit(s)), rebasing...
  → Updating Python dependencies...

Or if conflicts:

✗ Rebase failed due to merge conflicts.
  Your 1 local commit(s) were NOT lost.
  Stashed changes are preserved (ref: abc123).

  To resolve manually:
    git rebase origin/main
    # fix conflicts, then: git rebase --continue
    git stash apply abc123

Testing

  • Local commits + upstream update: rebase succeeds, commits preserved
  • Local commits + conflicting upstream update: rebase aborts, clear instructions
  • No local commits + diverged: reset --hard (unchanged behavior)
  • No local commits + ff succeeds: normal update (unchanged)

When `hermes update` detects local commits on the branch (ahead of
origin/main), the existing flow does `git reset --hard origin/main`,
silently destroying the user's local commits. This is destructive for
users who cherry-pick or commit local customizations (plugins, hooks,
config patches).

Changes:
- Detect local commits ahead of origin before pulling
- When ff-only fails and local commits exist, try `git rebase` to
  preserve them on top of the new upstream
- If rebase hits conflicts, abort cleanly with instructions for manual
  resolution (never auto-resolve with --strategy-option theirs/ours)
- Fall back to `git reset --hard` only when there are no local commits
  (pure divergence from upstream force-push)
- Show notification when local commits are preserved alongside upstream
  updates
@GratefulDave

Copy link
Copy Markdown
Contributor Author

Closing — needs a fresh rebase against current main. Will resubmit if still relevant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants