# Git 入门：main / HEAD / 分支 / 工作树（结合本仓库）

> 给小白的四个核心概念笔记，全部用**本仓库刚发生的真实操作**做例子。
> 一句话总比喻：Git 像「写书 + 拍快照存档」。

| 概念 | 是什么（大白话） | 比喻 |
| --- | --- | --- |
| **工作树** Working Tree | 你硬盘上当前能看到、能编辑的文件 | 桌上正在改的稿子 |
| **提交** Commit | 给某一刻的工作树拍的一张存档照片（有哈希编号） | 一张存档照片 |
| **分支** Branch | 一条照片串成的时间线（其实只是「最新照片」的标签） | 一条时间线 / 便利贴 |
| **HEAD** | 一个「你在这儿」的箭头，指向当前所在的 commit | 你站在哪张照片上 |
| **main** | 约定俗成的「主」时间线，最稳定、用来发布 | 主线书稿 |

---

## 1. 工作树 = 桌上的稿子

就是**当前硬盘上的文件**。用编辑器改文件 = 改工作树。改了**不等于**进了 Git，必须 `commit` 才存档。

本仓库工作树现在还躺着没提交的改动（跟内核工作无关，故意留着）：

```
M kernel/src/main.c          改了但没存档
D national-exam-site/...      删了但没存档
?? worktreeName.js            新文件，Git 还没管
```

---

## 2. 提交 = 一张照片；HEAD = 你站在哪张

`git commit` 把当时工作树拍成照片，给个哈希编号。本次内核工作那张：

```
f81a65e  feat(kernel): khyos 自研内核 Windows 跨平台构建…
```

**HEAD** 是「你在这儿」的箭头，现在指向 `f81a65e`。
- `git log` = 从 HEAD 往回看这条线的历史。
- 切换分支 = 把 HEAD 箭头挪到别的线上。

---

## 3. 分支 = 一条时间线

一张张照片首尾相连成线；**分支名只是这条线「最新照片」的标签**。本仓库现有：

```
main                              主线（停在较旧处）
docs/github-viral-launch-kit      之前的发布分支（比 main 多 81 张照片）
feat/windows-kernel-crossbuild    本次内核工作的新线，HEAD 正站这儿
```

**新建分支**（`git checkout -b feat/windows-kernel-crossbuild`）= 在当前照片旁贴张新标签，
之后新照片贴到新线，**不污染原线**。这就是「开独立分支提交」。

---

## 4. main = 那条「主」时间线

`main` 没魔法，就是一条分支，只是**大家约定它最稳定、用来发布**。
其他 feature 分支开发完，再「合并(merge)」回 main。

---

## 把四者串起来：本仓库这次到底发生了什么

```
            (commit 从左到右越来越新)

main ──●──●──●                                  主线，停在较旧处
              \
docs/...viral  ●──●──…──●  (领先 main 81 张)
                          \
feat/windows...            ●  f81a65e   把内核工作拍成这张，贴在新线上
                          ▲
                        HEAD  你现在站这儿

工作树: main.c / 删除 / worktreeName.js   还没拍照，留在桌上
```

翻译成大白话：
1. **新建分支**：在原 `docs/...` 线最新照片旁贴新标签 `feat/windows-kernel-crossbuild`，HEAD 挪过去。
2. **暂存 + 提交**：把工作树里**属于内核工作的 9 个文件**拍成 `f81a65e`，贴到新线。
3. **故意不拍**的 `main.c`、删除、`worktreeName.js` 留在工作树（与本次无关）。
4. **推送**：把这张照片上传到远端 gitlab，不只本机有。

---

## 三个最容易混的点（必记）

| 你可能以为 | 实际上 |
| --- | --- |
| 改了文件就进 Git 了 | ❌ 改文件只动**工作树**；必须 `commit` 才存档 |
| 分支是「文件夹的拷贝」 | ❌ 分支只是**一条时间线的标签**，切分支不复制文件夹 |
| HEAD 是某个文件 | ❌ HEAD 只是**「你在哪」的箭头**，指向当前 commit |

---

## 常用命令速查

```bash
git status                 # 我在哪条分支？工作树有哪些没提交的改动？（最常用）
git log --oneline -5       # 我脚下这条线最近 5 张照片
git branch                 # 有哪些分支？* 号是当前所在
git add <文件>             # 把某文件放进「待拍照」清单（暂存区）
git commit -m "说明"       # 把暂存的内容拍成一张照片
git checkout -b <新分支名>  # 在当前位置开一条新线并跳过去
git push                   # 把本地照片上传到远端
```

> 一条命令随时看清自己站在哪、桌上还有什么没存：`git status`。

---

## 进阶一步：还有个「暂存区」（Staging Area）

严格说，从「工作树」到「照片」中间还有一站，叫**暂存区**：

```
工作树（桌上改稿） --git add--> 暂存区（待拍照清单） --git commit--> 照片(commit)
```

这就是为什么本次提交分两步：先 `git add` **挑出** 属于内核工作的 9 个文件放进暂存区，
再 `git commit` 只把这 9 个拍进照片——`main.c` 等没 `add`，自然不进这张照片。
「挑选要存档的东西」正是暂存区的用途。
