Skip to content

Instantly share code, notes, and snippets.

@kathgironpe
Created June 25, 2026 00:42
Show Gist options
  • Select an option

  • Save kathgironpe/734e40565f1c240bd4c8d9cc16287e3c to your computer and use it in GitHub Desktop.

Select an option

Save kathgironpe/734e40565f1c240bd4c8d9cc16287e3c to your computer and use it in GitHub Desktop.
Issue #529 — Stack Rebase Runbook (run after PR #535 merged)

Issue #529 — Stack Rebase Runbook

Run this after PR #535 merged. It updates the remaining 6 PRs (#537–#542) so they're current and mergeable against the updated base. Verified against actual git state on 2026-06-25.

Current state (verified)

  • PR #535 merged via merge-commit 9421a816 into feature/issue-529-property-rental-cross-listing (the #536 base branch). The #535 head branch was deleted on merge.
  • 6 PRs remain, all targeting that base branch: #537 #538 #539 #540 #541 #542.
  • Because #535 was a merge-commit (not squash), rebasing each PR replays only that PR's own commits — git skips #535's already-merged commits.
  • Expect conflicts in api/lib/highlands/listings.ex (PR #535 rewrote the clone/delete region) and api/test/highlands/listings/listings_test.exs (PR #535 removed the clone/delete describe blocks into separate files).
  • #541 has two hard collisions (migration timestamp + docs) — see Step 5.

Setup (run once)

BASE=feature/issue-529-property-rental-cross-listing
git fetch origin --prune
git checkout main && git pull --ff-only

Step 1 — PR #537 (cross-listing link)

git checkout feature/issue-529-cross-listing-link
git reset --hard origin/feature/issue-529-cross-listing-link
git rebase --rebase-merges origin/$BASE
# If conflicts: edit the files, then repeat:
#   git add <resolved-files> && git rebase --continue
git push --force-with-lease origin feature/issue-529-cross-listing-link

Step 2 — PR #538 (create_rental_from_sale)

git checkout feature/issue-529-create-rental-from-sale
git reset --hard origin/feature/issue-529-create-rental-from-sale
git rebase --rebase-merges origin/$BASE
git push --force-with-lease origin feature/issue-529-create-rental-from-sale

Step 3 — PR #539 (also-available badge)

git checkout feature/issue-529-also-available-badge
git reset --hard origin/feature/issue-529-also-available-badge
git rebase --rebase-merges origin/$BASE
git push --force-with-lease origin feature/issue-529-also-available-badge

Step 4 — PR #540 (backfill linked_listing_id)

git checkout chore/issue-529-backfill-linked-listings
git reset --hard origin/chore/issue-529-backfill-linked-listings
git rebase --rebase-merges origin/$BASE
git push --force-with-lease origin chore/issue-529-backfill-linked-listings

Step 5 — PR #541 (upload-dedup) — CLEAN UP FIRST, then rebase

#541 carries a migration that collides by timestamp with #537/#542, plus docs that overlap #535's new foundation docs, plus 11 stray meta/docs commits. Clean it on the branch before rebasing:

git checkout feature/issue-529-upload-dedup
git reset --hard origin/feature/issue-529-upload-dedup

# 1. Squash the dedup work (commit f5b87a03 + the 11 stray commits) into ONE clean commit.
#    f5b87a03 is the dedup commit; reset --soft to its parent stages all of it:
git reset --soft f5b87a03^
git rm api/priv/repo/migrations/20260622000001_add_cross_listing_and_content_hash.exs
git rm -r docs/features/property-rental-cross-listing docs/features/image-dedup
git commit -m "feat(images): Add upload-level dedup via SHA-256 content hash"

# 2. Now rebase onto the updated base
git rebase --rebase-merges origin/$BASE
# Resolve conflicts:
#   - migration: keep #537/#542's split migration, drop #541's combined one (already removed above)
#   - docs: keep #536's foundation docs, drop #541's versions
#   - listings.ex / listings_test.exs: favor the #536 versions for the clone/delete region
git push --force-with-lease origin feature/issue-529-upload-dedup

Why remove the migration: 20260622000001_add_cross_listing_and_content_hash.exs shares version 20260622000001 with 20260622000001_add_linked_listing_to_listings.exs (#537/#542). Ecto rejects duplicate versions. The content_hash column comes from #542's 20260622000002_add_content_hash_to_listing_images.exs instead.

Step 6 — PR #542 (content-hash backfill) — last

git checkout chore/issue-529-backfill-content-hashes
git reset --hard origin/chore/issue-529-backfill-content-hashes
git rebase --rebase-merges origin/$BASE
git push --force-with-lease origin chore/issue-529-backfill-content-hashes

Conflict resolution pattern (any step)

# When a rebase stops on a conflict:
git status                       # see conflicted files
# edit each conflicted file to resolve
git add <resolved-files>
git rebase --continue            # repeat until "Successfully rebased"

# To ABORT a messed-up rebase and start over:
git rebase --abort

Verify after each rebase (must be green before moving on)

cd api
mix test                         # full suite, 0 failures
mix credo.safe --all             # must report: found no issues
mix ex_dna                       # must report: No code duplication detected
mix ecto.migrate                 # must NOT error with "multiple migrations with version 20260622000001"

If mix ecto.migrate errors on a duplicate version, the migration collision (Step 5) was not fully resolved — remove the duplicate migration file and re-run.

Merge order (after every PR is rebased and green)

Merge into the #536 base branch in dependency order, then land #536 on main last:

gh pr merge 537 --merge --base $BASE
gh pr merge 538 --merge --base $BASE
gh pr merge 539 --merge --base $BASE
gh pr merge 540 --merge --base $BASE
gh pr merge 541 --merge --base $BASE
gh pr merge 542 --merge --base $BASE
gh pr merge 536 --merge --base main      # land the whole feature on main

(You can --squash instead of --merge if you prefer linear history — but the rebases above assume #535's merge-commit is already in the base, which it is.)

Safety notes

  • Always --force-with-lease (never bare --force) and --rebase-merges (per .claude/rules/workflow-git-rebase-safety.md).
  • The git hooks (./scripts/install-git-hooks.sh) auto-create timestamped backups before each rebase and block bare git rebase on branches with merge commits.
  • #536 itself needs NO update — it's the base and already contains #535.
  • You don't have to merge each PR between rebases, but doing so means each later rebase replays fewer commits (fewer conflict surfaces).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment