ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

团队记忆共享方案:通过 Git 同步 .claude 目录的最佳实践与冲突解决

2026/9/29 3:57:38 拓冰建站 浏览量
团队记忆共享方案:通过 Git 同步 .claude 目录的最佳实践与冲突解决 1. 为什么 .claude 目录一进 Git 就出事多人协作里.claude目录是个很尴尬的存在。它既像本地缓存又装着团队真正需要共享的东西规则文件、上下文记忆、会话历史。你把它整个.gitignore掉新人拉下代码后 Claude Code 完全不知道项目背景生成的代码风格和接口调用全靠猜你把它整个提交上去context.md每天被多人改合并冲突率能飙到七成CI 里claude code --review直接因为残留的冲突标记解析失败退出。我见过最典型的一次事故两个分支各自更新了.claude/context.md一个写“数据库用 PostgreSQL 14”另一个写“迁移到 MySQL 8.0”Git 自动合并后文件里两段矛盾描述并存冲突标记还被顺手提交了。CI 跑到上下文解析阶段直接报错排查了半天才发现是.claude目录的锅。所以问题不是“要不要进 Git”而是“哪些进、怎么进、冲突了怎么办”。这篇就按这个思路给你一套可以直接抄的配置骨架.gitignore怎么划边界、settings.json和config.toml怎么写、CLAUDE.md冲突时怎么手动解、合并后怎么验证各成员环境一致。适合已经在用 Claude Code 做团队协作、被.claude同步问题折腾过的同学。2. 前置准备TaoToken 接入与目录分层在动 Git 之前先把模型接入这层理顺。团队里每个人本地跑 Claude Code底层走的是同一套 API 网关这样规则文件里约定的模型、参数才有意义。TaoToken 在这里的作用就是给团队一个统一的接入点避免有人用 A 渠道、有人用 B 渠道导致行为不一致。注册和拿 Key 的入口在这里官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end API 地址是 https://taotoken.net/api 。控制台里创建 API Key 的页面在 https://taotoken.net/console/api-keys 接入文档在 https://taotoken.net/doc 。这几个地址建议直接写进团队 onboarding 文档省得每个人问一遍。拿到 Key 之后本地环境变量这样配export TAOTOKEN_API_KEYsk-你的key export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEY$TAOTOKEN_API_KEYWindows 下用 PowerShell$env:TAOTOKEN_API_KEYsk-你的key $env:ANTHROPIC_BASE_URLhttps://taotoken.net/api $env:ANTHROPIC_API_KEY$env:TAOTOKEN_API_KEY配完先验证一下模型能不能通用模型对话页面快速测一条 https://taotoken.net/model-chat 。能正常返回说明接入层没问题接下来才轮到.claude目录的 Git 同步。目录分层是整套方案的地基。我的建议是拆成三层每层策略不同层级路径是否进 Git同步策略规则层.claude/rules/进只增不改版本化命名上下文层.claude/context.md、CLAUDE.md进段落级合并带时间戳会话层.claude/sessions/按需LFS 或只留最近 7 天缓存层.claude/cache/、.claude/tmp/不进本地生成这个分层决定了后面.gitignore和合并驱动的写法。3. 可复制配置.gitignore、settings.json、config.toml3.1 .gitignore 划边界根目录.gitignore里针对.claude的部分核心是“忽略缓存和临时文件保留规则和上下文”# .claude 缓存与临时文件坚决不进 Git .claude/cache/ .claude/tmp/ .claude/*.log .claude/**/*.lock # 会话历史按需默认忽略需要共享时用 LFS 单独处理 .claude/sessions/ # 本地个人覆盖配置不进 Git .claude/settings.local.json .claude/config.local.toml # 保留规则与上下文 !.claude/rules/ !.claude/context.md !CLAUDE.md注意!.claude/rules/这种否定规则要放在忽略规则之后Git 才认。如果你发现规则文件还是被忽略了多半是父目录被整体忽略导致否定失效检查一下有没有.claude/这种一刀切写法。3.2 settings.json 团队共享配置.claude/settings.json放团队统一的行为约定比如默认模型、允许的工具、上下文引用方式{ model: claude-sonnet-4-20250514, apiBaseUrl: https://taotoken.net/api, contextFiles: [ .claude/context.md, CLAUDE.md, .claude/rules/api-call-v2.md, .claude/rules/db-access-v1.md ], rules: { enforceContext: true, maxContextTokens: 120000 }, permissions: { allowFileWrite: true, allowShell: false } }这里contextFiles是显式声明要加载哪些文件比让 Claude Code 自己扫目录更可控也方便冲突排查时定位是哪个文件的问题。apiBaseUrl统一指向 TaoToken避免有人本地改了地址导致行为漂移。3.3 config.toml 合并驱动注册.claude/config.toml用来声明合并策略配合 Git 的 merge driver 使用[merge] context_file .claude/context.md claude_md CLAUDE.md driver claude-context strategy section-timestamp [merge.sections] split_pattern ^## timestamp_pattern !-- last-updated: (.*?) -- [sync] sessions_retention_days 7 validate_on_commit true然后在项目根目录的.gitattributes里绑定驱动.claude/context.md mergeclaude-context CLAUDE.md mergeclaude-context .claude/sessions/** filterlfs difflfs mergelfs -text再在本地或全局 Git 配置里注册驱动命令git config merge.claude-context.name Claude Context Merge Driver git config merge.claude-context.driver python3 scripts/merge_context.py %O %A %B %Lmerge_context.py的核心逻辑是按##段落切分每段读时间戳双方都改同一段时取时间戳较新的只有一方改时直接采用import re import sys SECTION_RE re.compile(r^## , re.M) TS_RE re.compile(r!-- last-updated: (.*?) --) def parse_sections(text): parts SECTION_RE.split(text) sections {} for i in range(1, len(parts), 2): title parts[i].strip() body parts[i 1] if i 1 len(parts) else ts_match TS_RE.search(body) ts ts_match.group(1) if ts_match else sections[title] {body: body, ts: ts} return sections def merge(base, ours, theirs): b, o, t parse_sections(base), parse_sections(ours), parse_sections(theirs) result {} for key in set(list(o.keys()) list(t.keys())): if key in o and key in t: result[key] o[key] if o[key][ts] t[key][ts] else t[key] elif key in o: result[key] o[key] else: result[key] t[key] return \n.join(f## {k}\n{v[body].strip()}\n for k, v in result.items()) if __name__ __main__: base, ours, theirs sys.argv[1], sys.argv[2], sys.argv[3] with open(base) as f: b f.read() with open(ours) as f: o f.read() with open(theirs) as f: t f.read() with open(ours, w) as f: f.write(merge(b, o, t))每个##段落开头必须带时间戳注释否则合并驱动没法判断新旧## 数据库状态 !-- last-updated: 2025-03-15T10:30:00Z -- 当前使用 PostgreSQL 14连接池大小 20。4. 验证同步合并后各成员环境一致配置写完得验证“拉下来之后大家跑的是同一套东西”。分三步。第一步本地初始化顺序要对。新人入职常见错误是先git pull再claude code --init结果.claude目录被覆盖。正确顺序是先初始化再拉取claude code --init git pull origin main第二步验证上下文加载是否一致。跑一条校验命令检查所有contextFiles引用是否有效claude code --validate正常输出类似[OK] .claude/context.md loaded, 6 sections [OK] CLAUDE.md loaded [OK] .claude/rules/api-call-v2.md loaded [OK] .claude/rules/db-access-v1.md loaded [OK] no conflict markers found如果出现conflict marker found in .claude/context.md说明有分支合并时残留了需要手动处理。第三步跨成员一致性检查。让两个同事各自跑同一条请求对比输出里的上下文引用claude code --print-context | grep -E rules|context | sort两边输出应该完全一致。如果 A 加载了api-call-v2.mdB 还加载api-call-v1.md说明 B 本地没拉到最新或者.gitignore把规则文件误忽略了。验证模型本身是否正常可以用模型对话页面发一条带上下文的请求 https://taotoken.net/model-chat 。如果模型能正确引用你context.md里的项目描述说明整条链路通了。5. 常见错排查CLAUDE.md 冲突与配置漂移5.1 CLAUDE.md 合并冲突手动解CLAUDE.md和context.md一样是冲突重灾区。假设合并后文件长这样## API 端点 HEAD !-- last-updated: 2025-03-15T10:30:00Z -- 使用 /v2/chat 端点超时 30s。 !-- last-updated: 2025-03-14T08:00:00Z -- 使用 /v1/chat 端点超时 60s。 feature/new-api处理动作保留时间戳较新的那段删掉冲突标记和旧段。这里 HEAD 是 3-15feature 是 3-14所以保留 HEAD 的/v2/chat## API 端点 !-- last-updated: 2025-03-15T10:30:00Z -- 使用 /v2/chat 端点超时 30s。如果两段内容都有价值比如一个改了端点、一个改了超时那就手动合并成一段时间戳取较新的## API 端点 !-- last-updated: 2025-03-15T10:30:00Z -- 使用 /v2/chat 端点超时 60s。解完跑一遍claude code --validate确认没有残留标记。5.2 同名段落重复两个分支各自新增了## 数据库配置合并后文件里出现两个同名段落。合并驱动如果没做去重Claude Code 读取时会取第一个第二个被忽略。排查方法grep -n ^## .claude/context.md | sort | uniq -d有重复输出就说明中招了。解决是在合并脚本里加去重逻辑同名段落按时间戳合并内容def deduplicate(sections): seen {} for key, sec in sections.items(): if key in seen: seen[key][body] \n sec[body] seen[key][ts] max(seen[key][ts], sec[ts]) else: seen[key] sec return seen5.3 配置漂移settings.local.json 被误提交有人把本地覆盖配置settings.local.json提交了导致团队里其他人拉下来后行为被改。检查git ls-files | grep -E settings.local|config.local有输出就说明误提交了从 Git 移除但保留本地文件git rm --cached .claude/settings.local.json echo .claude/settings.local.json .gitignore git commit -m chore: remove local settings from tracking5.4 会话文件过大拖慢 clone.claude/sessions/如果没走 LFS仓库体积会越来越大。检查大文件git rev-list --objects --all | git cat-file --batch-check%(objecttype) %(objectname) %(objectsize) %(rest) | awk /^blob/ {print $3, $4} | sort -rn | head -10如果.claude/sessions/下的文件排前面说明需要迁移到 LFS 或加清理脚本。清理只删已关闭的会话别误删正在用的find .claude/sessions -name *.md -mtime 7 -exec grep -l status: closed {} \; -delete5.5 CI 里 validate 失败但本地正常多半是 CI 环境没配ANTHROPIC_BASE_URL或者 API Key 没注入。CI 配置里加上env: ANTHROPIC_BASE_URL: https://taotoken.net/api ANTHROPIC_API_KEY: ${{ secrets.TAOTOKEN_API_KEY }}Key 在 https://taotoken.net/console/api-keys 生成存到 CI 的 secrets 里。接入细节参考 https://taotoken.net/doc 。6. 长期协作把 .claude 当知识库管跑通上面这套之后.claude目录的同步基本不会再出大事故。剩下的是长期维护问题。几个实操建议。规则文件只增不改这条要严格执行。改规则就新建api-call-v3.md在context.md里把引用从 v2 换成 v3旧文件留着回溯。这样 Git 合并时大家都是加文件冲突概率接近零。给规则文件加失效日期。文件头部写一行expires: 2025-06-01CI 里加检查过期文件自动标记提醒维护者清理避免规则库越堆越乱。监控变更频率。某个文件每天被改超过 3 次说明粒度太粗拆成更细的文件。我们之前把一个大context.md拆成context-db.md、context-api.md、context-arch.md冲突率降了八成。任何改.claude目录的 PR要求附带一句“为什么改”。这个约束看着简单但能挡掉大量随手改导致的漂移。如果团队要长期跑编码 Agent、做自动化 review可以考虑 Coding Plan 把额度固定下来 https://taotoken.net/coding-plan 。接入层稳定了.claude目录的同步才有意义——毕竟规则和上下文最终都是喂给模型的模型入口不统一共享目录也白搭。