mcpField
G
git-conflict-resolve

git-conflict-resolve

github.com/fudesign2008开发685 次安装1 天前更新
代码仓库

关于 git-conflict-resolve

git-conflict-resolve 是用于处理 Git 合并与变基冲突的语义分析 Skill,避免盲目选择一方。它逐文件分析变更并按置信度决定处理方式,随后验证文件并生成手动审查清单。

主要功能

  1. 01处理合并与变基冲突
  2. 02分析冲突双方的变更
  3. 03分类冲突与构建产物
  4. 04按置信度分级处理
  5. 05验证文件并生成审查清单

适用场景

  1. 01处理发布分支合并冲突
  2. 02处理变基过程中的多轮冲突
  3. 03确认有歧义的变更后再处理
  4. 04检查已解决文件中的残留标记

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/fudesign2008/open-skills --skill git-conflict-resolve

安装后在 Claude Code 中输入/git-conflict-resolve确认已加载。

附带文件reference.md

详细介绍

Git 冲突解决工作流(git-conflict-resolve)

概述

一种由语义驱动的 Git 冲突解决协议,用于替代盲目使用 -X ours/-X theirs 策略。

对于每个冲突文件:首先运行语义分析,了解双方的意图,然后推导出一条解决规则(并给出置信度)。高置信度的冲突会自动解决;中置信度的冲突会显示建议并等待确认;低置信度的冲突会显示三方视图并等待人工决策。解决冲突后,会逐个对每个文件进行逻辑验证,并生成最终的人工审核清单。

配套技能:由 git-release-finish 阶段 6 调用;也可以单独调用以处理任何合并/rebase 冲突。


输入参数

参数描述示例
source正在合入的分支(通常是发布分支)release/8.2.60
target合并目标分支(通常是 main/master)master
version版本号(用于命名合并分支)8.2.60
mode冲突场景:merge 或 rebasemerge

单独调用示例:

运行 git-conflict-resolve 技能,参数为 source=release/8.2.60、target=master、version=8.2.60、mode=merge


子阶段 Y.0 — 模式检测与初始化

  1. 读取输入参数并确认 mode(merge 或 rebase)
  2. 初始化累计冲突文件列表(一个会在所有轮次中持续保留的全局变量——绝不能在任何时候清空)
  3. 根据模式进行初始化:

merge 模式(默认):

# Create the merge branch from the target branch (no -X auto strategy, so conflicts surface naturally)
git checkout origin/<TARGET> -b merge-release/<VERSION>
git merge origin/<SOURCE> --no-commit --no-edit

⚠️ 不要使用 -X ours 或 -X theirs——盲目选择一方可能会悄无声息地丢弃逻辑。冲突应通过下方的语义分析逐个文件决定。

rebase 模式:

# Create a local working branch from the remote source (avoids polluting the original remote branch)
git checkout origin/<SOURCE> -b rebase-release/<VERSION>

# Replay source's commits one by one onto target
git rebase origin/<TARGET>
# Stops on conflict → proceed to Y.1
# If rebase completes with no conflicts → skip Y.1–Y.4, go straight to Y.5

⚠️ 推送 rebase 结果时,如果目标是受保护分支(release/*、main、master),远程服务可能会拒绝强制推送(remote: rejected)。推送前请检查分支保护;如有必要,应推送到新分支(例如 rebase-release/<VERSION>)并新建 MR,而不是强制推送到原分支。


子阶段 Y.1 — 冲突清单(跨轮次汇总)

⚠️ 在 rebase 模式下,每次执行 git rebase --continue 后出现新冲突时,都必须重新运行 Y.1,并将新文件追加到累计列表中——绝不能替换该列表。

# Get the conflicted files for the current round
git diff --name-only --diff-filter=U

追加规则:

cumulative list = cumulative list ∪ current round's conflicted files
(set union — no duplicates, but the round in which each file first appeared is retained)

输出格式:

【Conflict inventory — round N】
New conflicted files this round (M):
  - path/to/file-a.ts (new)
  - path/to/file-b.ts (new)

Cumulative conflict file list (K total, across all rounds):
  - path/to/file-a.ts (round 1)
  - path/to/file-b.ts (round 2)
  ...

如果当前轮次的冲突列表为空:

模式含义后续操作
merge 模式git 已自动合并所有内容冲突(但仍可能存在语义问题)跳过 Y.2–Y.4,直接进入 Y.5;重点验证版本字段和构建产物路径
rebase 模式当前提交没有冲突运行 git rebase --continue;如果出现新冲突,返回 Y.1;如果 rebase 完成,则进入 Y.5

→ 如果列表不为空,则进入 Y.1.5 检查构建产物,然后再决定是否进入 Y.2 进行语义分析。


子阶段 Y.1.5 — 构建产物短路处理(编译/打包文件)

⚠️ 此阶段在 Y.2 的语义分析之前运行——这是节省 token、避免误判的关键前置关卡。

构建产物(编译/打包生成的派生文件)由机器生成:其内容非常庞大(单行压缩代码可能长达数十万字符),因此读取会浪费大量 token;压缩代码没有可供分析的“双方意图”;而强行合并很容易留下冲突标记,或保留过时版本。这类文件始终以发布分支为准——正确做法是不读取、不分析,直接采用发布分支一侧。

对于累积列表中的每个文件,请使用 reference.md 中的“构建产物识别清单”进行分类(构建输出目录前缀 ∪ 文件特征 ∪ 项目特定补充项):

  • 匹配构建产物 → 不读取三方内容,也不进入 Y.2 的语义分析;直接使用下方的短路处理表解决:

    冲突类型解决方法
    内容冲突(UU)/ 双方新增git checkout --theirs <FILE> && git add <FILE>(采用发布分支一侧)
    整个目录均为构建产物git rm -rfq <DIR> && git checkout origin/<SOURCE> -- <DIR> && git add <DIR>
    重命名 + 哈希冲突使用 git 的重命名元数据获取文件名(不要读取文件内容);删除旧的哈希文件,并从发布分支获取新文件——详情参见 Y.4

    解决后,仍须运行 Y.4.5 的即时验证(扫描残留冲突标记),确认没有遗漏。

  • 不匹配(源代码/配置) → 继续进行 Y.2 的常规语义分析。

⚠️ 默认谨慎处理:边界模糊的文件(既不在已知的构建输出目录中,也不匹配明确的产物特征)绝不能短路处理——应交由 Y.2 处理。若将源代码误判为构建产物,就会丢失目标侧的更改,而这远比多读取一个文件代价更高——有疑问时,宁可读取,也不要误判。

📖 识别清单、各类冲突的详细命令,以及重命名 + 哈希冲突的备用处理方法和理由,请参见 reference.md。


子阶段 Y.1.6 — 机械分流快速路径(语义分析前)

⚠️ 在 Y.1.5 的构建产物短路之后、Y.2 的语义分析之前运行。默认情况下,机械标准只提供证据,不直接得出结论:“采用我方版本”只有在子集检查证明后才有效。如果机械标准无法作出判断,则进入 Y.2 的常规语义分析和 Y.3 的置信度分级。

对于每个剩余的冲突块(已通过 Y.1.5 的源代码 / 配置 / 文档):

1. 子集差异检查(首选) — 对方的内容是否是我方内容的子集?

diff <(ours_block) <(theirs_block) | grep -c '^>'
#   0  → theirs ⊆ ours → take ours (🟢 high confidence), record the criterion in the log
#   >0 → escalate: union merge or take-theirs analysis below

2. 符号存在性检查(源文件) — 验证对方的顶层符号(函数 / 类 / 导出项)是否存在于我方内容中;如果我方的方法签名已涵盖对方所需的参数,则我方在功能上是超集。如果三方比较(基础版本 / 我方版本 / 对方版本)显示双方是同一功能的替代实现——属于设计分歧,而非内容丢失——则记录该发现,并通过置信度分级解决。

3. 按标题键去重的合并(规范 / 文档) — 对于具有标题结构的文件(例如 ## → ### Requirement: → #### Scenario:),保留我方的全部内容,并追加我方中不存在其标题的对方内容块;标题相同的条目合并一次,绝不重复。

diff3 解析陷阱 — 从文件内容解析冲突块之前,先检测 diff3 样式(块内的 ^\|{7,} 基础版本部分,或读取 git config merge.conflictStyle)。使用 diff3 时,冲突块包含四个部分:<<<<<<< HEAD 我方版本、||||||| base 基础版本、======= 分隔符、对方版本。只了解三段式格式的解析器会误将基础版本部分当作我方版本,并得出“我方是超集”的结论——这是错误判断。


子阶段 Y.2 — 语义分析

⚠️ 此阶段为只读阶段——不要修改任何文件。

对于每个冲突文件,按顺序执行以下操作:

1. 阅读三方内容

git show :1:<FILE>   # BASE: the common ancestor version
git show :2:<FILE>   # main side (ours): the target branch's version
git show :3:<FILE>   # release side (theirs): the source branch's version

注意:在合并和变基模式下,:2: 都表示主分支一侧,:3: 都表示发布分支一侧,含义相同。

2. 分析变更差异

# Compute the common ancestor
MERGE_BASE=$(git merge-base origin/<SOURCE> origin/<TARGET>)

# What changed on the main side relative to BASE
git diff $MERGE_BASE origin/<TARGET> -- <FILE>

# What changed on the release side relative to BASE
git diff $MERGE_BASE origin/<SOURCE> -- <FILE>

3. 输出语义描述

【Semantic analysis — <FILE>】
main side intent: [unchanged / hotfix / feature development / refactor / deletion / version-field update / other]
  Specific changes: ...

release side intent: [unchanged / hotfix / feature development / refactor / deletion / version-field update / other]
  Specific changes: ...

Relationship between the two sides: [mutually exclusive (one overrides the other) / complementary (both must be kept) / one-sided change (the other side is identical to BASE)]

子阶段 Y.3 — 规则推导

根据 Y.2 的语义分析结论,为每个文件推导解决规则和置信度。

三个置信度等级
置信度标准后续操作
🟢 高意图明确,一方具有绝对权威,且不存在丢失逻辑的风险自动解决,并输出所采取的操作
🟡 中大体明确,但存在局部歧义或需要部分合并提出建议,并等待用户确认 A/B/C
🔴 低无法确定权威一方,或双方都有必须保留的重要逻辑显示三方视图,由用户自行决定
冲突类型识别(推导的前提)

在推导规则之前,先识别冲突的结构类型——不同类型的解决策略完全不同,分类错误会导致残留冲突标记或更改丢失。

两步识别:

步骤 1——根据 git status 确定大类:

git status --porcelain                        # conflict status codes
git diff --name-status --diff-filter=U        # rename info
git status 代码类别含义
UU(双方均已修改)内容冲突双方修改了同一个文件
UU + 冲突标记引用不同的文件名重命名冲突diff3 格式的 HEAD/base/theirs 标签使用了不同的文件名
AA(双方均已添加)添加/添加冲突双方独立添加了一个同名文件
DU / UD删除/修改冲突一方删除,另一方修改

步骤 2——根据文件特征进一步判断:

构建产物的初步识别和短路处理已在 Y.1.5 中完成(匹配时采用发布侧,并且不会进入 Y.3)。此处的特征检查是后备措施:如果 Y.1.5 未识别到,但 Y.3 检测到构建产物特征,则将其视为构建产物(采用发布侧)。

# Build-artifact hash file (webpack/vite/rollup chunk)
echo "$FILE" | grep -qE '[0-9a-f]{8,}\.(js|css|map)$'

# Config file
echo "$FILE" | grep -qE '(^|/)(package\.json|tsconfig\.json|\.config\.(js|ts))$'
规则库

按冲突类型和置信度组织。先匹配结构类型,再根据具体场景推导。

🟢 高置信度场景:

冲突类型场景推导出的规则
内容冲突version/testVersion 字段:发布侧已更新采用发布侧(发布侧为权威)
内容冲突发布侧删除了某个函数/模块,主线对该代码未做任何更改(与 BASE 相同)遵循发布侧的删除意图(采用发布侧)
内容冲突构建产物路径(dist/、resources/dist/)的哈希不同整个目录采用发布侧
内容冲突发布侧进行了完整重构(逻辑相同、结构不同),主线未触及该区域采用发布侧
重命名 + 构建产物哈希diff3 标签引用了不同哈希文件名,文件名符合 [0-9a-f]{8,}\.(js|css|map)删除旧哈希文件 + 从发布侧采用新文件(参见专门的 Y.4 节)
添加/添加双方都添加了同名构建产物采用发布侧

⚠️ 重命名 + 构建产物哈希是容易出错的场景:简单地执行 git checkout --theirs 不起作用,因为重命名后文件名已改变——必须明确删除旧哈希文件,并从发布侧拉取新文件。详细流程请参见 Y.4。

🟡 中置信度场景:

冲突类型场景推导出的规则
内容冲突发布侧删除了某个函数/模块,但主线对该代码做了独立更改(热修复)手动确认主线的更改是否仍有必要
内容冲突发布侧进行了重构 + 主线有独立热修复(双方都做了更改,方向不同)优先采用发布侧,但手动确认主线的热修复是否已被取代
内容冲突双方都更改了导入语句合并双方的导入,手动确认没有重复项
内容冲突多字段配置文件:双方分别更改了不同字段逐字段列出,让用户选择
重命名 + 源代码源文件已重命名(非构建产物)手动确认重命名的意图

🔴 低置信度场景:

冲突类型场景推导出的规则
内容冲突双方都对业务逻辑做了实质性更改(方向互补或相关)展示三方视图——不建议自动解决
添加/添加添加了同名文件,且该文件不是构建产物展示三方视图,手动合并
删除/修改一方删除,另一方修改展示三方视图,手动确认是否仍需保留
任意文件不属于上述任何类别默认设为低置信度,展示三方视图

子阶段 Y.4 — 按类别解决

按 Y.3 中的置信度分类,依次处理每个文件:

🟢 高置信度 — 自动解决
# Take the release side (theirs)
git checkout --theirs <FILE>
git add <FILE>

# Take the main side (ours)
git checkout --ours <FILE>
git add <FILE>

# Take the release side for a whole directory (build artifacts, etc.)
git rm -rfq <DIR>
git checkout origin/<SOURCE> -- <DIR>
git add <DIR>
重命名 + 构建产物哈希策略(绝不读取文件内容)

此场景通常已由 Y.1.5 的前置短路处理(匹配到构建产物时直接采用发布侧)。如果 Y.1.5 未能捕获(回退情况),请使用此策略处理,并且优先使用 git 的重命名元数据确定文件名——绝不读取文件内容。

重命名后文件名会改变,因此 git checkout --theirs 可能指向一个已不存在的路径;必须明确处理旧文件名和新文件名:

# 1. Preferred: get both sides' filenames from git's rename metadata (never reads file content)
git diff --name-status --diff-filter=U
# Output looks like: R100 old-abc.js new-def.js → gives OLD_FILE / NEW_FILE

# 1b. Fallback: if rename metadata is missing, extract filenames only from the conflict-marker lines (do not read the full file)
OLD_FILE=$(git show :2:<FILE> | grep "^<<<<<<<" | sed 's/^.*HEAD://')
NEW_FILE=$(git show :3:<FILE> | grep "^>>>>>>>" | sed 's/^.*://' | tail -1)

# 2. Delete the old hash file (otherwise the repo ends up with two functionally identical chunks)
git rm -f "$OLD_FILE" 2>/dev/null

# 3. Take the new hash file from the release branch
git checkout origin/<SOURCE> -- "$NEW_FILE"
git add "$NEW_FILE"

⚠️ 为什么直接执行 git checkout --theirs 不起作用:在重命名冲突中,--theirs 的文件路径可能与工作树中的当前路径不同。若未删除旧文件,仓库中会留下两个功能相同的代码块(旧哈希 + 新哈希),构建可能会引用错误的文件。

输出日志:

✅ [High confidence] <FILE>
   Rule: release refactored, main unchanged → take the release side
   Action: git checkout --theirs <FILE> && git add <FILE>
🟡 中等置信度 — 给出建议,等待用户确认
【Conflicted file】<FILE>
【main-side change】...
【release-side change】...
【AI recommendation】Favor release; main's hotfix has already been superseded by xxx in release
【Please choose】
A = Accept the AI's recommendation (take the release side)
B = Keep the main side
C = I'll edit it manually — let me know when it's done
🔴 低置信度 — 展示三方视图,等待用户决定
【Conflicted file】<FILE>
【BASE (common ancestor), lines X–Y】
...(code)

【main side (ours), lines X–Y】
...(code)

【release side (theirs), lines X–Y】
...(code)

【AI analysis】Both sides made substantive logic changes — cannot determine an authoritative side
【Please choose】
A = Take the release side
B = Take the main side
C = I'll merge it manually — let me know when it's done
Y.4.5 — 即时验证(解决每个文件后必须执行)

⚠️ 快速失败原则:每解决一个文件后立即扫描,而不是等到 Y.5 批量验证。这样能立刻发现单个文件中的错误,回滚成本也很低(只需重新处理这一个文件)。等到 Y.5 再验证,可能会忘记当时是如何解决该文件的。

在 Y.4 中每个文件的解决操作完成后(git checkout --theirs/--ours、手动编辑、重命名 + 哈希策略等),立即运行:

# Pair-first verdict (authoritative rule in git-release-finish Phase 0; same semantics here):
# a match counts as residue only when <, >, or | markers are present; pure '=' lines
# (license underlines, Markdown separators) are false positives.
if git grep -qE '^<{7,} |^>{7,} |^\|{7,} ' -- "$FILE" 2>/dev/null; then
  echo "❌ $FILE resolution failed: conflict markers remain"
  # Roll back to the conflicted state and re-enter Y.2 for analysis
  git checkout MERGE_HEAD -- "$FILE" 2>/dev/null
  return 1
elif git grep -qE '^={7,}$' -- "$FILE" 2>/dev/null; then
  echo "ℹ️ $FILE has pure '=' lines (no markers) — pair-first false positive, clean"
else
  echo "✅ $FILE is clean"
fi

为什么使用精确正则,而不是宽泛匹配:<<<<<<<(7 个 < 字符后跟一个空格)会锁定 git 的冲突标记格式,排除 CSS 注释或 ASCII 艺术字中的 === 分隔线。^={7,}$ 要求整行只有等号,因此像 /* ====== */ 这样的 CSS 注释不会匹配(等号后面还有 */)。配对语义遵循 git-release-finish Phase 0 中权威的先配对规则。

为什么使用 git grep 而不是 grep -r:git grep 会自动遵循 .gitignore,且只扫描已跟踪文件,因此自然会排除未跟踪的构建产物;与精确正则结合后,形成双重过滤。

继续多轮 rebase

处理完当前轮次中的所有文件后:

git rebase --continue

如果出现新的冲突 → 返回 Y.1,追加到累计列表中,并继续执行 Y.2–Y.4。 如果 rebase 完成 → 继续执行 Y.5。


子阶段 Y.5 — 逻辑验证

逐个验证累计列表中的每个文件(不只是当前轮次中的文件)。

1. 验证完整保留发布意图

# Compare the resolution result against the original release-side version
git show origin/<SOURCE> -- <FILE>

检查:发布分支中的关键更改(函数、导入、逻辑块)是否已在解决结果中完整保留?

2. 验证 main 上必要的更改

# Compare the resolution result against the original main-side version
git show origin/<TARGET> -- <FILE>

检查:main 上是否有独立且必要的更改(例如热修复)被错误地丢弃?

3. 检查残留冲突标记(仅限累计列表中的文件)

不要扫描整个仓库。只扫描 Y.1 累计列表中的文件——这些是本次冲突解决涉及的唯一文件,因此也是唯一可能残留冲突标记的位置。扫描整个仓库会被构建产物中的 CSS 注释等内容产生的大量误报淹没。

# Scan only the cumulative-list files; the verdict is pair-first (pure '=' lines without
# <, >, or | markers are false positives — authoritative rule in git-release-finish Phase 0)
for FILE in $CONFLICT_FILES_CUMULATIVE; do
  git grep -qE '^<{7,} |^>{7,} |^\|{7,} ' -- "$FILE" 2>/dev/null \
    && echo "❌ $FILE has residual markers"
done

⚠️ 警告标准(符合任一项即标记为 ⚠️):

  • 发布分支中存在的函数 / 类 / 方法在解决结果中消失
  • 发布分支删除的代码在解决结果中重新出现(即被“还原”)
  • 发布分支中的某条导入语句在解决结果中缺失
  • 版本字段(version/testVersion)与发布分支不匹配
  • 发布分支重构了某些逻辑,但解决结果退回到旧实现

❌ 失败标准(符合任一项即标记为 ❌):

  • 文件中仍有残留冲突标记(<<<<<<<、=======、>>>>>>>)
  • 同一个函数 / 变量在解决结果中出现两次(重复合并)
  • 存在明显的语法错误(例如多余的 }、未闭合的括号)

验证输出:

✅ <FILE> — logically consistent (release intent fully preserved, main's necessary changes handled)
⚠️ <FILE> — possibly lost a release change: function/logic xxx does not appear in the resolution result
❌ <FILE> — logic conflict: residual <<<<< markers or an obvious semantic contradiction

⚠️/❌ 文件:不得提交——必须先重新处理,然后才能继续执行 Y.6。


子阶段 Y.6 — 全局审查清单 + 提交

输出摘要表(涵盖累计列表中的所有文件):

⚠️ The following files were changed during this conflict resolution — please review them carefully:

| File | Round appeared | Resolution | Confidence | Logic verification | Needs extra review |
|------|---------|---------|--------|---------|----------|
| src/effects/database/search-database.ts | round 1 | AI automatic (took release side) | 🟢 High | ✅ | — |
| package.json | round 1 | AI automatic (took release's version field) | 🟢 High | ✅ | — |
| src/components/editor.tsx | round 2 | User chose A (release side) | 🟡 Medium | ✅ | — |
| src/utils/helper.ts | round 1 | User merged manually | 🔴 Low | ⚠️ | ⚠️ Needs review |

Files that need extra review (⚠️/❌ verification, or 🔴 low confidence):
  - src/utils/helper.ts: verification result ⚠️, possibly lost a release change

After confirming the files above are logically correct, reply "continue" to complete the commit.

用户确认后(按模式执行):

合并模式:

git add -A

⚠️ 提交前门禁(L2 防御):在执行 git commit 之前,扫描所有已暂存文件,检查是否残留冲突标记。这是提交前的最后一道防线——即使跳过了 Y.4.5 即时验证或验证出错,它仍能发现问题。

# Scan all staged files; the verdict is pair-first (pure '=' lines are false positives,
# authoritative rule in git-release-finish Phase 0)
git diff --cached --name-only | while read f; do
  git grep -qE '^<{7,} |^>{7,} |^\|{7,} ' -- "$f" 2>/dev/null \
    && { echo "❌ Commit blocked: $f still contains conflict markers"; exit 1; }
done
# exit 1 → blocks the commit, go back to Y.4 to reprocess that file

门禁通过后:

git commit --no-verify -m "Merge release/<VERSION> into <TARGET>"

⚠️ 仅当提交前钩子因格式警告等原因阻止合并提交时,才使用 --no-verify;如果钩子运行了类型检查,请修复错误,而不是绕过检查。

变基模式:

# Each rebased commit has already been applied individually — no extra merge commit is needed
# Notify the caller (git-release-finish) to perform the final force-push
git rebase --continue   # if commits remain to finish from the last round
# Once the rebase completes, exit and let git-release-finish stage 6 take over the force-push

禁止行为(危险信号)

以下行为违反本协议。如果 AI 注意到自己即将执行其中任何一项,必须立即停止并返回正确步骤。

违规行为正确做法
新一轮变基产生冲突时,清空累计列表并从头开始必须追加——累计列表需始终保留,绝不能清空
在 Y.4 中解决某个文件后跳过 Y.4.5 即时验证,直接处理下一个文件每个文件都必须执行 Y.4.5——遵循快速失败原则
以“高置信度文件应该没问题”为由,跳过 Y.5 的逻辑验证累计列表中的每个文件都必须执行 Y.5,不得例外
生成 Y.6 审查清单后,未等待用户确认就自动提交执行 git commit 前必须等待用户回复“继续”
Y.6 提交前门禁检测到冲突标记后,以“影响很小”为由强行提交门禁是硬性拦截——必须返回 Y.4 修复,然后重新运行门禁
未实际运行 git show :1:/:2:/:3:,仅凭记忆在 Y.2 语义分析中描述双方内容必须先运行命令读取三方内容,再基于实际内容进行分析
对重命名 + 构建产物哈希冲突使用 git checkout --theirs(不删除旧文件)必须使用 Y.4 专用的重命名 + 哈希处理策略:删除旧文件,取用新文件
对双方都有复杂改动的文件套用高置信度规则,跳过中/低置信度的人工确认置信度必须依据 Y.3 的标准判定——绝不可主观拔高
逻辑验证结果为 ⚠️/❌ 后,以“影响很小”为由继续提交不得提交 ⚠️/❌ 文件——必须重新处理
对构建产物(已编译/打包的文件)运行 Y.2 语义分析,或读取其三方内容应采用 Y.1.5 的前置快速处理:匹配时直接采用 release 侧内容,不读取或分析(参见 reference.md)
使用 grep 读取文件内容,以提取重命名 + 构建产物哈希冲突的文件名优先使用 git diff --name-status --diff-filter=U 中的重命名元数据获取文件名;备用方案只读取冲突标记所在行,绝不读取整个文件

错误处理

场景处理方法
git show :1:/:2:/:3: 没有输出该文件没有对应的暂存阶段——使用 git status 检查其状态(可能已自动解决,也可能是新文件)
git merge-base 出错使用 git log --oneline --graph -10 检查分支拓扑,并手动指定基准提交
git rebase --continue 再次产生冲突正常情况——返回 Y.1,追加到累计列表,并继续循环
逻辑验证结果为 ❌,且没有明确的正确修复方案暂停,向用户展示 ❌ 文件的三方视图,并等待人工决定
git checkout --theirs/--ours 报错“pathspec not found”先运行 git add -A,然后重试

快速参考命令

# ── Conflict-marker detection (precise regex + pair-first verdict, shared by every defense layer) ──
# Matcher: git's conflict-marker format, 7+ characters at line start + space/end-of-line
# Verdict: a match is residue only when the marker regex matches too; pure '=' lines are false positives
RE='^<{7,} |^={7,}$|^>{7,} |^\|{7,} '
RE_MARKER='^<{7,} |^>{7,} |^\|{7,} '

# Y.4.5 single-file instant verification
git grep -qE "$RE_MARKER" -- "$FILE" 2>/dev/null && git grep -nE "$RE" -- "$FILE" 2>/dev/null

# Y.5 cumulative-list scan
for f in $CONFLICT_FILES; do git grep -qE "$RE_MARKER" -- "$f" 2>/dev/null && git grep -lE "$RE" -- "$f" 2>/dev/null; done

# Y.6 pre-commit gate (staged files)
git diff --cached --name-only | while read f; do
  git grep -qE "$RE_MARKER" -- "$f" 2>/dev/null && git grep -lE "$RE" -- "$f" 2>/dev/null && echo "❌ $f"
done

# ── Three-way version content ──
git show :1:<file>   # BASE
git show :2:<file>   # main side (ours)
git show :3:<file>   # release side (theirs)

# Each side's delta (compute MERGE_BASE first)
MERGE_BASE=$(git merge-base origin/$SRC origin/$TGT)
git diff $MERGE_BASE origin/$TGT -- <file>   # main's delta
git diff $MERGE_BASE origin/$SRC -- <file>   # release's delta

# ── Conflict-type identification ──
git status --porcelain                        # conflict status codes (UU/AA/DU/UD)
git diff --name-status --diff-filter=U        # rename info

# ── Resolve by confidence ──
git checkout --theirs <file> && git add <file>   # take the release side
git checkout --ours <file> && git add <file>     # take the main side

# Y.1.5 build-artifact short-circuit (match → take release side, no content read)
git checkout --theirs <file> && git add <file>                                       # content conflict / Add-Add
git rm -rfq <dir> && git checkout origin/<SOURCE> -- <dir> && git add <dir>           # whole-directory artifact

# rename + build-artifact hash (prefer rename metadata, never read file content)
git diff --name-status --diff-filter=U                                               # get OLD/NEW filenames
git rm -f "$OLD" 2>/dev/null && git checkout origin/<SOURCE> -- "$NEW" && git add "$NEW"

# continue the rebase
git rebase --continue

评论

支持 Markdown