# repostack sync

> 

将本地 stack 状态同步到配置分支的最新提交。

```bash
repostack sync
repostack sync --yes
```

## 选项

| 选项          | 说明           |
| ----------- | ------------ |
| `-y, --yes` | 跳过未提交修改的确认提示 |

## 执行流程

<steps level="4">

#### **加载配置**- 读取 `repostack.yaml` 和 `.repostackrc`。





#### **下载缺失 repo**- 复用 `pull` 的逻辑：遍历所有 repo，对本地缺失的路径执行 `git clone`。
- 如果配置中的 `source` 仍是旧的占位路径值，且 lock 文件中有该 repo 的 `source`，会用 lock 中的地址纠正 clone 来源。
- 缺失 repo 会按 `settings.concurrency` 并发拉取，单仓失败默认自动重试到第 3 次。





#### **对每个 repo 执行同步**- 运行 `git fetch --all --tags` 更新远程引用。
- 如果当前不在 `repostack.yaml` 配置的 `branch` 上，先执行 `git switch <branch>`。
- 优先使用该分支的 upstream；如果没有 upstream 但存在 `origin/<branch>`，使用 `origin/<branch>`。
- 执行 `git merge --ff-only <upstream>`，只允许 fast-forward。

  
**安全提示**：若 repo 存在未提交的修改，且未使用 `--yes`，会先提示确认。`--yes` 只跳过确认，不会执行 `reset --hard` 或丢弃修改。



#### **重写 lock 文件**- 根据各 repo **当前的实际状态**重新生成 `repostack.lock.yaml`（包含新的 checksum）。





</steps>

## 涉及文件

| 文件                    | 操作                                       |
| --------------------- | ---------------------------------------- |
| `repostack.yaml`      | 读取                                       |
| `.repostackrc`        | 读取                                       |
| `repostack.lock.yaml` | 读取（仅用于缺失 repo 的 clone source 回退）/ 写入（覆盖） |

## Git 操作

- `git clone`（缺失 repo）
- `git fetch --all --tags`（每个 repo）
- `git switch <branch>`（切到配置分支）
- `git merge --ff-only <upstream>`（只做 fast-forward）
- `git rev-parse --abbrev-ref HEAD` 和 `git rev-parse HEAD`（重写 snapshot）

## 错误信息

| 场景                        | 错误信息                                                                                                            |
| ------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Lock 文件 checksum 不匹配      | `Lock file checksum mismatch: expected ..., got .... The lock file may have been corrupted or manually edited.` |
| Git fetch/switch/merge 失败 | 直接抛出底层 Git 错误                                                                                                   |
| 用户未配置                     | `This stack requires a user configuration...`                                                                   |
| 用户拒绝更新有未提交修改的 repo        | `Aborted: user declined to update <repo>`                                                                       |

## 边界情况

- **lock 文件缺失**：`sync` 仍会执行 `pull`、`fetch` 和分支 fast-forward。最终会根据当前状态生成一份新的 lock 文件。
- **空仓库**：如果 repo 没有 commit，分支和 revision 会被记录为字符串 `"(no commits)"`。
- **非 fast-forward**：如果本地分支有额外提交，`sync` 会失败并保留当前状态，需要手动处理合并或 rebase。
- **未提交修改保护**：默认情况下，如果 repo 有未提交的本地修改，`sync` 会提示确认；使用 `--yes` 可跳过确认，但不会强制覆盖修改。

## 适用场景

- 日常开发时更新所有 repo 到配置分支的最新提交
- 协作时获取团队共享分支上的最新代码
- 同步完成后刷新 `repostack.lock.yaml`

## 示例

```bash
repostack sync
```

如果需要恢复到 lock 文件记录的精确 revision，使用：

```bash
repostack restore
```
