---
name: sync-git-repos
description: Sync GitHub upstream changes to the Aliyun Codeup mirror for the open-connector project. Use when the user asks to pull upstream changes, sync from GitHub, update from upstream, merge GitHub changes, 同步 GitHub 到阿里云, 拉取上游代码, 更新远程分支, or resolve git merge conflicts between the two remotes. Not for regular git operations like commit, push to feature branches, or code review — those are normal git workflows the user handles directly.
---

# Sync GitHub Upstream → Aliyun Codeup

This project uses a **dual-remote** setup:

| Remote     | URL                                                | Direction                                    |
| ---------- | -------------------------------------------------- | -------------------------------------------- |
| `origin`   | `https://codeup.aliyun.com/.../open-connector.git` | push + pull (your main remote)               |
| `upstream` | `https://github.com/oomol-lab/open-connector.git`  | **pull only** (upstream is set to `no_push`) |

The workflow is: **pull from GitHub (`upstream`) → merge/rebase → push to Aliyun (`origin`)**.

No pull request is sent back to GitHub — this is a one-way sync.

---

## Core Workflow

### 1. Update the local `main` branch

Always do this first so your main branch stays in sync with the upstream source of truth:

```bash
# Switch to main and get the latest from GitHub
git checkout main
git fetch upstream main

# Put your local main on top of upstream's latest
git rebase upstream/main
# or: git merge upstream/main

# Push the updated main to your Aliyun mirror
git push origin main
```

**Why rebase vs merge:** Rebase keeps the history linear and clean — your local commits sit on top of upstream's commits as if you developed against the latest code. Merge creates a merge commit. For syncing main (where you rarely commit directly), rebase is cleaner. Use merge only if you want to explicitly record "I merged upstream at this point."

### 2. Update your feature branches

If you have a feature branch (e.g., `feat/my-connector`) that was branched from an older main, bring it up to date:

```bash
git checkout feat/my-connector
git fetch upstream main
git rebase upstream/main
# If there are conflicts → resolve them (see below)
git push origin feat/my-connector --force-with-lease
```

**Why `--force-with-lease` instead of `--force`:** `--force-with-lease` checks that your local understanding of the remote branch is current. If someone else pushed to the same branch on Aliyun, the push is rejected instead of overwriting their work. This is a safety net — always prefer it over bare `--force`.

### 3. Merge a feature branch into main

When your connector is ready to land on main:

```bash
git checkout main
git fetch upstream main
git rebase upstream/main       # main 是最新的
git merge feat/my-connector    # 合并你的分支
git push origin main
```

### 4. Delete the feature branch after merge (optional)

```bash
git branch -d feat/my-connector           # local
git push origin --delete feat/my-connector # remote
```

---

## Handling Merge Conflicts

Conflicts happen when both upstream and your changes modified the same lines. The most likely conflict file is `src/providers/registry.generated.ts` — this is **auto-generated**, never edit it manually.

### General conflict resolution

```bash
git rebase upstream/main
# Git stops and says "conflict in file X"

# See what's conflicted
git status

# See the conflict markers in the file
# <<<<<<< HEAD       ← your change (current)
# =======
# >>>>>>> upstream/main  ← upstream's change (incoming)

# Edit the file to resolve, then:
git add <resolved-file>
git rebase --continue

# If you get stuck and want to abort the rebase:
git rebase --abort
```

### Resolving `registry.generated.ts` conflicts specifically

This file is regenerated from your provider code, so you should **never** conflict-fix it by editing markers. Instead:

```bash
# Accept upstream's version for this file only
git checkout --theirs src/providers/registry.generated.ts
git add src/providers/registry.generated.ts
git rebase --continue

# Then re-run the generation to re-add your provider's entry
npm run generate:registry
git add src/providers/registry.generated.ts
git commit --amend --no-edit   # if already committed, squash into the rebase commit
```

### Conflict prevention tips

- **Pull upstream before starting new work.** Always `git fetch upstream main && git rebase upstream/main` before creating a new feature branch. This way your branch starts from the latest code.
- **Keep feature branches short-lived.** The longer a branch lives, the more upstream has diverged, and the more likely conflicts become.
- **Communicate which files you're modifying.** If you're adding `src/providers/my_service/actions.ts`, that's a new file — zero conflict risk. If you're modifying `src/server/connect-server.ts`, there's a chance upstream changed it too.
- **`registry.generated.ts` is the most common conflict.** Regenerate after merge rather than hand-editing.

---

## Full End-to-End Examples

### Scenario A: Quick sync (just update main)

```bash
git checkout main
git fetch upstream main
git rebase upstream/main
git push origin main
```

### Scenario B: Sync + update feature branch

```bash
# Phase 1: main
git checkout main
git fetch upstream main
git rebase upstream/main
git push origin main

# Phase 2: feature branch
git checkout feat/my-connector
git rebase upstream/main
# resolve conflicts if any
git push origin feat/my-connector --force-with-lease
```

### Scenario C: Feature branch with registry conflict

```bash
git checkout feat/my-connector
git rebase upstream/main
# conflict in src/providers/registry.generated.ts

# Accept upstream's registry for now
git checkout --theirs src/providers/registry.generated.ts
git add src/providers/registry.generated.ts
git rebase --continue
# rebase continues, then:

# Regenerate to add your provider
npm run generate:registry
git add src/providers/registry.generated.ts
git commit --amend --no-edit

# Push
git push origin feat/my-connector --force-with-lease
```

### Scenario D: Undo a bad rebase

```bash
# If you haven't pushed yet, find the last good state
git reflog
# Find the commit before the rebase, for example HEAD@{5}
git reset --hard HEAD@{5}

# If you already pushed with --force, you need to force-push the corrected state
git push origin feat/my-connector --force-with-lease
```

---

## Reference: Remote Configuration

The current configuration (set up once, should not need changing):

```bash
# View remotes
git remote -v
# → origin    https://codeup.aliyun.com/.../open-connector.git (fetch)
# → origin    https://codeup.aliyun.com/.../open-connector.git (push)
# → upstream  https://github.com/oomol-lab/open-connector.git (fetch)
# → upstream  no_push (push)

# If upstream push URL ever gets accidentally reset:
git remote set-url --push upstream no_push
```

---

## Key Principles

1. **`upstream` is read-only.** The push URL is set to `no_push`. If you ever see an error trying to push to `upstream`, that's by design.
2. **`main` tracks upstream.** Don't commit directly to main unless it's a trivial hotfix. Do all development on feature branches.
3. **Regenerate, don't hand-edit.** `registry.generated.ts` is auto-generated. If there's a conflict, take upstream's version and regenerate.
4. **Prefer `--force-with-lease` over `--force`.** It prevents accidentally overwriting someone else's pushes to the same branch.
5. **When in doubt, `git status` and `git log --oneline -10`.** These two commands give you the state of the working tree and recent history. Run them before and after any sync operation.
