fix(merge): in-place 合并脏树守卫忽略未跟踪文件(--untracked-files=no)

之前 mergeInPrimaryCheckout 用 git status --porcelain 判脏,未跟踪文件(GEMINI.md/.claude/
本地杂物)也算进去 → 误判拒绝合并(jiu/dudu 等带未跟踪文件的项目「通过并合并」必失败)。
改为 --untracked-files=no 只看已跟踪改动;未跟踪文件不挡合并(真要被覆盖时 git merge 自报错走 catch)。
测试加:仅未跟踪文件 → 仍 in-place 合并成功。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-13 14:40:31 +08:00
parent c1cdcc7e5e
commit d160d27645
2 changed files with 20 additions and 2 deletions
+4 -2
View File
@@ -29,7 +29,9 @@ export function mergeWorktreeDirFor(taskId: string): string {
*/
/**
* 目标分支正被主检出(repoPath)占用时的合并:直接在主检出里 `git merge --no-ff`。
* 这是用户手动合并会做的事,安全;但要求工作区干净,否则可能与未提交改动纠缠 → 拒绝。
* 这是用户手动合并会做的事,安全;但要求工作区无【已跟踪】的未提交改动,否则可能纠缠 → 拒绝。
* 注意:只看已跟踪改动(--untracked-files=no)。未跟踪文件(项目常有的本地杂物 GEMINI.md/.claude/…)
* 不算脏——它们不会被合并纠缠;万一某未跟踪文件恰好会被合并覆盖,git merge 会自己报错、走下方 catch。
*/
async function mergeInPrimaryCheckout(
repoPath: string,
@@ -37,7 +39,7 @@ async function mergeInPrimaryCheckout(
defaultBranch: string,
taskId: string,
): Promise<MergeResult> {
const dirty = (await git(repoPath, ['status', '--porcelain']).catch(() => '')).trim();
const dirty = (await git(repoPath, ['status', '--porcelain', '--untracked-files=no']).catch(() => '')).trim();
if (dirty) {
return {
ok: false,