native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: harden upstream sync workflow and script

onevcat 56deb491 46e97bb4

+48 -6
+14 -3
doc-onevcat/fork-sync-and-release.md
··· 36 36 ## One-Time Setup 37 37 38 38 ```bash 39 - git fetch origin upstream --prune 39 + git fetch origin --prune 40 + git fetch upstream --prune 40 41 git config rerere.enabled true 41 42 git config rerere.autoupdate true 42 43 ``` ··· 47 48 48 49 ```bash 49 50 git switch main 50 - git fetch origin upstream --prune 51 - git pull --ff-only origin main 51 + git fetch origin --prune 52 + git fetch upstream --prune 53 + git merge --ff-only origin/main 52 54 git merge --no-ff upstream/main 53 55 make build-app 54 56 make test ··· 56 58 ``` 57 59 58 60 If conflicts happen, resolve once, commit, and `rerere` will likely auto-apply next time. 61 + 62 + ## Common Pitfalls and Fixes 63 + 64 + - `git fetch origin upstream --prune` is invalid for this use case. 65 + `upstream` is interpreted as a refspec, which may fail with `fatal: couldn't find remote ref upstream`. 66 + Use two fetch commands (or `git fetch --all --prune`) instead. 67 + - Prefer `git merge --ff-only origin/main` in scripted sync flow. 68 + It is deterministic and avoids `git pull` edge cases around `FETCH_HEAD`. 69 + - Keep working tree clean before sync (`git status --short` should be empty), otherwise abort and stash/commit first. 59 70 60 71 ## Personal Release Strategy (Fork Release Page) 61 72
+34 -3
doc-onevcat/scripts/sync-upstream-main.sh
··· 3 3 4 4 TARGET_BRANCH="${1:-main}" 5 5 6 + die() { 7 + echo "[error] $*" >&2 8 + exit 1 9 + } 10 + 11 + ensure_remote_exists() { 12 + local remote_name="$1" 13 + git remote get-url "${remote_name}" >/dev/null 2>&1 || die "missing git remote: ${remote_name}" 14 + } 15 + 16 + ensure_clean_worktree() { 17 + if ! git diff --quiet || ! git diff --cached --quiet; then 18 + die "working tree is not clean. commit or stash your changes before syncing." 19 + fi 20 + } 21 + 22 + ensure_remote_branch_exists() { 23 + local remote_name="$1" 24 + local branch_name="$2" 25 + git show-ref --verify --quiet "refs/remotes/${remote_name}/${branch_name}" || \ 26 + die "remote branch not found: ${remote_name}/${branch_name}" 27 + } 28 + 29 + echo "[sync] preflight checks" 30 + ensure_clean_worktree 31 + ensure_remote_exists origin 32 + ensure_remote_exists upstream 33 + 6 34 echo "[sync] fetch remotes" 7 - git fetch origin upstream --prune 35 + git fetch origin --prune 36 + git fetch upstream --prune 37 + ensure_remote_branch_exists origin "${TARGET_BRANCH}" 38 + ensure_remote_branch_exists upstream "main" 8 39 9 40 echo "[sync] switch to ${TARGET_BRANCH}" 10 41 git switch "${TARGET_BRANCH}" 11 42 12 - echo "[sync] fast-forward from origin/${TARGET_BRANCH}" 13 - git pull --ff-only origin "${TARGET_BRANCH}" 43 + echo "[sync] fast-forward from origin/${TARGET_BRANCH} (deterministic merge-based flow)" 44 + git merge --ff-only "origin/${TARGET_BRANCH}" 14 45 15 46 echo "[sync] merge upstream/main into ${TARGET_BRANCH}" 16 47 git merge --no-ff upstream/main