Snapshot 与 Sync

snapshotsyncrepostack 实现"时间旅行"的核心机制。

两个配置文件的关系

文件作用是否应提交到 Git
repostack.yaml声明 stack 包含哪些 repo✅ 是
repostack.lock.yaml记录每个 repo 的精确 Git 状态✅ 是

简单记忆

  • repostack.yaml = "我想要什么"
  • repostack.lock.yaml = "实际是什么"

关于 lock 文件的详细说明,参见 Lock 文件

snapshot 做了什么

repostack snapshot

执行步骤:

读取当前 stack 中每个 repo 的:
  • path - 本地路径
  • source - 远程地址
  • 当前 branch
  • 当前 HEAD revision

构建 lock 对象并计算 checksum(SHA-256)

将数据写入 repostack.lock.yaml

生成示例

version: 1
checksum: a1b2c3d4e5f67890
repos:
  foo:
    path: foo
    source: git@github.com:example-org/foo.git
    branch: main
    revision: a79cd2d8f1b2c3d4e5f678901234567890abcdef

自动 Snapshot

以下命令会自动更新 lock 文件,通常不需要手动运行 snapshot

  • repostack use - 添加 repo 后自动 snapshot
  • repostack remove - 移除 repo 后自动 snapshot
  • repostack sync - 同步完成后自动 snapshot

sync 做了什么

repostack sync

执行步骤:

下载 - clone 本地缺失的 repo

读取 lock - 解析 repostack.lock.yaml

拉取 - 对每个 repo 执行 git fetch --all --tags

检出 - 如果 lock 有指定 revision,checkout 到该版本

记录 - 重新生成 lock 文件

Checksum 校验机制

lock 文件包含 SHA-256 校验和,用于检测文件是否被意外修改:

checksum: a1b2c3d4e5f67890

作用

  • 生成时计算 lock 内容(不含 checksum 本身)的 SHA-256 哈希,取前 16 位
  • sync 命令读取时重新计算比对
  • 不匹配时报错,防止文件被意外修改

详细计算方式参见 Lock 文件

如何处理错误

如果确实需要修改,删除 checksum 字段后重新运行 snapshot

如果是意外损坏,从 Git 历史恢复 lock 文件

时间旅行工作流

推荐将 stack root 本身作为 Git 仓库:

# 1. 当前状态
cd ~/my-stack
repostack list
# foo @ main a79cd2d
# bar @ main 1234567

# 2. 记录状态
repostack snapshot
git add repostack.lock.yaml
git commit -m "checkpoint: before big refactor"

# 3. 继续开发...
# (在 foo 和 bar 中做各种修改、提交)

# 4. 需要回到之前的状态
git log --oneline
git checkout abc123  # 回到之前的 stack 状态
repostack sync       # 各 repo 也回到当时的 revision

当前边界

  • snapshot 只记录 commit,不记录未提交的修改(dirty 状态只会在 list 中显示)
  • 如果 repo checkout 到具体 revision,branch 会显示为 HEAD
  • lock 文件记录的是 Git revision 快照,不是完整环境锁定(不包含 node_modules 等)

常见问题

Q: 为什么 use/remove 会自动 snapshot?
A: 为了保持 repostack.yamlrepostack.lock.yaml 始终同步。添加/移除 repo 后,lock 文件的内容定义已经变化,需要更新。

Q: lock 文件冲突了怎么办?
A: 解决方式和普通代码冲突一样:

选择一方的版本

运行 repostack sync 确保本地状态匹配

如果需要,重新 snapshot 生成新的 lock

Q: 空仓库(无 commit)会怎样?
A: 会显示 (no commits),sync 时不会尝试 checkout。