fix(release-workflow): use regular merge for dev/main sync after squash-merge#1490
Conversation
…sh-merge
The previous `--ff-only` strategy failed because main's squash commit has a
different SHA than dev's release commit, so dev was never fast-forwardable.
A reset-based "rewrite dev's history to match main" approach was tried and
rejected: it blows up every open PR targeting dev. Their merge-base shifts
to a much older commit, and their diffs balloon with all the release
content. Confirmed today: PRs that were +80/-1 became +6626/-300.
Use a regular merge instead (matches `/release` SKILL Step 9):
git checkout dev
git pull origin main --no-edit
git push origin dev
This creates a merge commit on dev that ties main's squash into dev's
history. Open PRs' merge-bases stay at their original commits, their diffs
stay small, no history is rewritten. The cost is a merge bubble in dev's
log, which is the right trade-off.
Same pattern applied to commit-formula's dev-sync section.
`commit-formula` also gets a `git stash push` before its `git checkout
main` — the previous step (`fetch-and-update-formula`) leaves the formula
file dirty, which blocks `git checkout` until stashed.
KNOWN ISSUE not fixed by this PR: the workflow's formula-update steps
(`fetch-and-update-formula` + `commit-formula`) duplicate CI's
`update-homebrew` job in `.github/workflows/release.yml`. They race each
other on the dev push. See #1489 for the full analysis and architectural
fix (drop the duplicated steps from this workflow). This PR addresses the
mechanical bugs that prevented the workflow from completing at all.
📝 WalkthroughWalkthroughThe release workflow is modified to handle SHA divergence between Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.archon/workflows/experimental/archon-release.yaml:
- Around line 841-846: The workflow currently mutates main by running git
checkout main, committing homebrew/archon.rb and pushing to origin main; change
it to create a new branch (e.g., refs/heads/release-homebrew-$ver or use the
existing dev flow), apply the file changes there, push that branch, and open a
pull request instead of pushing to main, or alternatively invoke the existing
release CI job that has permissions to update main; update the steps that
reference git checkout main, git commit -m "chore(homebrew): update formula to
v$ver", and git push origin main to instead create/checkout a new branch, git
add/commit on that branch, git push origin <branch>, and trigger a PR or the
release CI path so the update flows through dev → main review instead of
mutating main directly.
- Around line 843-846: Before running git commit/push for the Homebrew formula
update, check whether there are staged changes to homebrew/archon.rb and skip
the commit if none exist: after running git add homebrew/archon.rb, run a
staged-diff check (e.g., using git diff --staged --quiet or git diff --cached
--exit-code) and only invoke git commit -m "chore(homebrew): update formula to
v$ver" and git push origin main when that check indicates a non-empty staged
diff; otherwise log/echo that main is already up-to-date and skip the
commit/push steps.
- Around line 650-652: The workflow uses the command "git pull origin main
--no-edit" which can perform a rebase depending on runner config; replace each
occurrence of that command with an explicit fetch followed by a merge (i.e., run
"git fetch origin main" then "git merge --no-edit origin/main") so merge
semantics are forced and deterministic; update both places where "git pull
origin main --no-edit" appears to use this fetch+merge sequence.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 93dafd82-61b8-4b50-b10f-75c482eb9d76
📒 Files selected for processing (1)
.archon/workflows/experimental/archon-release.yaml
| git checkout dev | ||
| git pull origin main --ff-only --quiet | ||
| git pull origin main --no-edit | ||
| git push origin dev |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Does git pull origin main --no-editstill honorpull.rebase/branch..rebase, and is git fetch origin main && git merge --no-edit FETCH_HEAD(orgit pull --no-rebase) the correct way to force a merge commit?
💡 Result:
No, git pull origin main --no-edit still honors pull.rebase or branch.main.rebase configurations. The --no-edit option only affects whether an editor is opened for the merge commit message during a merge (it is passed to git merge); it does not override the rebase/merge decision made by pull.rebase (true/false) or --rebase/--no-rebase. If pull.rebase is true (or branch.main.rebase is true), git pull origin main --no-edit will fetch and then rebase onto origin/main (non-interactively, without editing rebase messages if applicable), not create a merge commit. Yes, git fetch origin main && git merge --no-edit FETCH_HEAD (or equivalently git pull origin main --no-rebase --no-edit) is the correct way to force a merge commit (accepting the auto-generated message without editing). This performs fetch + merge (skipping editor), overriding any rebase configuration.
Citations:
- 1: https://git-scm.com/docs/git-pull/2.32.0.html
- 2: https://www.kernel.org/pub/software/scm/git/docs/git-pull.html
- 3: https://git-scm.com/docs/git-pull/2.35.0.html
- 4: https://github.com/git/git/blob/e0bfec3dfc356f7d808eb5ee546a54116b794397/Documentation/git-pull.adoc
- 5: https://git-scm.com/docs/git-merge.html
- 6: https://git-scm.com/docs/git-pull.html
Use explicit fetch + merge to ensure deterministic merge behavior.
Lines 651 and 852 use git pull origin main --no-edit, which still respects pull.rebase and branch.*.rebase configurations. On runners configured for rebase pulls, this produces a rebase instead of a merge commit, undoing the intended sync behavior. Use git fetch + git merge --no-edit to force merge semantics:
Suggested change
git checkout dev
- git pull origin main --no-edit
+ git fetch origin main --quiet
+ git merge --no-edit FETCH_HEAD
git push origin dev📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| git checkout dev | |
| git pull origin main --ff-only --quiet | |
| git pull origin main --no-edit | |
| git push origin dev | |
| git checkout dev | |
| git fetch origin main --quiet | |
| git merge --no-edit FETCH_HEAD | |
| git push origin dev |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.archon/workflows/experimental/archon-release.yaml around lines 650 - 652,
The workflow uses the command "git pull origin main --no-edit" which can perform
a rebase depending on runner config; replace each occurrence of that command
with an explicit fetch followed by a merge (i.e., run "git fetch origin main"
then "git merge --no-edit origin/main") so merge semantics are forced and
deterministic; update both places where "git pull origin main --no-edit" appears
to use this fetch+merge sequence.
| git checkout main | ||
| git pull origin main --ff-only --quiet | ||
| git stash pop | ||
| git add homebrew/archon.rb | ||
| git commit -m "chore(homebrew): update formula to v$ver" | ||
| git push origin main |
There was a problem hiding this comment.
Avoid mutating main from this workflow.
This block still checks out main, commits on it, and pushes directly to it. That bypasses the repo’s documented dev → main flow and keeps formula updates outside the normal review path. Prefer routing the formula update through a PR or handing it off entirely to the existing release CI path.
Based on learnings: Never commit directly to main branch; main is the release branch, dev is the working branch; all feature work branches off dev and merges back to dev.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.archon/workflows/experimental/archon-release.yaml around lines 841 - 846,
The workflow currently mutates main by running git checkout main, committing
homebrew/archon.rb and pushing to origin main; change it to create a new branch
(e.g., refs/heads/release-homebrew-$ver or use the existing dev flow), apply the
file changes there, push that branch, and open a pull request instead of pushing
to main, or alternatively invoke the existing release CI job that has
permissions to update main; update the steps that reference git checkout main,
git commit -m "chore(homebrew): update formula to v$ver", and git push origin
main to instead create/checkout a new branch, git add/commit on that branch, git
push origin <branch>, and trigger a PR or the release CI path so the update
flows through dev → main review instead of mutating main directly.
| git stash pop | ||
| git add homebrew/archon.rb | ||
| git commit -m "chore(homebrew): update formula to v$ver" | ||
| git push origin main |
There was a problem hiding this comment.
Skip the commit when main is already up to date.
This path still overlaps the separate Homebrew-update flow. If main already has the same homebrew/archon.rb by the time Line 844-Line 846 run, git commit exits non-zero on an empty index and the release fails even though the repo is already in the desired state. Guard the commit/push with a staged-diff check.
Suggested change
git stash pop
git add homebrew/archon.rb
- git commit -m "chore(homebrew): update formula to v$ver"
- git push origin main
+ if git diff --cached --quiet; then
+ echo "Formula already up to date on main"
+ else
+ git commit -m "chore(homebrew): update formula to v$ver"
+ git push origin main
+ fi🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.archon/workflows/experimental/archon-release.yaml around lines 843 - 846,
Before running git commit/push for the Homebrew formula update, check whether
there are staged changes to homebrew/archon.rb and skip the commit if none
exist: after running git add homebrew/archon.rb, run a staged-diff check (e.g.,
using git diff --staged --quiet or git diff --cached --exit-code) and only
invoke git commit -m "chore(homebrew): update formula to v$ver" and git push
origin main when that check indicates a non-empty staged diff; otherwise
log/echo that main is already up-to-date and skip the commit/push steps.
…main sync (#1492) The SKILL's Step 9 already uses the correct primitive (`git pull origin main`, which creates a regular merge commit), but doesn't explicitly warn against the two trap doors that bit us during v0.3.10: 1. `git pull origin main --ff-only` — used by the experimental archon-release workflow's sync-dev-with-main step. Fast-forward is impossible across a squash merge; the workflow aborted on every release run. 2. `git reset --hard origin/main` — used during today's recovery as a "clean up the merge commit" workaround for #1. It worked locally but rewriting dev's history severed every open PR's merge-base, ballooning their diffs from <100 lines to thousands. Confirmed: PR #1444 went from +80/-1 to +6626/-300, restored after a recovery merge that re-attached the original release commits to dev. Add explicit DO-NOT block under the existing "Important" callout. Also document the conflict-resolution gotcha: when the merge conflicts on homebrew/archon.rb, use `git checkout origin/main -- ...` (NOT local `main`, which is typically stale because the release pushes via `git push origin dev:main` without fast-forwarding local main). The workflow-level fixes for both traps landed in #1490. This is the documentation companion so a future maintainer (or AI agent) doesn't repeat either trap.
…sh-merge (coleam00#1490) The previous `--ff-only` strategy failed because main's squash commit has a different SHA than dev's release commit, so dev was never fast-forwardable. A reset-based "rewrite dev's history to match main" approach was tried and rejected: it blows up every open PR targeting dev. Their merge-base shifts to a much older commit, and their diffs balloon with all the release content. Confirmed today: PRs that were +80/-1 became +6626/-300. Use a regular merge instead (matches `/release` SKILL Step 9): git checkout dev git pull origin main --no-edit git push origin dev This creates a merge commit on dev that ties main's squash into dev's history. Open PRs' merge-bases stay at their original commits, their diffs stay small, no history is rewritten. The cost is a merge bubble in dev's log, which is the right trade-off. Same pattern applied to commit-formula's dev-sync section. `commit-formula` also gets a `git stash push` before its `git checkout main` — the previous step (`fetch-and-update-formula`) leaves the formula file dirty, which blocks `git checkout` until stashed. KNOWN ISSUE not fixed by this PR: the workflow's formula-update steps (`fetch-and-update-formula` + `commit-formula`) duplicate CI's `update-homebrew` job in `.github/workflows/release.yml`. They race each other on the dev push. See coleam00#1489 for the full analysis and architectural fix (drop the duplicated steps from this workflow). This PR addresses the mechanical bugs that prevented the workflow from completing at all.
…main sync (coleam00#1492) The SKILL's Step 9 already uses the correct primitive (`git pull origin main`, which creates a regular merge commit), but doesn't explicitly warn against the two trap doors that bit us during v0.3.10: 1. `git pull origin main --ff-only` — used by the experimental archon-release workflow's sync-dev-with-main step. Fast-forward is impossible across a squash merge; the workflow aborted on every release run. 2. `git reset --hard origin/main` — used during today's recovery as a "clean up the merge commit" workaround for #1. It worked locally but rewriting dev's history severed every open PR's merge-base, ballooning their diffs from <100 lines to thousands. Confirmed: PR coleam00#1444 went from +80/-1 to +6626/-300, restored after a recovery merge that re-attached the original release commits to dev. Add explicit DO-NOT block under the existing "Important" callout. Also document the conflict-resolution gotcha: when the merge conflicts on homebrew/archon.rb, use `git checkout origin/main -- ...` (NOT local `main`, which is typically stale because the release pushes via `git push origin dev:main` without fast-forwarding local main). The workflow-level fixes for both traps landed in coleam00#1490. This is the documentation companion so a future maintainer (or AI agent) doesn't repeat either trap.
Summary
archon-releaseworkflow'ssync-dev-with-mainandcommit-formulasteps both usedgit pull origin main --ff-onlyto bring dev in line with main after the squash-merge. Fast-forward is impossible across a squash merge (main's squash commit has a different SHA than the release commit on dev), so the workflow aborted atsync-dev-with-mainon every release run.commit-formulahad a second bug:git checkout mainrefused whilehomebrew/archon.rbwas still dirty from the prior step.--ff-onlyin both steps with a regular merge:git pull origin main --no-edit(matches the/releaseSKILL's Step 9). This creates a merge commit on dev that ties main's squash into dev's history without rewriting anything.git stash pushtocommit-formulabefore itsgit checkout mainso the dirtyhomebrew/archon.rb(and any in-progress recovery edits to other tracked files) gets carried across the branch switch instead of blocking it.fetch-and-update-formulaandcommit-formulasteps still duplicate CI'supdate-homebrewjob — see bug(release-workflow): sync-dev-with-main race-clobbers CI's update-homebrew formula commit #1489 for the full analysis. This PR addresses the mechanical bugs that prevented the workflow from completing at all; the architectural duplication is fixed in bug(release-workflow): sync-dev-with-main race-clobbers CI's update-homebrew formula commit #1489.Why not a "rewrite dev to match main" approach
The first iteration of this fix replaced
--ff-onlywithgit reset --hard origin/main && git push --lease. It "worked" in that the workflow completed, but rewriting dev's history broke every open PR targeting dev. Their merge-bases shifted to much older commits, and their diffs ballooned with the release content. Confirmed today on PRs that went from +80/-1 to +6626/-300 across many files. Don't do that.The regular-merge approach preserves history, costs only a merge bubble in dev's log, and is what the SKILL has always done.
Linked Issue
Validation Evidence
sync-dev-with-mainandcommit-formulafailed with the exact errors this PR fixes./releaseSKILL, then verified with/test-release brew 0.3.10and/test-release curl-mac 0.3.10. All 8 e2e smoke tests also pass on the brew-installed v0.3.10 binary (archon-stable).Security Impact
Compatibility / Migration
Human Verification
git pull origin main --no-editwas used during today's recovery to merge main into dev cleanly. Thegit stash pushpattern was applied during recovery as well.Side Effects / Blast Radius
.archon/workflows/experimental/archon-release.yaml. No other workflows, no engine, no docs.git stash pushincommit-formulawill carry across any tracked-file edits the operator has in flight when the workflow runs. They reappear aftergit stash popand remain uncommitted; onlyhomebrew/archon.rbis staged for the formula commit.set -euo pipefailin both steps means any sub-command failure aborts the step.Rollback Plan
git revertthis commit. The workflow goes back to its pre-PR state, which was already broken.sync-dev-with-mainfails with "Not possible to fast-forward".Risks and Mitigations
git logwill accumulate merge bubbles after each release. Some teams prefer linear dev history.update-homebrewdocumented in bug(release-workflow): sync-dev-with-main race-clobbers CI's update-homebrew formula commit #1489 still exists.Summary by CodeRabbit