diff --git a/CLAUDE.md b/CLAUDE.md index 20cd2478..767b24bf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,62 +1,80 @@ # Working in this fork `hotdata-dev/liquid-cache` is a fork of `datafusion-contrib/liquid-cache`. -`main` contains upstream's history in full plus our patches, so -`git merge-base main ` resolves. +`origin/main` contains upstream's history in full plus our patches, so +`git merge-base origin/main upstream/main` resolves. Check `origin/main` +rather than local `main`: a local branch can track the wrong remote or simply +be stale, and neither says so. -Nothing here states where upstream currently is, or where we are: both move. -Ask git instead. +## Set your remotes up first + +The standard fork layout, which everything below assumes: ``` -git fetch https://github.com/datafusion-contrib/liquid-cache main -git log --oneline FETCH_HEAD..main # ours that upstream does not have -git log --oneline main..FETCH_HEAD # upstream's that we do not have +origin hotdata-dev/liquid-cache ours, where we push +upstream datafusion-contrib/liquid-cache theirs, read-only ``` -`AGENTS.md` and `README.md` are upstream's and describe the project itself. -This file is ours and describes only what differs here. Nothing in this repo -should edit an upstream-owned file to record a fork convention: that conflicts -on every sync. Add a file upstream does not have instead. +See what you have first — the two cases need different commands, and running +the wrong one leaves both remotes pointing at this fork, where `upstream/main` +silently means our `main` and every recipe below is wrong with no error. -## Remotes +``` +git remote -v +``` -**Check before using a remote name. They vary by clone and they are not what -you would guess** — in at least one working copy `origin` is *upstream* and the -fork is a second remote named `fork`, which is the reverse of the usual -arrangement. +**Cloned this fork** (`origin` already correct) — add the other: ``` -git remote -v +git remote add upstream https://github.com/datafusion-contrib/liquid-cache.git ``` -Commands below name repositories by URL rather than by remote, so they are -correct in any clone. Do the same when writing instructions for anyone else: a -bare `origin/main` is ambiguous here and has already been misread as the -opposite of what it meant. +**Cloned upstream** (`origin` points at *upstream*, which has already been +misread as the opposite of what it meant) — rename it, then add ours: -## Branches +``` +git remote rename origin upstream +git remote add origin git@github.com:hotdata-dev/liquid-cache.git +git fetch origin +git branch --set-upstream-to=origin/main main +``` -- Work off `main`, and fetch before branching — a local `main` goes stale with - no signal, and branching off a stale one silently drops everything merged - since. -- **Upstream PRs branch from upstream, not from `main`**, and are named - `upstream/`. A branch cut from `main` carries our whole patch stack - into the PR diff. +The last two matter: `git remote rename` rewrites the tracking config of every +branch that followed it, so after the rename local `main` follows +`upstream/main`. A `git pull` on `main` would then merge upstream straight into +it, and `git merge-base main upstream/main` would pass whatever the fork's +state is. - ``` - git fetch https://github.com/datafusion-contrib/liquid-cache main - git checkout -b upstream/ FETCH_HEAD - ``` +Either way, confirm the two point at *different* repositories before relying +on anything below: + +``` +git remote get-url origin # must be hotdata-dev +git remote get-url upstream # must be datafusion-contrib +``` - Before pushing, this must list only the commits you wrote — anything else is - a fork patch that would land in the upstream diff. Re-fetch upstream on the - line above it: `FETCH_HEAD` holds whatever the last fetch wrote, so after - fetching any other remote it is no longer upstream and the check hides every - fork patch. +Then `origin/main` and `upstream/main` are stable refs that mean one thing. +Prefer them over `FETCH_HEAD`, which holds only the most recent fetch and has +repeatedly produced instructions in this file that silently checked the wrong +thing. + +`AGENTS.md` and `README.md` are upstream's and describe the project itself. +This file is ours and describes only what differs here. Nothing in this repo +should edit an upstream-owned file to record a fork convention: that conflicts +on every sync. Add a file upstream does not have instead. + +## Branches + +- `git fetch origin` before branching, and branch from `origin/main`. A local + `main` goes stale with no signal, and branching off a stale one silently + drops everything merged since. +- **Upstream PRs branch from upstream**, named `upstream/`. A branch cut + from our `main` carries the whole patch stack into the PR diff. ``` - git fetch https://github.com/datafusion-contrib/liquid-cache main - git log --oneline FETCH_HEAD..HEAD + git fetch upstream + git checkout -b upstream/ upstream/main + git log --oneline upstream/main..HEAD # must list only your own commits ``` `.github/workflows/upstream-branch-guard.yml` checks the same property on @@ -73,45 +91,32 @@ opposite of what it meant. ## Syncing from upstream -Merge upstream into a branch off `main` and raise a PR; do not use GitHub's -"Sync fork" button, which offers to discard our commits when the merge is not -a fast-forward. - -Fetch *this fork* first and branch from what came back, not from local `main` -— the upstream fetch below never refreshes `main`, so a stale one would make -the sync PR revert fork commits merged since. Use each `FETCH_HEAD` -immediately: it holds only the last fetch. - ``` -git fetch https://github.com/hotdata-dev/liquid-cache main -git checkout -b sync/upstream- FETCH_HEAD - -git fetch https://github.com/datafusion-contrib/liquid-cache main -git merge FETCH_HEAD +git fetch --multiple origin upstream +git checkout -b sync/upstream- origin/main +git merge upstream/main ``` -**Merge this PR, do not squash it.** A squash gives the result a single parent, -so upstream's history never enters `main`'s ancestry: the merge-base does not -move, the same upstream commits stay missing, and nothing reports it. +Raise a PR; do not use GitHub's "Sync fork" button, which offers to discard our +commits when the merge is not a fast-forward. -Verify afterwards. The merge happens on GitHub, so local `main` does not have -it and must not be what you check; and `FETCH_HEAD` holds only the last fetch, -so capture upstream before fetching the fork over it: +**Merge that PR, do not squash it.** A squash gives the result a single parent, +so upstream's history never enters `main`'s ancestry: the merge-base does not +move, the same upstream commits stay missing, and nothing reports it. Verify +afterwards — the merge happens on GitHub, so fetch before checking: ``` -git fetch https://github.com/datafusion-contrib/liquid-cache main -upstream=$(git rev-parse FETCH_HEAD) -git fetch https://github.com/hotdata-dev/liquid-cache main -git merge-base --is-ancestor "$upstream" FETCH_HEAD && echo ok +git fetch --multiple origin upstream +git merge-base --is-ancestor upstream/main origin/main && echo ok ``` A change we contributed upstream comes back as their squash of it. The content matches but the commit does not, so the merge conflicts where both sides -touched the same lines — typically a module list that each side appended to. -Keep ours *for the returned change*, and keep any other upstream edit in the -same hunk: upstream may have appended something of its own next to it, and -taking the whole hunk from our side drops that silently. Read the hunk rather -than resolving by rule. +touched the same lines — typically a module list each side appended to. Keep +ours *for the returned change*, and keep any other upstream edit in the same +hunk: upstream may have appended something of its own next to it, and taking +the whole hunk from our side drops that silently. Read the hunk rather than +resolving by rule. Sync promptly rather than letting such a conflict wait: alone it is obvious, bundled with real upstream work later it is not.