
上一篇发出去后,评论区有人说 context 优化才是小事,怕的是 AI 改出看不见的坑。
昨天就踩了一个。
最近在做微信小程序的虚拟支付功能。12 个微服务都要接入,就让 Claude Code 帮忙写。
功能代码写完了。合并到 master 时报错:
fatal: refusing to merge unrelated histories
查了一下,12 个仓库全部被 shallow clone 过。功能分支和 master 找不到共同祖先。
发现问题
我有一个后端微服务矩阵,所有项目在同一个组织 codeup 下,目录结构类似:
~/workzone/my-company/
├── my-common/ # 公共模块
├── my-spring-common/ # Spring 公共模块
├── my-A/ # 业务服务 A
├── my-B/ # 业务服务 B
├── my-C/ # 业务服务 C
├── ... # 其他服务
我的指令大概是这样的:
本次功能开发涉及到的微服务工程都在同一个组织 key 下,你帮我都 clone 下来,checkout 到对应的开发分支,进行开发。
然后它就开始了。
功能代码确实写完了,每个服务都改了。我想把某个分支合并到 master,执行:
git merge master
报了 unrelated histories。
这个错误我以前只见过一次——两个仓库完全不相干,比如初始化了一个空仓库然后拉了另一个远程。
但这个分支是从 master checkout 的,不可能没有共同祖先。
查了一下:
git merge-base master feats/wx_virtual_pay
返回 exit code 1。没有输出。两个分支没有共同祖先。
排查
第一反应是看 reflog:
git reflog show feats/wx_virtual_pay
bed51f34 feats/wx_virtual_pay@{0}: commit: fix(微信虚拟支付): AiChatBusinessOrderServiceImpl添加handleOrderRefund方法
93e3cfcc feats/wx_virtual_pay@{1}: commit: cleanup: 删除 MINI_COURSE.virtualPayZoneId 配置(虚拟支付不需要zoneId)
96276cf2 feats/wx_virtual_pay@{2}: clone: from codeup.aliyun.com:.../my-A.git
关键在第 3 行。clone。
这个分支不是 checkout 出来的,是 clone 出来的。
再看 .git/shallow 文件:
cat .git/shallow
96276cf2611557f01f163e12fc34bf6376950e35
这个 hash 正好是分支上的第一个提交。也就是说,Claude Code 执行了类似这样的操作:
git clone --depth 1 git@codeup:.../my-A.git --branch feats/wx_virtual_pay
--depth 1 只拉了最新的几个提交,在 .git/shallow 里标记了边界。Git 不知道这个提交的 parent 是谁。
虽然 parent 提交本地恰好存在,但 shallow 标记让 Git 的遍历算法在那里停住了。所以 merge-base 找不到共同祖先。
12 个仓库,全部中招。
用一条命令批量检查:
for dir in ~/workzone/my-company/*/; do
if [ -f "${dir}.git/shallow" ]; then
branch=$(cd "$dir" && git branch --show-current)
echo "⚠️ $(basename $dir) ($branch) - shallow clone"
fi
done
跑出来:
⚠️ my-A (feats/wx_virtual_pay) - shallow clone
⚠️ my-B (feats/wx_virtual_pay) - shallow clone
⚠️ my-C (feats/wx_virtual_pay) - shallow clone
⚠️ my-common (master) - shallow clone
⚠️ my-D (feats/wx_virtual_pay) - shallow clone
⚠️ my-E (feats/wx_virtual_pay) - shallow clone
⚠️ my-F (feats/wx_virtual_pay) - shallow clone
⚠️ my-G (feats/wx_virtual_pay) - shallow clone
⚠️ my-H (master) - shallow clone
⚠️ my-I (feats/wx_virtual_pay) - shallow clone
⚠️ my-J (master) - shallow clone
⚠️ my-spring-common (feats/wx_virtual_pay) - shallow clone
9 个在功能分支,3 个在 master。全是 shallow clone。
原因

回看我的指令:
你帮我都 clone 下来,checkout 到对应的开发分支,进行开发。
我说了"clone"这个词。但没有指定不要用 --depth。AI 自行加了 --depth 1,它觉得这样更快。
浅克隆的问题

浅克隆不只是合不了。还有一个问题:无法 checkout 其他线上分支。
浅克隆后,Git 只知道当前分支的少量提交。checkout 到其他分支——master、dev、或者其他同事的分支——Git 会报错:
git checkout master
fatal: cannot lock ref 'refs/heads/master': reference is not a tree
原因是 Git 不知道 master 分支上那些提交对应的 tree object。--depth 1 只拉了当前分支最新的几个提交。
正常的全量 clone 后,所有远程分支的引用都在本地,可以随意 checkout。但浅克隆的仓库,你被锁死在 clone 时指定的那个分支上。
手动 git fetch origin <其他分支> 也不行。shallow 限制下,fetch 到的也是残缺的。
修复

好消息是:已有的提交没有丢,工作区的修改也在。
不能用"删分支重建"的方案。部分仓库有未提交的修改,直接 checkout 会丢。
先 commit 未提交的修改:
cd <repo>
git status
git add .
git commit -m "feat: 保存功能开发中的修改"
这步很重要。工作区有修改直接执行后续操作,可能会丢变更。
恢复完整历史:
cd <repo>
git checkout feats/wx_virtual_pay
git fetch --unshallow origin
git fetch origin master
git fetch --unshallow 从远程拉取所有缺失的提交,补齐 .git/shallow 标记的边界之后的历史。只改 git 内部对象,不影响已提交的代码、工作区、分支指针。
实际跑的时候,有几个仓库拉下来一堆 tag:
* [new tag] v1.8.6 -> v1.8.6
* [new tag] v1.8.7 -> v1.8.7
* [new tag] v1.8.8 -> v1.8.8
* [new tag] v1.8.9 -> v1.8.9
* [new tag] v1.9.0 -> v1.9.0
之前 --depth 1 把 tag 也截断了,现在补回来了。
验证一下:
git merge-base master feats/wx_virtual_pay
正常的话会返回一个 commit hash。
但我跑了 12 个仓库,有几个报了这个:
fatal: Not a valid object name master
这几个仓库 shallow clone 时只拉了功能分支,本地根本没有 master 分支,只有 origin/master 的引用。用 origin/master 即可:
git fetch origin master
git merge-base origin/master feats/wx_virtual_pay
返回 hash。修复成功。
12 个仓库全部验证通过:

✅ my-A merge-base: bed51f34
✅ my-B merge-base: 93e3cfcc
✅ my-C merge-base: 96276cf2
✅ my-common 完整仓库(原 shallow,已修复)
✅ my-D merge-base: 7cf7e94b (origin/master)
✅ my-E merge-base: 512593f0 (origin/master)
✅ my-F merge-base: ac85c3f7
✅ my-G merge-base: 87dfa03f (origin/master)
✅ my-H 完整仓库(原 shallow,已修复)
✅ my-I merge-base: 4bd1c0c8
✅ my-J 完整仓库(原 shallow,已修复)
✅ my-spring-common merge-base: 0a9b58ef (origin/master)
同时也能自由 checkout 其他分支了。
几点经验
让 AI clone 仓库时,明确说不要 --depth。它为了省时间会自己加,不会告诉你。
或者更好的方式——不要 clone,在现有仓库上操作:
cd ~/workzone/my-company/my-A
git checkout feats/wx_virtual_pay
git pull origin feats/wx_virtual_pay
需要隔离环境?用 git worktree:
git worktree add ../my-A-feature feats/wx_virtual_pay
一个独立目录,同一份仓库。不截断历史,不重复下载。
AI 的"优化"可能是炸弹。我说了"clone 下来",AI 自行决定加 --depth 1。它没有全局视角理解仓库和 master 的关系、后续需要 merge、历史完整性很重要。AI 擅长局部最优,不擅长全局约束。需要人把关。
检查你的仓库是不是也被 shallow 过:
cat .git/shallow 2>/dev/null && echo "⚠️ shallow clone" || echo "✅ 完整仓库"
AI 编码工具确实快。跨 12 个仓库写功能代码,人工可能要一天,它几十分钟就搞定了。
但规模一大,质量就不好说了。
这个坑,我排查+修复花了半小时。
还有之前踩过的其他坑——接口定义和实现对不上、边界条件漏处理、异常路径没覆盖——都不是一眼能看出来的。等上了生产、出了问题,回头看代码才发现是 AI 写的时候埋的雷。
写代码快不等于省时间。擦屁股的时间可能比开发时间还长。
欢迎评论区聊聊你用 AI 编码踩过的坑。
夜雨聆风