Stack Root 作为 Git 仓库
为什么 Stack Root 应该是 Git 仓库
repostack 的设计中,stack root 本身应该是一个 Git 仓库。这是实现"时间旅行"能力的基础。
核心原理
stack-root/ ← 这是一个 Git 仓库
├── .git/ ← stack root 的 Git 历史
├── repostack.yaml ← 声明:stack 包含哪些 repo
├── repostack.lock.yaml ← 状态:repo 当前的精确 revision
└── repos/ ← 子目录(不是子模块)
├── foo/ ← 独立的 Git 仓库
└── bar/ ← 独立的 Git 仓库
Stack root 的 每一个 commit 代表:
- 当时 stack 包含哪些 repo
- 每个 repo 当时的精确 revision
- 当时的视图配置和命令预设
时间旅行工作流
# 1. 当前在开发新功能
cd ~/my-stack
repostack list
# foo @ main a79cd2d
# bar @ main 1234567
# 2. 记录当前状态并提交
repostack snapshot
git add repostack.yaml repostack.lock.yaml
git commit -m "checkpoint: before v2 refactor"
# 3. 继续开发(各种修改、提交)
# ... 几天后 ...
# 4. 需要回到之前的版本组合
git log --oneline
# abc123 checkpoint: before v2 refactor
git checkout abc123
repostack sync # foo 和 bar 都回到当时的 revision
如果不使用 Git
如果不将 stack root 作为 Git 仓库管理:
- ❌ 无法记录 stack 的历史状态
- ❌ 无法回滚到之前的 repo 组合
- ❌ 团队协作时没有统一的"快照"
- ❌ 配置文件的变更没有追溯能力
init 命令的 Git 处理
自动检测
repostack init 会检测当前目录是否已经是 Git 仓库:
# 场景 1:已经是 Git 仓库
cd ~/existing-project
repostack init
# 输出:Initialized repostack.yaml
# (不会重复初始化 Git)
# 场景 2:不是 Git 仓库,自动初始化
cd ~/new-stack
repostack init --yes
# 输出:
# Initialized repostack.yaml
# Initialized git repository
# 场景 3:不是 Git 仓库,手动处理
cd ~/new-stack
repostack init
# 输出:Initialized repostack.yaml
# (提示:当前目录不是 Git 仓库,建议手动 git init)
建议的初始化流程
# 创建新的 stack 目录
mkdir ~/my-stack
cd ~/my-stack
# 方案 1:全自动(推荐用于新仓库)
repostack init --yes
# 方案 2:手动控制(推荐用于已有目录)
repostack init
git init
git add repostack.yaml
git commit -m "init repostack"
提交什么到 Git
必须提交
| 文件 | 说明 |
|---|---|
repostack.yaml | Stack 的声明配置 |
repostack.lock.yaml | Stack 的精确状态 |
建议提交
- 根目录的辅助脚本(如
bootstrap.sh) - 根目录的文档(如
README.md) - CI/CD 配置(如
.github/workflows/)
不要提交
| 路径 | 原因 |
|---|---|
repos/ 或子目录 | 这些是独立的 Git 仓库,不应作为 stack root 的子模块 |
node_modules/ | 依赖目录 |
| 临时文件 | 如日志、缓存 |
.gitignore 建议
# 不要提交子 repo(它们是独立 Git 仓库)
foo/
bar/
baz/
qux/
# 依赖和缓存
node_modules/
*.log
.DS_Store
协作工作流
场景:新成员加入
# 1. 克隆 stack root
git clone git@github.com:team/stack-root.git
cd stack-root
# 2. 下载所有子 repo
repostack pull
# 3. 同步到锁定版本
repostack sync
# 4. 验证状态
repostack list
场景:更新 stack 状态
# A 成员更新了 foo 和 bar
cd ~/stack-root
cd foo && git pull && cd ..
cd bar && git pull && cd ..
# 记录新状态
repostack snapshot
# 提交变更
git diff repostack.lock.yaml
git add repostack.lock.yaml
git commit -m "update: foo to v2.1, bar to v1.5"
git push
# B 成员获取更新
git pull
repostack sync
与 Git 子模块的区别
| 特性 | Git 子模块 | Repostack |
|---|---|---|
| 版本锁定 | 在主仓库记录子模块 commit | 在 lock 文件记录 revision |
| 子仓库感知 | 子仓库知道自己是子模块 | 子仓库完全独立 |
| 提交操作 | 需要进入子目录提交 | 直接在子目录使用 git |
| 灵活性 | 严格绑定 | 灵活切换、临时调整 |
| 学习成本 | 较高 | 较低 |
Repostack 更适合"独立 repo 灵活组合