# repostack sync

> 

将本地 stack 状态与声明/锁定状态对齐。

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

## 选项

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

## 执行流程

<steps level="4">

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





#### **下载缺失 repo**- 复用 `pull` 的逻辑：遍历所有 repo，对本地缺失的路径执行 `git clone`。





#### **读取 lock 文件**- 读取 `repostack.lock.yaml`。
- 如果 lock 文件包含 `checksum`，会先进行 SHA-256 校验：

  - 计算除 `checksum` 字段外整个对象的哈希值。
  - 若与文件中的 `checksum` 不符，抛出错误：`Lock file checksum mismatch...`。
- 如果没有 `checksum`（旧版 lock），以 debug 日志提示后跳过校验。





#### **对每个 repo 执行同步**- 运行 `git fetch --all --tags` 更新远程引用。
- 如果 lock 文件中存在该 repo 的 `revision`，则执行 `git checkout <revision>` 将其切换到精确版本。

  - **安全提示**：若 repo 存在未提交的修改，且未使用 `--yes`，会先提示确认：
  ```text
  Repo "xxx" has uncommitted changes. Checkout <revision> anyway? (y/N)
  ```


  用户拒绝或按 `Ctrl+C` 会中止整个 `sync`。
- 如果 lock 文件中**没有**该 repo 的 pinned revision，仅 fetch，不切换分支或 detached HEAD。





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





</steps>

## 涉及文件

| 文件                    | 操作          |
| --------------------- | ----------- |
| `repostack.yaml`      | 读取          |
| `.repostackrc`        | 读取          |
| `repostack.lock.yaml` | 读取 / 写入（覆盖） |

## Git 操作

- `git clone`（缺失 repo）
- `git fetch --all --tags`（每个 repo）
- `git checkout <revision>`（仅当 lock 中 pinned 了 revision）
- `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/checkout 失败      | 直接抛出底层 Git 错误                                                                                                   |
| 用户未配置                      | `This stack requires a user configuration...`                                                                   |
| 用户拒绝 checkout 有未提交修改的 repo | `Aborted: user declined to checkout <repo>`                                                                     |

## 边界情况

- **lock 文件缺失**：`sync` 仍会执行 `pull` 和 `fetch`，但不会对任何 repo 执行 `checkout`。最终会根据当前状态生成一份新的 lock 文件。
- **空仓库**：如果 repo 没有 commit，分支和 revision 会被记录为字符串 `"(no commits)"`。
- **Detached HEAD**：`sync` 会 detached checkout 到具体 revision，而不是分支的最新提交。
- **未提交修改保护**：默认情况下，如果 repo 有未提交的本地修改，`sync` 会提示确认；使用 `--yes` 可跳过确认直接执行（适合自动化脚本）。

## 适用场景

- 切换 stack root 的 Git 分支后恢复特定版本组合
- 协作时同步到团队统一的 repo 状态
- 确保本地状态与 lock 文件一致

## 示例

```bash
repostack sync
```
