Skip to content

[sync] Always overwrote synced files, and deleted each file once, since the last merged sync. - #9

Merged
SgtSwagrid merged 1 commit into
mainfrom
feature_simple_sync
Oct 26, 2026
Merged

SgtSwagrid merged 1 commit into
mainfrom
feature_simple_sync

Conversation

@SgtSwagrid

Copy link
Copy Markdown
Owner

Summary

Replaces the provenance rule of #7 and #8 with a simpler model:

  • Updates: every sync copies every non-ignored file, overwriting whatever the target has.
  • Deletions: each file the source deletes is deleted from the target once. A sync deletes the files the source has deleted since the source commit of the last sync from it that the target merged.
  • Opting out: only through ignore.

Measuring deletions from the last merged sync, rather than from the push that triggered the run, means:

  • a sync run that's skipped or fails is made up for by the next;
  • a sync PR rebuilt by later pushes keeps every deletion;
  • a file the target re-adds after a deletion was merged is left alone.

All the provenance and history comparison is gone.

Changes

  • scripts/last-sync.sh (new, its own workflow step): finds the source commit of the last sync this target merged, and exports it as SOURCE_SYNCED.
    • It reads the new GitHub-Graph-Source trailer on this source directory's commit in the most recently merged sync PR. GitHub keeps PR commits after a merge, whether squashed or not and with the branch deleted.
    • It searches the latest 20 merged sync PRs; 50 exceeded GitHub's GraphQL node limit.
    • With no such PR (the first sync, or syncs made before this version), it falls back to the commit before the triggering push, so that push's own deletions still go through. Without that either, it syncs no deletions.
  • scripts/merge-files.sh: copies every non-ignored file in the source root, as before [sync] Deleted a file whose last change came from the source, however it first arrived. #7. It then deletes the target's copy of each file deleted between SOURCE_SYNCED and the source's head (git diff --diff-filter=D), skipping ignored files. If that commit isn't in the source's history (say, after a force push), it warns and skips deletions. Over 90 lines are gone: the per-file history walks, the state map and the Kept reasons.
  • scripts/publish.sh:
    • Each sync commit now also carries GitHub-Graph-Source: <source commit>, after the key trailer. The PR body, which drops everything from the key trailer on, is unaffected.
    • replay() goes back to applying every change as it is. No carry-forward is needed: this source's commit is rebuilt each time from everything since the last merged sync.
    • The key calculation moved to load-config.sh.
  • scripts/load-config.sh: exports the source directory's key (SYNC_KEY) and the two trailer names, for last-sync.sh and publish.sh.
  • .github/workflows/sync.yml: a "Find last sync" step before "Merge files", given the target's token and github.event.before.
  • README.md: "Which files are synced" describes the model: copy everything, delete once since the last merged sync, opt out with ignore, and what a skipped run, a re-added file and a closed PR mean. "Merge semantics" says again that files are overwritten, that downstream changes are lost unless ignored, and that the most recent source wins.
  • templates/pull-request-body.md: the default warning is back to its original text, which is accurate again.

Testing

No CI exercises the scripts, so I ran them locally:

  • merge-files.sh, against a source and target with known histories:

    • from the last merged sync, it deleted the two files deleted by a skipped run;
    • it left alone a file deleted before that sync (which the target still has);
    • it updated a file the source deleted and re-added within the range;
    • it skipped an ignored deleted file;
    • it overwrote the target's edited and own copies, and kept a target-only file.

    With no SOURCE_SYNCED it copied everything and deleted nothing. With a commit missing from the history, it warned and skipped deletions.

  • last-sync.sh, with gh stubbed:

    • it read the trailer, ignoring a lookalike in the body text;
    • it fell back to the commit before the push when the trailer was missing, as with older syncs;
    • it synced no deletions for an all-zero (branch-creating) before or none at all.
  • The real --jq filter, against SgtSwagrid/codeswitch's merged sync PRs: it found the latest merged sync commit from scala-browser-plugin-config by its key trailer. That commit predates the new trailer, so a live run would use the fallback until the next merged sync.

  • The commit message: %(trailers:key=…) reads both trailers, and the rendered PR body excludes them.

  • replay(): an update, addition and deletion all apply onto a newer base, including over the target's changes. Deleting a file the target already deleted is a no-op.

  • Syntax: bash -n passes for every script.

Notes

🤖 Generated with Claude Code

…ce the last merged sync.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SgtSwagrid
SgtSwagrid merged commit 28ba536 into main Oct 26, 2026
3 checks passed
@SgtSwagrid
SgtSwagrid deleted the feature_simple_sync branch October 26, 2026 15:40
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.

1 participant