# Git 工作流 > 这个仓库已经 `git init`,首次提交完成。下面是怎么用,以及为什么这么用。 --- ## 为什么这个仓库特别适合 git 不是所有项目都值得上 git。这个仓库有三条天然契合: | 特性 | 带来的好处 | |---|---| | **原材料只增不改** | 加文件几乎永远不冲突。这是最关键的——协作时最怕两个人改同一个文件 | | **全是 Markdown** | diff 读得懂。改了什么、删了什么,一眼看出来,不用看二进制 | | **索引是派生的** | `_index.md`、`derivations.jsonl` 冲突了直接重生成,不用手工合并 | 还有一条隐藏价值:**知识库的 git 历史 = 课程内容的演进史**。半年后你想知道「客户画像这一页是怎么长成现在这样的」,`git log -p` 能看到它被五份资料逐步充实的过程。这比任何笔记都可靠。 --- ## 一次性设置(已配好,换机器要重做) ```bash git config core.quotepath false # 中文文件名正常显示,不显示成八进制 git config user.name "你的名字" git config user.email "你的邮箱" ``` `core.quotepath false` 这条别漏。不配的话 `git status` 里全是 `\346\212\200\350\203\275` 这种,没法看。 --- ## 日常:一次同步,一个提交 ``` 丢资料 → 说「同步」→ 跑 kb.py check → git add -A → git commit ``` **提交前必须跑一次检查**,别把死链和没出处的数字提交进去: ```bash python 90-工具/kb.py check ``` ### 提交信息规范 统一前缀加一句话,方便日后 `git log --oneline` 扫读: | 前缀 | 什么时候用 | 例子 | |---|---|---| | `sync:` | 增量同步完成 | `sync: 入库 3 份行业报告,派生 9 页` | | `retract:` | 源删除后的回滚 | `retract: 删除 2024 旧版大纲,归档 4 页` | | `course:` | 课程产出 | `course: 银行 3 天课大纲初稿` | | `fix:` | 修复体检问题 | `fix: 清理 12 处死链与 3 个孤儿页` | | `rule:` | 改契约或技能 | `rule: 新增证据分级 A/B/C/D` | | `chore:` | 工具改动 | `chore: kb.py 增加 repair 命令` | 不要写 "update"、"修改"、"提交一下"。三个月后自己看不懂。 --- ## 多人协作:谁改什么 冲突的根源是两个人改同一个文件。按下面的分工,冲突面能压到接近零。 | 角色 | 主要改 | 基本不碰 | |---|---|---| | 资料策展人 | `00-原材料/` 加文件 | 知识库页面 | | 做课的人 | `20-课程产出/`、`10-知识库/modules/` | 别人的 topic 页 | | 库维护者 | `10-知识库/topics/`、`entities/`、`_meta/` | 产出目录 | ### 三个冲突高发点 | 文件 | 冲突概率 | 原因 | |---|---|---| | `_meta/manifest.json` | **极高** | 单一文件,谁同步都会改 | | `topics/*.md` | 中 | 两个人可能同时往同一主题页补料 | | `*/_index.md` | 中 | 每次 `graph` 都重写 | --- ## 冲突怎么解 ### 情况一:`manifest.json` 冲突 **不要手动合并 JSON。** 它本质是磁盘状态的缓存,直接从磁盘重建就行: ```bash git checkout --ours 10-知识库/_meta/manifest.json python 90-工具/kb.py repair ``` `repair` 会扫磁盘算指纹、扫页面反推派生关系,把 manifest 重新建出来。恢复不了的只有「整理时间」和「已删除源的记录」,不影响使用。 ### 情况二:页面冲突 正常解,但注意 **`sources:` 列表要取并集**,不是二选一。少一个源,将来删那个源时这页就回滚不掉。 ```yaml sources: - "01-行业资料/报告A.pdf" # 对方加的 - "02-客户与需求/访谈.md" # 你加的 ``` ### 情况三:`_index.md` 冲突 **别解,直接重生成:** ```bash git checkout --theirs 10-知识库/topics/_index.md python 90-工具/kb.py graph ``` 它是 `kb.py graph` 的产物,手工合并没有任何意义。 --- ## 用 git 做四件具体的事 ### 1. 撤销一次糟糕的同步 同步完发现喂了错误的资料,整批派生页都脏了: ```bash git reset --hard HEAD~1 # 回到上一个提交(会丢未提交的改动,先确认) ``` 比手动删页面安全得多。 ### 2. 看某一页是怎么长出来的 ```bash git log -p -- 10-知识库/topics/客户画像.md ``` 能看到它第一次只是一句话,后来被几份资料逐步补成现在的样子,每次补料是谁、按什么依据。**这是这个仓库最值钱的用法之一。** ### 3. 找回被误删的页 ```bash git log --diff-filter=D --name-only -- 10-知识库/ ``` 列出所有被删过的文件,配合 `git checkout ^ -- <路径>` 恢复。 ### 4. 对比两周前的库 ```bash git diff HEAD~20 --stat ``` 一眼看出这两周库长大了多少、哪些方向在长、哪些页一直没动过。 --- ## 远端优先:每次开工先拉 git 服务在本机或内网,不存在外泄风险,所以这个库可以、也应该**以远端为准**。 ### 但有个前提要说清 公开的只读知识库(比如那本人生指南)可以「拉一份临时副本 → 读完扔掉」,因为它只读。 **这个库要写入。** 拉下来的副本改完往哪推?所以不能照抄那个模式。正确的做法是: > 本地保留完整工作区,但**每次都从远端拉最新**,改完推回去。 「远端为准」靠的不是「本地不存」,而是**每次开工先把本地对齐到远端**。 ### 一条命令 ```bash python 90-工具/kb.py pull ``` 它做四件事: 1. 检查是不是 git 仓库、有没有配远端 2. **工作区有未提交改动就拒绝拉取** —— 避免和 rebase 打架,并列出脏文件 3. `git pull --rebase` 拉最新 4. 对比拉取前后的提交,**报出原材料新增/修改/删除/移动各几个,具体是哪些文件** 输出长这样: ``` 从 origin/main 拉取… 拉到 1 个新提交。原材料变化:新增 2 · 修改 0 · 删除 0 · 移动 0 [NEW] 00-原材料/01-行业资料/远端新增报告.md [NEW] 00-原材料/03-课程素材/远端新案例.md 下一步:让模型按 kb-sync 的流程处理上面这些变化。 ``` 拉完之后**不需要额外的检测逻辑**:文件真的落地了,`kb.py scan` 的 sha256 比对自然能发现它们。实测这比让 git 自己算 diff 更可靠 —— 它还能发现没提交的本地改动。 ### 为什么这样最省时间 `git pull` 只传增量。唯一的全量传输是第一次 `git clone`,之后每次都是几百 KB 级别。 反过来,如果为了省磁盘只检出需要的部分(sparse-checkout),`kb.py scan` 就扫不到全量原材料,指纹比对直接失效 —— 省下的空间远不值得。 ### 按仓库体积选策略 | 仓库体积 | 做法 | |---|---| | < 500 MB | **全量 + 每次 pull**(默认,就是现在这套) | | 500 MB – 5 GB | 全量 + 大文件走 git-lfs(lfs 对象按需下载,工作区里是几百字节的指针) | | > 5 GB 或含大量视频 | 原材料单独开一个仓库,主库只放知识库与技能 | 绝大多数做课资料在第一档。 ### 日常节奏 ``` 早上开工 python 90-工具/kb.py pull # 拿到别人昨天整理的结果 白天 丢资料 → 说「同步」 晚上收工 git add -A && git commit && git push ``` **收工不推,等于白干。** 第二天别人 pull 不到,你自己换台机器也接不上。 --- ## 首次配置远端 ```bash git remote add origin <你的本地 git 服务地址> git push -u origin main ``` 如果是自建的 Gitea / GitLab,地址形如 `http://192.168.1.10:3000/team/course-factory.git`。 纯本机的话,也可以直接指向本地目录的 bare 仓库: ```bash git init --bare D:/git/course-factory.git git remote add origin D:/git/course-factory.git git push -u origin main ``` **不要推到公开 GitHub** —— 库里有客户名称、报价、内部方法论。 --- ## 大文件 `00-原材料/` 里如果有超过 50MB 的 PDF 或视频,建议用 git-lfs,否则仓库会很快膨胀到几个 GB: ```bash git lfs install git lfs track "00-原材料/**/*.pdf" git lfs track "00-原材料/**/*.mp4" git add .gitattributes ``` **已经提交过的大文件不能再靠 lfs 瘦身**,需要用 `git filter-repo` 重写历史。所以最好现在就决定。 --- ## 和 kb.py 的分工 别把两件事搞混: | | 管什么 | |---|---| | **git** | 文件的历史版本:谁在什么时候改了什么 | | **kb.py** | 当前状态的一致性:哪些源整理过、哪些页该删、索引对不对 | `git` 回答「上周这页写的什么」,`kb.py` 回答「现在库里有没有过期内容」。两个都要,互相替代不了。 --- ## 一条最小纪律 > **每次说「同步」结束后,立刻提交一次。** 不要攒着。攒了三天的改动一起提交,出问题时你分不清是哪一批资料搞坏的。