mcpField
C
conflict-resolver

conflict-resolver

github.com/curiouslearner開発2937 回インストール53 週間前に更新
リポジトリ

conflict-resolver について

conflict-resolverは、Gitのマージコンフリクトを分析して解決するスキルです。競合の種類と両ブランチの変更意図を調べ、解決策と結果の検証方法を提示します。

主な機能

  1. 01内容と構造の競合を分類
  2. 02両ブランチの変更意図を分析
  3. 03自動または手動の解決案を提示
  4. 04変更を組み合わせる戦略を提案
  5. 05解決後の検証手順を推奨

活用シーン

  1. 01ソースファイルの重複編集の解決
  2. 02マージ時のファイル移動や削除への対応
  3. 03API変更の調整

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/curiouslearner/devkit --skill conflict-resolver

インストール後、Claude Code で/conflict-resolverを入力して読み込まれたか確認します。

詳細

競合解決スキル

コンテキスト分析、パターン検出、自動解決戦略を備えたスマートな git マージ競合解決。

手順

あなたは git マージ競合解決の専門家です。呼び出されたときは、次のことを行います。

  1. 競合を分析する:

    • 競合の種類(コンテンツ、構造、ホワイトスペース)を特定する
    • 両方の変更のコンテキストを理解する
    • 各ブランチの意図を判断する
    • マージ戦略の実現可能性を評価する
  2. 解決策を提案する:

    • 安全な場合は自動解決を提案する
    • 手動解決のガイダンスを提供する
    • 各アプローチのトレードオフを説明する
    • 潜在的な問題について警告する
  3. 解決戦略:

    • 受信側/現在側の変更を受け入れる
    • 両方の変更をインテリジェントに統合する
    • 両方に対応できるようコードを再構成する
    • 必要に応じてリファクタリングを提案する
  4. 解決策を検証する:

    • 構文の正確性を確保する
    • コードの一貫性を維持する
    • 両方の機能セットを保持する
    • テスト手法を推奨する

競合の種類

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 (Current Change)
// Your current branch code
const result = newImplementation();
=======
// Incoming branch code
const result = differentImplementation();
>>>>>>> feature-branch (Incoming Change)
競合の構造
  • <<<<<<< HEAD: 現在のブランチの変更の開始
  • =======: 変更間の区切り
  • >>>>>>> branch-name: 受信側の変更の終了

解決戦略

戦略 1: 現在側を受け入れる(Ours)
# Accept all current branch changes
git checkout --ours path/to/file

# For specific files
git checkout --ours src/utils/helper.js

# After resolving
git add src/utils/helper.js

使用する場面:

  • フィーチャーブランチの変更が正しくない
  • 現在の実装の方がより完全である
  • 受信側の変更が古くなっている
戦略 2: 受信側を受け入れる(Theirs)
# Accept all incoming branch changes
git checkout --theirs path/to/file

# For specific files
git checkout --theirs src/api/endpoints.js

# After resolving
git add src/api/endpoints.js

使用する場面:

  • 受信側の変更が現在側を置き換える
  • 受信側ブランチで大規模なリファクタリングが行われた
  • 現在側の変更が実験的である
戦略 3: 手動解決
# Open file in editor and manually resolve
# Look for conflict markers and edit

# After editing, stage the file
git add path/to/file

# Check status
git status
戦略 4: 三方マージツール
# Configure merge tool (one-time setup)
git config --global merge.tool vimdiff
# Or: meld, kdiff3, p4merge, etc.

# Use merge tool
git mergetool

# Clean up backup files
git clean -f

よくある競合シナリオ

シナリオ 1: import 文の競合

競合:

<<<<<<< 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'; // Keep correct path
シナリオ 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: 並行した機能開発

状況: 2 つのブランチが同じファイルに異なる機能を追加している

<<<<<<< HEAD
function processData(data) {
  // Feature A: Add logging
  console.log('Processing data:', data);
  const result = transform(data);
  console.log('Result:', result);
  return result;
}
=======
function processData(data) {
  // Feature B: Add validation
  if (!data || !data.length) {
    throw new Error('Invalid data');
  }
  const result = transform(data);
  return result;
}
>>>>>>> feature-branch

解決(両方の機能を統合):

function processData(data) {
  // Feature B: Add validation
  if (!data || !data.length) {
    throw new Error('Invalid data');
  }

  // Feature A: Add logging
  console.log('Processing data:', data);
  const result = transform(data);
  console.log('Result:', result);

  return result;
}
パターン 2: リファクタリングの競合

状況: 一方のブランチがリファクタリングし、他方が機能を追加している

<<<<<<< HEAD
// Refactored version with new structure
class AuthService {
  constructor(private config: AuthConfig) {}

  async authenticate(credentials: Credentials) {
    return this.performAuth(credentials);
  }

  private async performAuth(credentials: Credentials) {
    // Auth logic
  }
}
=======
// Original with new feature
class AuthService {
  async authenticate(username, password) {
    // Auth logic
  }

  async refreshToken(token) {
    // New feature: token refresh
  }
}
>>>>>>> feature-branch

解決(リファクタリングを維持 + 機能を追加):

class AuthService {
  constructor(private config: AuthConfig) {}

  async authenticate(credentials: Credentials) {
    return this.performAuth(credentials);
  }

  async refreshToken(token: string) {
    // New feature: token refresh
    // Implement using new structure
  }

  private async performAuth(credentials: Credentials) {
    // Auth logic
  }
}
パターン 3: API シグネチャの変更

状況: 関数シグネチャが両方のブランチで変更されている

<<<<<<< HEAD
// Changed return type
async function getUser(id: string): Promise<UserDto> {
  const user = await db.users.findById(id);
  return this.mapToDto(user);
}
=======
// Added parameters
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);
}

マージ競合コマンド

競合ステータスを確認する
# View files with conflicts
git status

# View conflict diff
git diff

# View conflicts in specific file
git diff --ours path/to/file
git diff --theirs path/to/file

# View three-way diff
git diff --base path/to/file
解決コマンド
# Accept current branch version
git checkout --ours path/to/file

# Accept incoming branch version
git checkout --theirs path/to/file

# After manual resolution
git add path/to/file

# Continue merge after resolving all conflicts
git merge --continue

# Abort merge if needed
git merge --abort

# Mark as resolved
git add .
git commit
マージツールコマンド
# Launch merge tool for all conflicts
git mergetool

# Use specific merge tool
git mergetool -t vimdiff
git mergetool -t meld

# Skip a file during merge tool session
# (Just close the merge tool window)

# Accept remote version for binary files
git checkout --theirs path/to/binary/file
git add path/to/binary/file

自動競合解決

シンプルな自動解決スクリプト
#!/bin/bash
# auto-resolve.sh - Automatically resolve simple conflicts

# Function to auto-resolve if one side is clearly better
auto_resolve_file() {
  local file=$1

  # Check if file has conflicts
  if git diff --check "$file" 2>/dev/null | grep -q "conflict"; then
    echo "Analyzing $file..."

    # If incoming is just whitespace changes, keep ours
    if git diff --theirs "$file" | grep -E "^[+-]\s*$"; then
      echo "Whitespace-only conflict, keeping current version"
      git checkout --ours "$file"
      git add "$file"
      return
    fi

    # If current is just whitespace changes, keep theirs
    if git diff --ours "$file" | grep -E "^[+-]\s*$"; then
      echo "Whitespace-only conflict, accepting incoming version"
      git checkout --theirs "$file"
      git add "$file"
      return
    fi

    echo "Complex conflict, manual resolution needed"
  fi
}

# Process all conflicted files
git diff --name-only --diff-filter=U | while read file; do
  auto_resolve_file "$file"
done

# Report remaining conflicts
remaining=$(git diff --name-only --diff-filter=U | wc -l)
if [ $remaining -gt 0 ]; then
  echo "$remaining files still have conflicts requiring manual resolution"
  git diff --name-only --diff-filter=U
else
  echo "All conflicts resolved!"
fi
スマートマージ戦略の設定
# Configure git to use better merge strategies

# Use patience algorithm (better for refactorings)
git config --global merge.algorithm patience

# Enable rerere (reuse recorded resolutions)
git config --global rerere.enabled true

# Show common ancestor in conflict markers
git config --global merge.conflictstyle diff3

diff3 形式:

<<<<<<< HEAD
// Current change
const result = newImplementation();
||||||| base
// Common ancestor
const result = oldImplementation();
=======
// Incoming change
const result = differentImplementation();
>>>>>>> feature-branch

競合防止戦略

1. 頻繁にリベースする
# Keep branch up to date
git checkout feature-branch
git fetch origin
git rebase origin/main

# Resolve conflicts incrementally
# Fix conflicts one commit at a time
git add .
git rebase --continue
2. より小さく焦点を絞ったコミット
# Make atomic commits
git add -p  # Interactively stage changes
git commit -m "feat: add specific feature"

# Easier to resolve conflicts on small commits
3. コミュニケーション
# Before making large changes
# 1. Check what others are working on
# 2. Communicate your changes
# 3. Coordinate refactorings
4. フィーチャーフラグ
// Use feature flags to avoid conflicts
const useNewImplementation = featureFlags.newAuth;

function authenticate(credentials) {
  if (useNewImplementation) {
    return newAuthFlow(credentials);
  }
  return oldAuthFlow(credentials);
}

解決後のテスト

検証チェックリスト
# 1. Ensure no conflict markers remain
grep -r "<<<<<<< HEAD" src/
grep -r "=======" src/ | grep -v "node_modules"
grep -r ">>>>>>>" src/

# 2. Syntax check
npm run lint

# 3. Run tests
npm test

# 4. Build project
npm run build

# 5. Manual testing of affected features
解決後のスクリプト
#!/bin/bash
# verify-resolution.sh

echo "Checking for remaining conflict markers..."
if grep -r "^<<<<<<< \|^=======$\|^>>>>>>> " --include="*.js" --include="*.ts" src/; then
  echo "ERROR: Conflict markers found!"
  exit 1
fi

echo "Running linter..."
npm run lint || exit 1

echo "Running tests..."
npm test || exit 1

echo "Building project..."
npm run build || exit 1

echo "All checks passed!"

複雑な競合シナリオ

シナリオ: ファイルが移動され、かつ変更された
# Branch A: Moved file
git mv src/utils/old.js src/helpers/new.js

# Branch B: Modified file
# Edit src/utils/old.js

# Conflict: Git may not detect the move

# Resolution:
# 1. Accept the move
git checkout --theirs src/helpers/new.js
# 2. Remove old location
git rm src/utils/old.js
# 3. Apply modifications to new location
# Manually apply changes from branch B
シナリオ: ファイルが削除された vs 変更された
# Branch A: Deleted file
git rm src/deprecated.js

# Branch B: Modified file
# Edit src/deprecated.js

# Conflict: Deleted on one branch, modified on other

# Resolution option 1: Keep deletion
git rm src/deprecated.js

# Resolution option 2: Keep modification
git add src/deprecated.js
シナリオ: バイナリファイルの競合
# Binary files can't be merged

# Check file history
git log --follow -- path/to/image.png

# Choose version
git checkout --ours path/to/image.png
# OR
git checkout --theirs path/to/image.png

# Stage resolution
git add path/to/image.png

ベストプラクティス

マージ前
  • 最新の変更を取得: git fetch && git pull
  • 変更内容を確認: git diff main...feature-branch
  • 両方のブランチを理解: それぞれが何を変更したかを把握する
  • コミュニケーション: 必要に応じて他の開発者と話し合う
解決中
  • コンテキストを読む: 周囲のコードを確認する
  • 意図を理解: それぞれの変更が何をしようとしていたか?
  • 機能を保持: 可能な限り両方の機能を残す
  • スタイルを維持: プロジェクトの規約に従う
  • 段階的にテスト: 各解決の後に検証する
解決後
  • マーカーを削除: 競合マーカーが残っていないことを確認する
  • 構文チェック: リンターを実行する
  • テストを実行: 何も壊れていないことを確認する
  • 手動テスト: 影響を受けた機能をテストする
  • コードレビュー: 複雑な解決については誰かにレビューしてもらう

便利な Git 設定

# Better conflict visualization
git config --global merge.conflictstyle diff3

# Enable rerere (Reuse Recorded Resolution)
git config --global rerere.enabled true

# Use better merge algorithm
git config --global merge.algorithm patience

# Configure default merge tool
git config --global merge.tool meld

# Don't create backup files
git config --global mergetool.keepBackup false

# Auto-stage resolved files
git config --global mergetool.keepTemporaries false

競合解決ツール

コマンドライン
  • vimdiff: 組み込みで、vim ユーザーに強力
  • git mergetool: 汎用ツールランチャー
GUI ツール
  • Meld: クロスプラットフォームのビジュアル diff/マージ
  • KDiff3: 三方向マージツール
  • P4Merge: Perforce のビジュアルマージツール
  • Beyond Compare: 商用で強力
  • VS Code: 組み込みのマージ競合 UI
IDE 統合
  • VS Code: インラインでの競合解決
  • IntelliJ/WebStorm: スマートなマージ機能
  • GitKraken: ビジュアルなマージ競合解決

注意事項

  • 両側が何を達成しようとしているのかを常に理解する
  • 迷ったときは、競合する変更の作者に尋ねる
  • 競合を解決した後は徹底的にテストする
  • rerere を使って同じ競合を二度解決するのを避ける
  • 競合の可能性を最小限にするためにコミットを小さく保つ
  • 大規模なリファクタリングについてはチームとコミュニケーションを取る
  • フィーチャーブランチを使い、頻繁にマージする
  • マージ戦略(ours、theirs、recursive)の使用を検討する
  • 複雑な競合については解決の決定を文書化する

コメント