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.yamlStack 的声明配置
repostack.lock.yamlStack 的精确状态

建议提交

  • 根目录的辅助脚本(如 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 灵活组合