name: conflict-resolver description: 智能 Git 合并冲突解决,带有上下文分析、模式检测和自动化解决策略…
冲突解决器技能
智能 Git 合并冲突解决,带有上下文分析、模式检测和自动化解决策略。
说明
您是一名 Git 合并冲突解决专家。当调用时:
-
分析冲突:
- 识别冲突类型(内容、结构、空格)
- 理解双方更改的上下文
- 确定每个分支的意图
- 评估合并策略的可行性
-
提出解决方案:
- 在安全时建议自动解决
- 提供手动解决指南
- 解释每种方法的权衡
- 警告潜在问题
-
解决策略:
- 接受传入/当前更改
- 智能结合双方更改
- 重构代码以容纳双方
- 需要时建议重构
-
验证解决方案:
- 确保语法正确性
- 保持代码一致性
- 保留两组功能
- 推荐测试方法
冲突类型
1. 内容冲突
- 同一位置的线级更改
- 对相同代码的不同修改
- 重叠的功能更改
2. 结构冲突
- 函数/类重组
- 文件移动和重命名
- 模块重构
3. 语义冲突
- API 签名更改
- 接口修改
- 破坏性更改
4. 空格/格式化
- 缩进差异
- 行尾更改
- 代码格式化冲突
使用示例
@conflict-resolver
@conflict-resolver --analyze src/auth/login.js
@conflict-resolver --auto-resolve simple
@conflict-resolver --strategy combine
@conflict-resolver --validate
理解 Git 冲突
冲突标记
<<<<<<< HEAD (当前更改)
// 您当前分支的代码
const result = newImplementation();
=======
// 传入分支的代码
const result = differentImplementation();
>>>>>>> feature-branch (传入更改)
冲突解剖
<<<<<<< HEAD:当前分支更改的开始=======:更改之间的分隔符>>>>>>> branch-name:传入更改的结束
解决策略
策略 1:接受当前(我方)
# 接受所有当前分支更改
git checkout --ours path/to/file
# 针对特定文件
git checkout --ours src/utils/helper.js
# 解决后
git add src/utils/helper.js
何时使用:
- 功能分支更改不正确
- 当前实现更完整
- 传入更改已过时
策略 2:接受传入(对方)
# 接受所有传入分支更改
git checkout --theirs path/to/file
# 针对特定文件
git checkout --theirs src/api/endpoints.js
# 解决后
git add src/api/endpoints.js
何时使用:
- 传入更改取代当前
- 传入分支进行重大重构
- 当前更改是实验性的
策略 3:手动解决
# 在编辑器中打开文件并手动解决
# 寻找冲突标记并编辑
# 编辑后,暂存文件
git add path/to/file
# 检查状态
git status
策略 4:三方合并工具
# 配置合并工具(一次性设置)
git config --global merge.tool vimdiff
# 或:meld、kdiff3、p4merge 等
# 使用合并工具
git mergetool
# 清理备份文件
git clean -f
常见冲突场景
场景 1:导入语句冲突
冲突:
<<<<<<< HEAD
import { useState, useEffect } from 'react';
import { useAuth } from './hooks/useAuth';
=======
import { useState, useEffect, useContext } from 'react';
import { useAuth } from './hooks/auth';
>>>>>>> feature-branch
解决方案(结合双方):
import { useState, useEffect, useContext } from 'react';
import { useAuth } from './hooks/useAuth'; // 保持正确路径
场景 2:函数实现冲突
冲突:
<<<<<<< HEAD
async function fetchUser(userId) {
const response = await fetch(`/api/users/${userId}`);
return response.json();
}
=======
async function fetchUser(userId) {
const response = await fetch(`/api/v2/users/${userId}`, {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) {
throw new Error('Failed to fetch user');
}
return response.json();
}
>>>>>>> feature-branch
解决方案(结合双方最佳部分):
async function fetchUser(userId) {
const response = await fetch(`/api/v2/users/${userId}`, {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) {
throw new Error('Failed to fetch user');
}
return response.json();
}
场景 3:配置冲突
冲突:
<<<<<<< HEAD
{
"name": "my-app",
"version": "1.2.0",
"scripts": {
"start": "node server.js",
"test": "jest"
}
}
=======
{
"name": "my-app",
"version": "1.3.0",
"scripts": {
"start": "node server.js",
"test": "jest",
"lint": "eslint ."
}
}
>>>>>>> feature-branch
解决方案(使用更高版本和所有脚本):
{
"name": "my-app",
"version": "1.3.0",
"scripts": {
"start": "node server.js",
"test": "jest",
"lint": "eslint ."
}
}
场景 4:类方法冲突
冲突:
class UserService {
<<<<<<< HEAD
async createUser(userData: UserData): Promise<User> {
const user = await this.db.users.create(userData);
return user;
}
=======
async createUser(userData: CreateUserDto): Promise<User> {
const validated = await this.validate(userData);
const user = await this.db.users.create(validated);
await this.sendWelcomeEmail(user);
return user;
}
>>>>>>> feature-branch
}
解决方案(结合验证和邮件):
class UserService {
async createUser(userData: CreateUserDto): Promise<User> {
const validated = await this.validate(userData);
const user = await this.db.users.create(validated);
await this.sendWelcomeEmail(user);
return user;
}
}
高级解决技巧
模式 1:并行功能开发
情况:两个分支在同一文件中添加不同功能
<<<<<<< HEAD
function processData(data) {
// 功能 A:添加日志
console.log('Processing data:', data);
const result = transform(data);
console.log('Result:', result);
return result;
}
=======
function processData(data) {
// 功能 B:添加验证
if (!data || !data.length) {
throw new Error('Invalid data');
}
const result = transform(data);
return result;
}
>>>>>>> feature-branch
解决方案(结合双方功能):
function processData(data) {
// 功能 B:添加验证
if (!data || !data.length) {
throw new Error('Invalid data');
}
// 功能 A:添加日志
console.log('Processing data:', data);
const result = transform(data);
console.log('Result:', result);
return result;
}
模式 2:重构冲突
情况:一个分支重构而另一个添加功能
<<<<<<< HEAD
// 重构版本,带有新结构
class AuthService {
constructor(private config: AuthConfig) {}
async authenticate(credentials: Credentials) {
return this.performAuth(credentials);
}
private async performAuth(credentials: Credentials) {
// 认证逻辑
}
}
=======
// 原始版本,带有新功能
class AuthService {
async authenticate(username, password) {
// 认证逻辑
}
async refreshToken(token) {
// 新功能:令牌刷新
}
}
>>>>>>> feature-branch
解决方案(保留重构并添加功能):
class AuthService {
constructor(private config: AuthConfig) {}
async authenticate(credentials: Credentials) {
return this.performAuth(credentials);
}
async refreshToken(token: string) {
// 新功能:令牌刷新
// 使用新结构实现
}
private async performAuth(credentials: Credentials) {
// 认证逻辑
}
}
模式 3:API 签名更改
情况:函数签名在两个分支中都更改
<<<<<<< HEAD
// 更改返回类型
async function getUser(id: string): Promise<UserDto> {
const user = await db.users.findById(id);
return this.mapToDto(user);
}
=======
// 添加参数
async function getUser(id: string, includeProfile: boolean): Promise<User> {
const user = await db.users.findById(id);
if (includeProfile) {
user.profile = await db.profiles.findByUserId(id);
}
return user;
}
>>>>>>> feature-branch
解决方案(结合双方更改):
async function getUser(
id: string,
includeProfile: boolean = false
): Promise<UserDto> {
const user = await db.users.findById(id);
if (includeProfile) {
user.profile = await db.profiles.findByUserId(id);
}
return this.mapToDto(user);
}
合并冲突命令
检查冲突状态
# 查看有冲突的文件
git status
# 查看冲突差异
git diff
# 查看特定文件中的冲突
git diff --ours path/to/file
git diff --theirs path/to/file
# 查看三方差异
git diff --base path/to/file
解决命令
# 接受当前分支版本
git checkout --ours path/to/file
# 接受传入分支版本
git checkout --theirs path/to/file
# 手动解决后
git add path/to/file
# 解决所有冲突后继续合并
git merge --continue
# 如果需要,中止合并
git merge --abort
# 标记为已解决
git add .
git commit
合并工具命令
# 启动合并工具处理所有冲突
git mergetool
# 使用特定合并工具
git mergetool -t vimdiff
git mergetool -t meld
# 在合并工具会话中跳过文件
# (只需关闭合并工具窗口)
# 对二进制文件接受远程版本
git checkout --theirs path/to/binary/file
git add path/to/binary/file
自动化冲突解决
简单自动解决脚本
#!/bin/bash
# auto-resolve.sh - 自动解决简单冲突
# 函数:如果一方明显更好,则自动解决
auto_resolve_file() {
local file=$1
# 检查文件是否有冲突
if git diff --check "$file" 2>/dev/null | grep -q "conflict"; then
echo "分析 $file..."
# 如果传入只是空格更改,保持我方
if git diff --theirs "$file" | grep -E "^[+-]\s*$"; then
echo "空格冲突,保持当前版本"
git checkout --ours "$file"
git add "$file"
return
fi
# 如果当前只是空格更改,保持对方
if git diff --ours "$file" | grep -E "^[+-]\s*$"; then
echo "空格冲突,接受传入版本"
git checkout --theirs "$file"
git add "$file"
return
fi
echo "复杂冲突,需要手动解决"
fi
}
# 处理所有冲突文件
git diff --name-only --diff-filter=U | while read file; do
auto_resolve_file "$file"
done
# 报告剩余冲突
remaining=$(git diff --name-only --diff-filter=U | wc -l)
if [ $remaining -gt 0 ]; then
echo "$remaining 个文件仍有冲突,需要手动解决"
git diff --name-only --diff-filter=U
else
echo "所有冲突已解决!"
fi
智能合并策略配置
# 配置 git 使用更好的合并策略
# 使用耐心算法(更适合重构)
git config --global merge.algorithm patience
# 启用 rerere(重用记录的解决方案)
git config --global rerere.enabled true
# 在冲突标记中显示共同祖先
git config --global merge.conflictstyle diff3
diff3 格式:
<<<<<<< HEAD
// 当前更改
const result = newImplementation();
||||||| base
// 共同祖先
const result = oldImplementation();
=======
// 传入更改
const result = differentImplementation();
>>>>>>> feature-branch
冲突预防策略
1. 经常变基
# 保持分支更新
git checkout feature-branch
git fetch origin
git rebase origin/main
# 逐步解决冲突
# 一次提交一次地修复冲突
git add .
git rebase --continue
2. 小规模、专注的提交
# 制作原子提交
git add -p # 交互式暂存更改
git commit -m "feat: 添加特定功能"
# 在小提交上更容易解决冲突
3. 沟通
# 在进行大型更改前
# 1. 检查其他人正在做什么
# 2. 沟通您的更改
# 3. 协调重构
4. 功能标志
// 使用功能标志避免冲突
const useNewImplementation = featureFlags.newAuth;
function authenticate(credentials) {
if (useNewImplementation) {
return newAuthFlow(credentials);
}
return oldAuthFlow(credentials);
}
解决后测试
验证清单
# 1. 确保没有冲突标记残留
grep -r "<<<<<<< HEAD" src/
grep -r "=======" src/ | grep -v "node_modules"
grep -r ">>>>>>>" src/
# 2. 语法检查
npm run lint
# 3. 运行测试
npm test
# 4. 构建项目
npm run build
# 5. 手动测试受影响的功能
解决后脚本
#!/bin/bash
# verify-resolution.sh
echo "检查剩余冲突标记..."
if grep -r "^<<<<<<< \|^=======$\|^>>>>>>> " --include="*.js" --include="*.ts" src/; then
echo "错误:找到冲突标记!"
exit 1
fi
echo "运行代码检查器..."
npm run lint || exit 1
echo "运行测试..."
npm test || exit 1
echo "构建项目..."
npm run build || exit 1
echo "所有检查通过!"
复杂冲突场景
场景:文件移动和修改
# 分支 A:移动文件
git mv src/utils/old.js src/helpers/new.js
# 分支 B:修改文件
# 编辑 src/utils/old.js
# 冲突:Git 可能无法检测到移动
# 解决方案:
# 1. 接受移动
git checkout --theirs src/helpers/new.js
# 2. 移除旧位置
git rm src/utils/old.js
# 3. 将修改应用到新位置
# 手动应用分支 B 的更改
场景:文件删除与修改
# 分支 A:删除文件
git rm src/deprecated.js
# 分支 B:修改文件
# 编辑 src/deprecated.js
# 冲突:一个分支删除,另一个修改
# 解决方案选项 1:保持删除
git rm src/deprecated.js
# 解决方案选项 2:保持修改
git add src/deprecated.js
场景:二进制文件冲突
# 二进制文件无法合并
# 检查文件历史
git log --follow -- path/to/image.png
# 选择版本
git checkout --ours path/to/image.png
# 或
git checkout --theirs path/to/image.png
# 暂存解决方案
git add path/to/image.png
最佳实践
合并前
- 拉取最新更改:
git fetch && git pull - 审查更改内容:
git diff main...feature-branch - 理解双方分支:知道每个更改了什么
- 沟通:如果需要,与其他开发者交谈
解决期间
- 阅读上下文:查看周围代码
- 理解意图:每个更改试图做什么?
- 保留功能:尽可能保留双方功能
- 保持风格:遵循项目约定
- 逐步测试:每次解决后验证
解决后
- 移除标记:确保没有冲突标记残留
- 语法检查:运行代码检查器
- 运行测试:确保没有损坏
- 手动测试:测试受影响的功能
- 代码审查:让某人审查复杂解决方案
有用的 Git 配置
# 更好的冲突可视化
git config --global merge.conflictstyle diff3
# 启用 rerere(重用记录的解决方案)
git config --global rerere.enabled true
# 使用更好的合并算法
git config --global merge.algorithm patience
# 配置默认合并工具
git config --global merge.tool meld
# 不创建备份文件
git config --global mergetool.keepBackup false
# 自动暂存已解决文件
git config --global mergetool.keepTemporaries false
冲突解决工具
命令行
- vimdiff:内置,适合 vim 用户
- git mergetool:通用工具启动器
GUI 工具
- Meld:跨平台,可视化差异/合并
- KDiff3:三方合并工具
- P4Merge:Perforce 可视化合并工具
- Beyond Compare:商业,功能强大
- VS Code:内置合并冲突 UI
IDE 集成
- VS Code:内联冲突解决
- IntelliJ/WebStorm:智能合并功能
- GitKraken:可视化合并冲突解决
备注
- 始终理解双方试图实现的目标
- 如有疑问,询问冲突更改的作者
- 解决冲突后彻底测试
- 使用 rerere 避免两次解决相同冲突
- 保持提交小以减少冲突可能
- 与团队沟通大型重构
- 使用功能分支并频繁合并
- 考虑使用合并策略(我方、对方、递归)
- 记录复杂冲突的解决决策