---
name: git-upstream-sync
description: The only way to merge origin/main into a branch, conflicts or not. Use it every time main comes in — a PR reported conflicting or DIRTY, a branch behind origin/main, a CI failure to reproduce on the merged tree. Never run `git merge origin/main` or `git pull origin main` by hand.
---

# Overview

Merge origin/main into the current branch. Follow every step whether or not the
merge conflicts: a clean merge still ends with the sanity check.

## Procedure

### 1. Fetch and merge with zdiff3

If the branch is on `origin`, pull it first: CI's `tidy` job may have pushed
`chore: tidy` onto it. If that pull conflicts, take it through steps 2 and 3,
then start again here, so `origin/main` is merged too. Then move the checked-out submodules to the pointers the
merge recorded, so the next `git add -A` does not stage a stale checkout.

```sh
b=$(git branch --show-current)
if git ls-remote --exit-code --heads origin "$b" > /dev/null; then
  git pull --no-rebase origin "$b" || exit 1   # a conflict stops here
fi
git fetch origin main
git -c merge.conflictstyle=zdiff3 merge origin/main
git submodule update --recommend-shallow
```

### 2. If conflicts exist, commit them as-is

If the merge produces conflicts, **commit the conflict markers without resolving them first**. This records the raw conflict state in a dedicated commit, separate from the resolution.

```sh
git add -A
git diff --cached origin/main -- vendor
git commit -m "merge origin/main (conflicts unresolved)"
```

The `vendor` diff prints nothing unless the branch bumps a submodule itself.
Anything else is a stale checkout that `git add -A` staged, reverting main's
bump. Restore main's pointer for each such path before committing, and check
again after every `git add -A`, step 3's included:

```sh
git update-index --cacheinfo 160000,"$(git rev-parse origin/main:vendor/wasmtime)",vendor/wasmtime
```

### 3. Resolve conflicts

After committing the unresolved state:

1. Read each conflicted file and understand both sides of the conflict
2. Resolve conflicts **in code files** (remove conflict markers, choose correct code)
3. For **generated files** (golden fixtures, generated parsers, …) that conflict,
   **regenerate them** by re-running their generator and commit the fresh output —
   do not hand-resolve the markers or defer them (see "Generated files" below)
4. Stage and commit the resolution:

```sh
git add -A
git diff --cached origin/main -- vendor   # as in step 2
git commit -m "resolve merge conflicts"
```

### 4. Run `mise run test` for sanity check

CI applies clippy and format, so a quick sanity check is sufficient.

## Important

- Always use `-c merge.conflictstyle=zdiff3` so the merge base is visible in conflict markers (with zealous zdiff3 reducing noise)
- Always commit the unresolved conflicts first, then resolve in a separate commit — this preserves a clear record of what the conflicts looked like vs how they were resolved
- Do NOT squash the two commits together

## Generated files

- **Always regenerate golden / generated files and commit.**
  Re-run the generator (do not hand-resolve the markers) and commit its output.
  Do not skip them or defer them to `on-task-done` / CI.
- **Never silently discard generated output** (e.g. `git restore` to clean the
  tree or quiet a hook). Commit it, or ask. Discarding generated work without
  asking is always wrong.
