| name | re-main |
| description | Re(base) main — rebase the current branch on the repo's default branch (`origin/main`, or `origin/master` where that's the name) end-to-end — runs the git rebase, auto-resolves conflicts in the project's known auto-generated files, renames branch-added alembic migrations to today's date, regenerates the alembic chain when needed, and re-runs codegen plus the frontend build so generated artifacts reflect the rebased source. Use when the user says "re-main", "rebase on main", or "rebase my branch", or after working on a long-lived feature branch and wanting to pull in main. Full flow when the project has the generated files listed in the skill; otherwise a safe rebase with no auto-resolution. |
| allowed-tools | ["Bash","Edit","Read","Glob","Grep","AskUserQuestion"] |
Rebase on main
One invocation, full flow: git rebase + project-specific cleanup.
Detect the project
Default branch. Find it before anything else:
git symbolic-ref --short refs/remotes/origin/HEAD
(If that's unset, use git remote show origin and read the "HEAD branch" line.) Every command below is written for main — substitute master (or whatever came back) throughout if the repo differs.
Capabilities. Each later section applies only if its files exist in the repo:
demo/days/*.sql / demo/days/*.sorted snapshots → the demo conflict auto-resolution and the demo regeneration note.
backend/src/*/openapi.yaml with a generated frontend/src/Api/Data.elm → the codegen conflict auto-resolution and the regen step.
backend/src/*/db/versions/ → the alembic sections.
codegen / dist / check targets in the backend and frontend Makefiles → the regen and verify commands.
If none apply, do pre-flight and the rebase only: auto-resolve nothing — every conflict goes to the user — then run whatever check/build targets the project's Makefile or README documents, and report.
Auto-resolution principle: take main's side only for files that are fully regenerated by a build step. Never extend the generated-file list by guessing — if an unlisted file looks generated, ask.
Pre-flight
Fetch first, so every check below runs against fresh refs:
git fetch origin main
Refuse to start unless all of these hold. If any fails, explain the problem and stop.
git status shows a clean working tree (no staged or unstaged changes, no conflicting untracked files). If dirty, tell the user to commit or stash first — never auto-stash.
- Current branch is not the default branch. If it is, stop.
- The branch has commits ahead of
origin/main. If git rev-list --count origin/main..HEAD is 0, the branch has nothing to rebase; say so and stop.
- Main has moved. If
git rev-list --count HEAD..origin/main is 0, the branch is already on top of main — say so and stop.
Plan the work
Look at what main added since the branch diverged so you know what regeneration to expect later:
BASE=$(git merge-base HEAD origin/main)
git diff --name-only "$BASE" origin/main
Note whether main's diff contains any of:
backend/src/*/db/versions/*.py — new alembic migration on main
demo/days/*.sql or demo/days/*.sorted — demo snapshot changes
backend/src/*/openapi.yaml — API spec changes
State the plan in one short paragraph before running the rebase so the user can sanity-check it.
Run the rebase
git rebase origin/main
Loop until rebase completes or you hit a conflict that needs the user. After each git rebase --continue, re-check for the next conflict.
The two auto-resolutions below apply only to the generated files detected in "Detect the project".
Conflict only in demo/days/*.sql / demo/days/*.sorted — take main's version. These are auto-generated; hand-merging them produces nonsense.
git checkout --ours -- demo/days/
git add demo/days/
git rebase --continue
(During a rebase, --ours is the upstream side = main's version, --theirs is the commit being replayed.)
Conflict in frontend/src/Api/Data.elm — take main's version; it'll be regenerated below.
git checkout --ours -- frontend/src/Api/Data.elm
git add frontend/src/Api/Data.elm
git rebase --continue
Conflict in any hand-written file (source code, openapi.yaml, migration files, anything else) — stop. Run git status to surface conflicts and ask the user how to resolve. Do not guess; the source of truth is the user's intent on the branch versus main's intent.
If the rebase is unrecoverable, run git rebase --abort to restore ORIG_HEAD and report what went wrong.
Update branch migration dates
If the branch added any alembic migrations, their filename date prefix and Create Date: docstring still reflect when the branch was first cut — which can be weeks ago. Rename them and update the comment so they sort chronologically after main's latest migration.
List branch-added migrations:
git diff --name-only --diff-filter=A origin/main...HEAD -- 'backend/src/*/db/versions/'
If empty, skip this section. Otherwise, for each file YYYY_MM_DD_<revision>_<name>.py:
- Get today's date in both formats:
date +%Y_%m_%d (filename) and date +%Y-%m-%d (comment).
- Rename the file: replace the leading
YYYY_MM_DD_ with today's date (keep the revision and name parts unchanged).
- Edit the
Create Date: YYYY-MM-DD HH:MM:SS.NNNNNN line in the docstring: replace only the date portion with today's; keep the time portion as-is (it's arbitrary, and changing it would falsely imply alembic was re-run).
Use git mv for the rename so the file history is preserved.
Skip any file whose date prefix is already today.
Alembic migration rebase
Skip this entire section if the branch added no migrations:
git diff --name-only --diff-filter=A origin/main...HEAD -- 'backend/src/*/db/versions/'
If empty, jump to "Regenerate codegen".
Static graph check
Pre-check the migration graph statically — no DB, no nix-shell needed — to catch a stale down_revision left by the rebase:
python backend/src/*/scripts/check_migrations.py
(Skip the static check if the script doesn't exist — not every project has it. Still run the DB verification below.)
OK: N migrations form a single valid chain. — graph is fine, move on to DB verification.
Multiple Alembic heads or references revision '<rev>', which does not exist — the rebase left a stale down_revision. Fix it:
- Find main's new head:
cd backend && nix-shell --run "alembic -c etc/development.ini heads"
- Edit the earliest branch-added migration's
down_revision = "..." to point to main's new head. Don't touch the chain of branch migrations after that — they stay chained to each other.
- Re-run the static graph check and confirm it prints
OK: .... If not, fix and re-run before touching the DB.
DB verification
Run the branch's migration against a freshly-seeded main DB. This catches real schema conflicts the static check can't see (e.g. same column added on both sides) and validates the migration against the schema state production will be in.
- Make sure Postgres is running. If
pg_isready fails (or the equivalent), start it:
cd backend && nix-shell --run "make up"
- Seed the local DB to main's current schema. Since we're on the feature branch, it's safe to hard-reset local
main to origin/main:
BRANCH=$(git branch --show-current)
git fetch origin main:main
git checkout main
cd backend && nix-shell --run "make devdb"
git checkout "$BRANCH"
(git fetch origin main:main updates local main to origin/main without checking out — works even when local main has diverged, since we're not on it. If that fails for any reason, fall back to git checkout main && git reset --hard origin/main.)
- Apply the branch migrations on top:
cd backend && nix-shell --run "alembic -c etc/development.ini upgrade head"
If alembic upgrade head fails, stop and report — the migration has a real conflict with main's schema, which needs user judgment.
If make devdb fails, the DB verification is meaningless; flag it in the final summary so the user knows the branch migration is unverified.
Regenerate codegen + rebuild frontend
If the project has the codegen and dist targets, always run these two, in this order — regardless of what main changed. Running make codegen first guarantees frontend/src/Api/Data.elm matches the rebased openapi.yaml, which then lets make dist compile cleanly in a single pass (no "run it twice" workaround). Always through nix-shell, not devenv or make directly — devenv has a stale-cache issue that produces "unknown alias" / missing-constructor errors after openapi-generator runs.
cd backend && nix-shell --run "make codegen"
cd frontend && nix-shell --run "make dist"
This also ensures backend/src/*/static/dist reflects the rebased source — any change main brought in to a .elm file or tailwind.config.js gets picked up.
Demo SQL regeneration
If demo/days/*.sql was touched on either side (or you took main's during conflict resolution), the snapshots no longer reflect the branch's state.
Don't run make demo yourself — it needs an interactive browser session and is slow. Surface it as the explicit next step in the final summary instead.
Verify
cd backend && nix-shell --run "make check"
cd frontend && nix-shell --run "make check"
If either reports a diff on a generated file, that means a regen step above was skipped. Re-run the right step rather than git checkout-ing the diff away — the diff is the signal.
Output
End with:
- Branch name and what was rebased:
N commits replayed on top of origin/main at <SHA>.
- What from main triggered branch-specific work (alembic chain fixups, demo SQL conflicts). Note that
make codegen and make dist are always run when present, so no need to call them out unless they failed.
- Conflicts encountered and how they were resolved (auto-taken from main, or user-resolved).
- Whether
make check is clean in the affected subdirectories.
Do not push, force-push, or amend. Leave the post-rebase working-tree changes (renamed migrations, regenerated codegen) uncommitted on purpose: the intended flow is that the user amends them — together with fresh demo snapshots, if any — into the branch commits before pushing.
If demo snapshots are stale, close by asking explicitly: will the user run make demo now (then amend everything together), or amend and push without it?