Aider 陷阱合集

Aider 的坑和 IDE 类工具很不一样——Git 自动提交、/add /drop 手动管理、多模型切换,每一个机制都能咬你一口。7 个真实坑。

踩过新坑?提 Issue 或 PR。


陷阱 1:自动 commit 吃进了你的工作树变更

症状

  • 你在项目里改了几个文件还没 commit
  • 让 Aider 改一个别的文件
  • 它生成代码后自动 commit,把你未 stage 的变更也一起打包提交

根因 Aider 默认开启 auto-commits: true。它 commit 的范围是整个工作树 diff,不区分"我改的"和"用户改的"。Aider 觉得"改完就提交"是好事,不知道你有别的工作正在进行。

出坑

git reset HEAD~1        # 取消最后一次 commit,文件回到工作树
git status              # 核对哪些是你的、哪些是 Aider 的
# 手动 commit 该 commit 的,丢弃该丢的

预防 三选一:

  1. 开会话前先 git stash:把你未完成的工作藏起来,Aider 的 commit 才干净
  2. 关闭自动 commitaider --no-auto-commits,或在 .aider.conf.ymlauto-commits: false
  3. 开独立 feature 分支git checkout -b feature/xxx 再开 Aider,弄脏也只是脏分支

陷阱 2:/add 漏文件,AI 靠脑补填空

症状

  • 让 Aider 改 ServiceA,它顺利改完
  • 但 ServiceA 依赖的 UtilB 里的函数签名其实已经变了,Aider 不知道,生成的代码调用了根本不存在的签名
  • 跑起来 TypeError

根因 Aider 只把 /add 过的文件真正读进上下文。Map 模式会索引项目结构(名字+位置),但不读内容。依赖文件没 /add,AI 只能基于文件名猜。

出坑

/add src/utils/UtilB.ts
# 把依赖也加进来,让它重新看一遍
重新看一下 ServiceA 依赖的 UtilB,确认你用的签名是对的

预防 改之前先让 Aider 自己列出依赖:

/ask
我要改 ServiceA。列出它直接依赖的所有文件,
以及它的公开接口被哪些文件调用。
给我 /add 的命令,我一次性加齐。

然后把它列的都 /add 进来再开始 /code


陷阱 3:切了模型,行为突然变了

症状

  • 原来用 Claude,习惯了它的严谨风格
  • 为了省钱切到 DeepSeek,同一个提示词产出质量断崖下跌
  • 复杂重构开始出奇怪的 bug,Architect 模式给的方案也变得粗糙

根因 不同 LLM 的"指令理解能力"差异很大。同样一句 /architect 设计 WebSocket 通知系统

  • Claude Sonnet:会追问需求、考虑异常路径
  • DeepSeek:直接给一个方案,细节覆盖不全
  • 本地 7B 模型:给一个结构对但细节漏洞很多的方案

出坑

  • 复杂任务发现模型跟不上:切回 Claude 做这一步,做完再切回便宜模型
  • --weak-model 分工:主推理用强模型,commit message/简单任务用弱模型

预防 配置分层(.aider.conf.yml):

model: claude-sonnet-4-5           # 主模型
weak-model: deepseek/deepseek-chat # 弱任务(commit message、简单补全)
editor-model: claude-haiku-4-5     # 编辑器补全

按任务类型切:

任务建议模型
/architect 方案设计Claude Sonnet/Opus
/code 实现已有方案DeepSeek 够用
/ask 问答/解释任意
大型重构Claude Opus

陷阱 4:Lint/Test 自动循环,账单爆炸

症状

  • 配了 auto-lint: trueauto-test: true
  • Aider 改完跑 lint 失败,它自己修,又失败,又修……循环几轮
  • 一次对话下来 token 消耗是预期的 5 倍

根因 Aider 的 auto-lint/test 是 "失败就让 LLM 再改一次"。如果问题根本不是代码能修好的(比如环境配置、依赖版本),它会永远修不好,一直重试直到达到默认上限。每次重试都烧 token。

出坑

/undo                     # 回滚本轮修改
/lint-cmd none            # 临时关掉 auto-lint
# 手动修根本问题(环境、配置),再打开 auto-lint

预防

  • 限制重试次数(aider --max-reflections 3
  • lint 命令用 --fix 模式让 linter 先尝试自动修复,而不是报错扔给 AI:
lint-cmd: "eslint --fix"   # 不是 "eslint"
  • 测试命令跑 fail-fast:
test-cmd: "pytest -x --maxfail=1"

陷阱 5:Map 模式过期,引用了已删除的文件

症状

  • 项目结构变了(删了目录、重命名了模块)
  • Aider 还"记得"旧结构,生成 import 路径引用不存在的模块
  • 或者 /ls 列出的文件和磁盘对不上

根因 Map 模式的索引在会话开始时生成,会话中如果 git 层面大变(切分支、rebase、大规模删除),Map 不自动刷新。

出坑 退出 Aider 重进,Map 会重建。 或者在会话里:

/reset             # 清空会话上下文
/map-refresh       # 重新扫描项目结构(取决于版本是否支持)

预防

  • 切分支后重启 Aider(别在同一会话里跨分支操作)
  • 大规模文件变更后也重启
  • 长会话定期 /reset 刷新状态

陷阱 6:Architect 方案漂亮,Code 执行跑偏

症状

  • /architect 给出一个清晰的方案,你很满意
  • 切回 /code 让它实现,头一两个文件还对,越往后越偏
  • 最后成品和 Architect 方案几乎不一样

根因 Aider 的 Architect 和 Code 模式共享会话上下文,但 Architect 阶段的设计很长,随着 Code 阶段不断改代码,早期的 Architect 方案被上下文压缩逐步丢失。

出坑

# 每实现一步后,复核一次方案
/ask 对照 Architect 阶段的方案,当前实现偏离了哪些点?

预防

  • Architect 方案生成后立刻写进文件把这个方案写到 docs/arch.md,我们照这个文件实现
  • 实现阶段明确引用文件:/add docs/arch.md 按这里的方案实现下一步
  • 复杂任务每个模块开独立会话:一个会话做一个子模块,避免长会话漂移

陷阱 7:/commit--amend 失控

症状

  • 你让 Aider 改一下刚才的某个文件(已经自动 commit 了)
  • 它做完又 commit 了一次
  • 你想"合并到刚才的 commit",让它 --amend
  • 结果 amend 把你之前 stash 的内容吃进来了,或者把 Aider 的两次改动合进去,历史反而更乱

根因 Aider 的 commit 时机是"改完就提交",不是"原子化每个逻辑改动"。你手动 amend 会混入所有当前 staged 内容。同时 Aider 本身不支持精细的 commit 粒度控制。

出坑

git reflog                    # 找回 amend 前的状态
git reset --hard HEAD@{N}     # 回滚
# 用 interactive rebase 重新整理
git rebase -i HEAD~5

预防

  • Aider 会话结束后统一 squash
    git reset --soft HEAD~N   # N = Aider 的 commit 数
    git commit -m "feat: add notifications"
    
  • 别在 Aider 会话进行中用 --amend
  • 关键 checkpoint 自己打 tag:git tag wip-before-aider,出事能回

贡献新陷阱

模板见 claude-code.md 结尾


相关方法论