ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Git 合并冲突怎么解决?用 AI 处理冲突的流程、Prompt 和 4 个易错点

Git 合并冲突怎么解决?用 AI 处理冲突的流程、Prompt 和 4 个易错点 目录一、合并之前先看会冲突在哪二、先改一个配置让冲突块带上 base三、再补一层两边为什么改四、哪些冲突可以交给 AI五、哪些冲突必须自己拍板六、可复制 Prompt七、4 个易错点1. 两边都留结果做了两遍2. 悄悄丢掉一边3. rebase 时 ours 和 theirs 是反的4. 没报冲突的地方才最危险八、合并完的验收清单九、什么时候别让 AI 碰小结合并冲突本身不难删掉几行标记、留下该留的代码而已。难的是看不出两边原本想干什么。默认的冲突块里只有两段代码你的和对方的。缺了最关键的一段——它们分叉之前长什么样。人缺这段信息要靠猜AI 缺这段信息也在猜而且猜得很自信。这篇记我现在处理冲突的流程合并前先预判冲突了先把信息补齐再分清哪些交给 AI、哪些自己拍板最后用几条命令验收。附一段可复制的 Prompt。一、合并之前先看会冲突在哪冲突最好在合并之前就知道。Git 2.38 起有个不碰工作区的「预演」命令gitmerge-tree --write-tree --name-only main feature它不动工作区、索引和当前分支只在后台把两个分支试合一遍输出第一行是合并结果的树对象可以忽略后面列出的就是会冲突的文件。有冲突时退出码是 1也能直接放进脚本里用。开 PR 之前我还会在 wescode 里问一句「我的分支和 main 有没有改到同一个函数」把两边都改过的函数列出来提前找改同一处的同事对一下。⟦截图wescode 里询问「我的分支和 main 有潜在冲突吗」的回答说明文字「合并前按函数预判冲突」⟧二、先改一个配置让冲突块带上 base默认的冲突标记长这样 HEAD timeout : 30 * time.Second timeout : cfg.Timeout feature/config只看这两段没法判断该留谁。是你把超时改成了 30 秒还是对方原来是多少打开 zdiff3Git 2.35 及以上更老的版本用diff3gitconfig--globalmerge.conflictStyle zdiff3同一个冲突会变成这样 HEAD timeout : 30 * time.Second ||||||| 8a9b3c1 timeout : 60 * time.Second timeout : cfg.Timeout feature/config|||||||和之间多出来的这段就是两边分叉前的原始版本base。现在一眼能看清你把默认超时从 60 秒改成了 30 秒对方把硬编码改成了读配置。两边的意图并不冲突正确的合并大概率是保留读配置同时把配置里的默认值改成 30 秒。这一条对 AI 同样关键。没有 base它只能在两段代码里二选一或者硬拼有了 base它能分别说出两边各改了什么。已经冲突了才想起来没开可以对单个文件重新生成带 base 的冲突标记gitcheckout--conflictzdiff3 -- path/to/file注意这会丢掉你在这个文件里已经做的解决最好一开始就执行。三、再补一层两边为什么改冲突块只告诉你改了什么不告诉你为什么。下面几条命令补齐剩下的信息# 列出所有冲突文件gitdiff--name-only --diff-filterU# 两边动过这个文件的提交gitlog--merge--oneline-- path/to/file# 连同具体改动一起看gitlog--merge-p-- path/to/file# 分别查看三个版本的完整文件gitshow :1:path/to/file# basegitshow :2:path/to/file# ours当前分支gitshow :3:path/to/file# theirs合进来的分支commit message 写得好不好这时候最能看出来。fix(pay): 回调超时从 60s 改为 30s避免上游重试堆积能直接回答「为什么」update只能去翻 PR 或者找人问。四、哪些冲突可以交给 AI冲突类型典型样子处理方式两边各加了不同的 import / 依赖同一位置各加了几行都保留去重、排序两边往同一个列表里加了不同的项路由注册、配置项、枚举值都保留确认顺序是否有含义一边改格式一边改逻辑缩进换行 vs 实际改动以逻辑改动为准合完再格式化一边改注释一边改代码文档注释 vs 函数体合完检查注释是否还对得上共同点两边的意图不冲突只是改到了相邻的行。这类交给 AI 能省不少时间风险也低。我在 wescode 里遇到这类冲突基本直接交给它合合完扫一眼 diff 就提交。五、哪些冲突必须自己拍板1. 两边改了同一段逻辑目的不同比如一边把重试次数从 3 改成 5另一边把重试整个换成了指数退避。AI 可以给方案但「要不要保留、参数取多少」是业务判断不是文本合并。2. 一边删了一边改了git status里显示deleted by us或deleted by them。这种冲突没有冲突块可看本质是一个决定对方删掉这个文件的理由是否盖过了你这次的修改。先问删文件的人。3. lock 文件和生成文件go.sum、package-lock.json、pnpm-lock.yaml、*.pb.go、mock 文件——别让 AI 手工拼哈希或者合生成代码。先解决源头文件再用工具重新生成# Go先解决 go.modgo.sum 取任意一边后整理gitcheckout--ours-- go.sumgo mod tidy# npm / pnpm先解决 package.json再重新安装生成 lockgitcheckout--ours-- package-lock.jsonnpminstallgitcheckout--ours-- pnpm-lock.yamlpnpminstall# 生成代码先解决 .proto 或接口定义再跑项目自己的生成命令4. 数据库迁移文件两个分支各加了一个迁移文件文件名不同Git 通常不报冲突。但序号撞了、或者执行顺序和依赖关系错了要到部署时才暴露。合并后顺手看一眼迁移目录的顺序。六、可复制 Prompt你在帮我解决一个 Git 合并冲突。只处理我给出的冲突块冲突块以外的代码不要动。 背景 - 当前分支ours分支名目的一句话 - 合入分支theirs分支名目的一句话 - 相关提交git log --merge --oneline 的输出 粘贴 冲突块zdiff3 格式含 base 粘贴 要求 1. 先分别说明相对 baseours 改了什么、theirs 改了什么 2. 判断两边能否同时保留如果语义互斥停下来说明分歧不要替我选 3. 给出合并后的代码并标注每一处来自 ours / theirs / 新写 4. 不要为了「兼容两边」把作用相同的两份逻辑都留下 5. 列出合并后需要我验证的点调用方、测试、配置第 3 条最有用标了来源review 时一眼就能看出它有没有悄悄丢掉某一边。我在 wescode 里的做法是把冲突文件进对话再贴上面这段。冲突文件多的时候先让它排处理顺序依赖文件go.mod、package.json最先配置其次业务代码最后每解决一步就跑一次编译编译不过就停下来别等全部解完才发现问题。⟦截图wescode 对话里 冲突文件并贴入 Prompt 后的分析结果说明文字「每一处都标了来源的合并结果」⟧七、4 个易错点1. 两边都留结果做了两遍「两边都保留」是 AI 最常给的「安全」解法。重复的 import、重复的函数定义编译器会报错但同一个中间件注册两次、同一条配置写两遍、同一个事件发两次编译器不管。看到「两边都保留」的方案专门检查一下是不是同一件事被做了两遍。2. 悄悄丢掉一边反过来它也可能整块采用了一边另一边的修改就这么没了。冲突标记删得干干净净看起来一切正常。解决完、提交前对每个冲突文件跑这两条gitdiffHEAD--stat-- path/to/file# 合并结果 vs oursgitdiffMERGE_HEAD--stat-- path/to/file# 合并结果 vs theirs哪一条的输出是空的就说明合并结果和那一边一模一样——另一边对这个文件的改动被整块丢了。要么确认是有意为之要么回去查。rebase 时把MERGE_HEAD换成REBASE_HEAD。3. rebase 时 ours 和 theirs 是反的merge 时ours 当前分支theirs 合进来的分支rebase 时反过来ours 你要变基到的目标分支比如 maintheirs 正在重放的你自己的提交所以在 rebase 过程中执行git checkout --theirs保留的是你自己的改动。人经常搞混AI 也一样。给 AI 贴冲突时别只写「保留 ours」直接说清楚「保留 main 上的版本」还是「保留我这个提交的版本」。4. 没报冲突的地方才最危险一个分支把GetUser改名成FindUser并更新了所有调用另一个分支新写了一处GetUser调用。两边改的不是同一行Git 自动合并一个冲突都不报。编译型语言会在编译时报错还算幸运。更糟的是只改语义、不改签名一边把CalcFee的返回值从「元」改成了「分」另一边新增的调用还在按「元」用。编译通过测试没覆盖到就这么上线了。这类问题在冲突块里根本看不到只能靠两件事合并后做完整的编译和测试不只跑冲突文件相关的那部分把对方分支改过签名或语义的函数列出来逐个查它们在你这边的新增调用第二件我是在 wescode 里直接问「feature 分支上改过签名的函数有哪些main 这边谁在调用它们」然后逐个点过去看。用命令行的话先git diff main...feature找出对方改过签名的函数再git grep -n 函数名搜调用方通过接口间接调用的地方要额外留意。八、合并完的验收清单# 1. 残留的冲突标记git add 不会拦你所以 add 已解决的文件之后再查一遍gitdiff--cached--check# 2. 两边的改动都在对每个冲突文件gitdiffHEAD--stat-- path/to/filegitdiffMERGE_HEAD--stat-- path/to/file# 3. 完整构建和测试换成你项目的命令go build ./...gotest./...git diff --check也会报行尾空格这类问题重点看leftover conflict marker那几行。长期分支反复 rebase、同一处冲突一次次重复解的可以打开 rerere让 Git 记住你的解法gitconfig--globalrerere.enabledtrue下次遇到同样的冲突会自动套用。但它复用的也可能是你上次的错误解法所以上面的验收一步都别省。九、什么时候别让 AI 碰冲突一大片的时候。长期分支合 main一下冲突几十个文件。这时先git merge --abort考虑按 main 上的提交分几段合进来每次解一小批。规模一大AI 逐个文件处理很容易前后不一致。你不知道对方为什么这么改的时候。去问写代码的人比问 AI 靠谱。AI 只能从代码推测意图推测错了还很有说服力。lock 文件和生成文件。交给工具重新生成前面说过了。小结处理合并冲突信息比技巧重要合并前先用git merge-tree预判哪些文件会冲突打开 zdiff3让冲突块带上 base用git log --merge看两边为什么改机械冲突交给 AI语义冲突自己拍板lock 文件和生成文件交给工具验收三件事没有残留标记、两边的改动都在、完整编译测试通过AI 在这件事上的价值是把「读懂两边各改了什么」这一步做快。至于该保留谁仍然是人的决定。上面的流程我是在 wescode 里跑的官网是 weisyn.com。你们团队处理冲突有什么约定比如谁的分支谁负责解欢迎评论区聊聊。
返回列表