# Stack Root 作为 Git 仓库

> 

## 为什么 Stack Root 应该是 Git 仓库

`repostack` 的设计中，**stack root 本身应该是一个 Git 仓库**。这是实现"时间旅行"能力的基础。

### 核心原理

```text
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
- 当时的视图配置和命令预设

### 时间旅行工作流

```bash
# 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 仓库：

```bash
# 场景 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）
```

### 建议的初始化流程

```bash
# 创建新的 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 建议

```gitignore
# 不要提交子 repo（它们是独立 Git 仓库）
foo/
bar/
baz/
qux/

# 依赖和缓存
node_modules/
*.log
.DS_Store
```

## 协作工作流

### 场景：新成员加入

```bash
# 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 状态

```bash
# 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 灵活组合
