故障处理

Codex 无法 git commit:.git/index.lock 权限被拒怎么排查

Codex 能改代码却无法 git add 或 git commit?区分 index.lock 权限拒绝、锁占用与 dubious ownership,定位真实 Git 目录、检查生效权限,并审查暂存和提交结果。

Codex 已经改好代码,git status 也能显示改动,但一到 git add 或 git commit 就失败。先保留完整错误、失败命令和报错路径:能写源文件,并不代表能写 Git 的索引、对象或引用。

如果你搜索的是 codex git index.lock permission denied 或 Operation not permitted,先用下表分流。锁文件不存在也可能报“无法创建锁”,不能一看到 index.lock 就删文件。

先分清是哪种失败

错误或现象 先判断什么 下一步
Permission denied 或 Operation not permitted 创建或替换 Git 文件的权限被拒 查真实目录、系统权限与 Codex 生效策略
File exists 目标锁已存在,可能有任务在使用 查正在运行的 Git 操作,再判断是否为遗留锁
detected dubious ownership Git 不信任当前身份访问该仓库 核实仓库归属与信任,不当成锁权限修复
Author identity unknown、签名或 hook 失败 已进入其他提交阶段 按身份、签名或 hook 的具体错误处理
nothing to commit 当前目录或暂存内容不符合预期 查分支、worktree 与暂存区,不调整权限

只想找回另一目录中的改动时,先看 worktree 改动找不到。本文处理的是已经发生的 Git 写入失败。

1. 在失败的环境里定位真正的 Git 目录

适用情况: 已拿到错误,但还不能确定被拒的是哪个目录。让 Codex 在原执行环境运行以下检查;自己核对时,也要进入同一台主机、同一容器或 WSL 环境的同一仓库。

git --version
git rev-parse --show-toplevel
git rev-parse --path-format=absolute --git-dir
git rev-parse --path-format=absolute --git-common-dir
git rev-parse --path-format=absolute --git-path index
git --no-optional-locks status --short

这些命令用于读取位置与状态,最后一条避免 status 顺带进行可选的索引刷新。--git-dir 是当前工作树的 Git 元数据位置;--git-common-dir 是共享 Git 目录;--git-path index 给出索引路径。通常索引路径加上 .lock 就是对应的索引锁,仍以本次错误中的完整路径为准。

预期结果: 顶层目录是你要提交的项目;元数据目录和索引位置明确。worktree 的 .git 可以是一个指向其他位置的文件,不能只检查项目内的 .git 外观。Git 官方路径参考也支持对这些路径输出绝对位置。

如果命令提示不在仓库,先纠正工作目录。若提示不支持参数,记录 Git 版本,分别运行不带 --path-format=absolute 的命令,并按当前目录解释相对路径;不要把相对路径误当成仓库根目录下的位置。如果已出现 dubious ownership,直接进入第 4 步,先解决信任判断。

2. 权限被拒:比较系统访问与 Codex 策略

适用情况: 报错是 Permission denied 或 Operation not permitted。记录 Codex 客户端、CLI 版本,以及命令实际在本地、远程、WSL 还是容器运行;CLI 版本可在对应终端用 codex --version 查看。

先查看第 1 步得到的真实 Git 目录及其父目录。以下路径是占位示例,替换为刚刚读到的路径;不要照抄到其他项目。

macOS / Linux 可先查看目录和已有索引的基本权限:

ls -ld "/实际/Git目录" "/实际/Git目录的父目录"
ls -l "/实际/索引路径"

macOS 需要进一步查看 ACL 和文件标记时,使用 ls -ldeO 检查同一目标;Linux 若有额外 ACL、只读挂载或容器卷限制,需要继续查对应系统配置。基本权限位看起来可写,不能排除这些限制。

Windows 原生环境可只读显示目录 DACL:

whoami
icacls "C:\实际\Git目录"
icacls "C:\实际\Git目录的父目录"

这里的 icacls 没有带修改参数。查看当前身份适用的允许、拒绝与继承项;owner 相同也不代表一定可写。WSL 内失败则先查 WSL 内的路径和挂载,不能只看 Windows 终端中的同名项目。

随后检查 Codex 会话本身。当前 CLI 可在会话中使用:

/status
/debug-config

/status 用于查看当前审批策略、可写根目录等状态;/debug-config 用于定位配置层和策略来源。命令不存在时,以该版本命令菜单与帮助为准,不套用其他客户端的界面。

官方审批与安全文档说明,默认 workspace-write 模式仍把 .git 及指针解析后的 Git 目录保护为只读。因此,“仓库在可写根目录内”不足以证明可以提交。审批是否允许某次操作,与文件系统边界也需要分别看。

如果使用新版权限 profile,查当前选中的 profile 及覆盖规则。权限文档目前将该机制标为 Beta;继承 :workspace 会保留 .git 等路径的只读保护。它与旧的 sandbox_mode、sandbox_workspace_write 不是叠加配置;加载了旧 sandbox_mode 或传了 --sandbox 等情况下,可能仍在使用旧机制。不要把两套配置拼在一起,也不必为一次提交强行迁移。

如何据此操作:

  • 如果系统本身就拒绝访问,由仓库维护者修复已确认的目标目录权限或挂载问题,再复查同一个路径。不要递归改整个磁盘的 owner,也不要使用 chmod 777。
  • 如果证据指向 Codex 的 Git 目录保护,且这次暂存或提交已经获得授权,使用当前客户端和组织策略允许的单次审批或最小必要授权,核对完整命令与目标后再执行。
  • 如果管理策略禁止该操作,保留策略诊断,交管理员确认;若团队允许人工提交,可由你在正常授权的终端审查并完成第 5 步。不要用管理员身份重开所有程序或全局关闭沙箱来试错。

验证目标: 同一环境、同一仓库中的目标操作获准,且原拒绝不再出现。若外部终端成功而 Codex 仍失败,继续核对两者的身份、路径和策略差异;这条对比证据本身不能单独证明是哪项设置导致。

3. File exists:先确认谁在使用锁

适用情况: 完整错误明确写着锁已存在。Git 锁文件机制会在更新文件时创建锁,并在完成后替换目标文件;另一个写入者遇到已有锁会失败。

先检查当前终端、IDE 源码管理、其他 Codex 任务是否正在暂存、提交、合并、变基或等待提交消息编辑器。使用系统任务管理工具核对相关进程、启动时间与项目路径;让已知操作正常完成,再重试原来的单个操作。不要批量结束所有 Git 或 Codex 进程。

如果没有活动操作,但锁仍存在,记录实际锁路径、修改时间,以及此前是否有中断的 Git 操作。仅凭锁很旧,或者一次进程查询没找到结果,还不能证明它可删除。

只有仓库维护者确认相关写入者已退出、暂停该仓库的自动 Git 操作,并备份未提交工作与当前索引后,才处理这一个确认遗留的锁;可先移到有记录的备份位置。不要删索引文件本身,不要扫描并清空所有 .lock。处理后重试一次;锁立即重现时回到进程排查,若变成权限错误则回到第 2 步。

预期结果: 活动 Git 操作正常结束,或确认遗留锁被有范围地处理;原操作可以继续,原有暂存内容没有丢失。

4. dubious ownership:核实信任,别扩大到所有仓库

适用情况: Git 明确提示仓库归属可疑。先确认路径是否为你预期的仓库,是否由不同账号、管理员、容器或共享盘创建。若是打开错了副本,回到正确目录即可。

对确实需要使用的共享仓库,由维护者确认预期身份与归属。如果团队确认该仓库可信并允许添加例外,可按 Git 提示只为这个已核实的绝对路径设置 safe.directory,然后重新运行状态检查。Git 官方配置说明解释了它允许的是仓库信任例外。

不要将 safe.directory 设为 *,也不要把信任例外当作写权限授予。信任错误消失后若出现 index.lock: Permission denied,说明还需继续第 2 步。

5. 只暂存审查过的文件,再核对提交

适用情况: 原因已处理,且你确实要提交这些改动。先在正确仓库检查当前状态、已有暂存和未暂存差异:

git --no-optional-locks status --short
git diff --cached --stat
git diff --cached
git diff

git diff 不包含未跟踪文件正文;状态中的 ?? 文件需要另外打开审查。若暂存区已有他人的改动,先协调范围,不执行一次包含所有内容的提交。参见 Git 的 状态与 差异参考。

确认暂存区只会包含本次目标后,把下面占位路径与消息换为实际值,逐条执行:

git add -- "本次要提交的文件"
git diff --cached --name-status
git diff --cached
git commit -m "说明本次改动"
git show --stat --oneline HEAD
git --no-optional-locks status --short

看到暂存差异与预期不符就停在提交之前。提交后,确认新提交包含目标文件;需要核对正文时再运行 git show HEAD。其他原有未提交改动应仍在预期状态;仓库不必完全干净。Git commit 文档说明了默认提交暂存内容的行为。

如果新的错误是身份、签名或 hook 失败,就沿新错误处理,不再反复调整锁权限。暂存成功只证明这一步可以写索引,不能代替提交成功的验证。

仍然失败时,带哪些信息求助

提供脱敏后的失败命令、完整错误、Git 与 Codex 版本、执行环境、仓库顶层/Git 目录/索引位置,以及当前策略来源。说明失败发生在 add 还是 commit,是否有其他活动 Git 操作;不要上传整个配置、环境变量、私有差异或凭据。

配置明明改了却未生效,可继续查 config.toml 排障;脚本退出状态不明确时,查 codex exec 输出与异常退出。如果连 CLI 版本都与预期不同,先核对 更新后版本没变。

本文于 2026-10-17 核对官方资料,并在 macOS 独立测试仓库验证 worktree 路径、已有锁与目录不可写两类错误,以及审查后的提交结果。该验证没有调用模型,也没有模拟所有平台的 Codex 沙箱或管理策略;Windows 检查以官方命令资料为依据。

社区讨论

补充你的经验或问题

评论由 GitHub Discussions 承载;参与讨论需要登录 GitHub。