0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Git コンフリクトでJetBrains AI Assistantの自動マージを使ってみた

0
Last updated at Posted at 2026-05-27

はじめに

git でコンフリクトが起きたときに困るのは「どちらが正しいか」ではなく「両方正しい」ケース。

たとえば、

  • main ブランチ: register() にバリデーション(メール形式・パスワード長のチェック)の追加
  • feature-logging ブランチ: 同じ register() にログ出力の追加

どちらも正しい変更で、本来は両方取り込みたい。手動で2つの変更を読んで組み合わせて直す必要がある。変更箇所が多くなると、時間がかかるのと、見落としのリスクも上がる。

今回はIntelliJ IDEA AI Assistantの「AI で Git の競合を解決する」という機能があって、実際に2つのシナリオで試してみた。

AI で Git の競合を解決する

製品: IntelliJ IDEA 2026.1.2 / AI Assistant プラグイン有効
image.png

3ペインの構成

ペイン 内容
HEAD(今いるブランチ)の変更
中央 マージ結果(ここを編集して確定する)
マージしようとしているブランチの変更

シナリオ1: どちらか一方しか正解がないコンフリクト

まず「両立できない」ケースで動作確認しました。

同じ fetchUser() メソッドを2つのブランチで別々に変更した状態。

// 共通祖先  
public User fetchUser(String id) {  
    return users.get(id);  
}  
  
// main: キャッシュレイヤーを追加  
public User fetchUser(String id) {  
    User cached = cache.get(id);  
    if (cached != null) return cached;  
    User user = database.findById(id);  
    if (user != null) cache.put(id, user);  
    return user;  
}  
  
// feature-logging: 見つからない場合に例外を投げる設計に変更  
public User fetchUser(String id) {  
    User user = users.get(id);  
    if (user == null) throw new UserNotFoundException("User not found: " + id);  
    return user;  
}  

main はキャッシュ付きで nullable を返す設計、feature-logging は見つからなければ例外を投げる non-null 設計。戻り値の型が変わるほど本質的に異なる変更なので、両立はできない。

「AIを使用してマージする」をクリックすると、中央ペインに main 側(キャッシュ付き)の実装が採用された。採用された行は左・中央・右ペインを横断する線で囲まれ、どのペインの変更が中央に取り込まれたかが視覚的にわかる。

確認できたこと

  • AI は main 側を採用した
  • Apply 前に手動で編集できる
  • 採用されなかった右ペインの変更は残ったまま参照できる

気になった点

  • キャッシュ側を選んだ説明がなかった

シナリオ2: 両方の変更を統合できるコンフリクト(メイン)

次に「両方取り込める」ケース

// 共通祖先  
public User register(String email, String password) {  
    User user = new User(UUID.randomUUID().toString(), email, password);  
    database.save(user);  
    return user;  
}  
  
// main: 入力バリデーションを追加  
public User register(String email, String password) {  
    if (!email.contains("@")) {  
        throw new IllegalArgumentException("Invalid email format: " + email);  
    }  
    if (password.length() < 8) {  
        throw new IllegalArgumentException("Password too short (min 8 characters)");  
    }  
    User user = new User(UUID.randomUUID().toString(), email, password);  
    database.save(user);  
    return user;  
}  
  
// feature-logging: 監査ログを追加  
public User register(String email, String password) {  
    logger.info("Registering new user: " + email);  
    User user = new User(UUID.randomUUID().toString(), email, password);  
    database.save(user);  
    logger.info("User registered successfully: " + user.getId());  
    return user;  
}  

変更箇所が独立している(関数の先頭にバリデーション vs 関数の先頭と末尾にログ)ので、理論上は両方取り込んだ結果が存在する。

「AIを使用してマージする」をした結果:
image.png

ペイン 内容の概要
左 (main) if バリデーション 2行 → User 生成 → database.save → return
中央 (AI 結果) if バリデーション 2行 → logger.info → User 生成 → database.savelogger.info → return → (共通ブロック重複)
右 (feature-logging) logger.info → User 生成 → database.savelogger.info → return

AI は main のバリデーション 2行と feature-logging の監査ログを両方取り込んだ。 ただし、コンフリクト範囲外の共通ブロック(User 生成 → save → return)が末尾に重複して挿入された。シナリオ1は「どちらか一方」、シナリオ2は「両方統合」。

AI なしで同じコンフリクトを解決するとどうなるか

AI を使わずに手動解決しようとすると、

<<<<<<< HEAD  
public User register(String email, String password) {  
    if (!email.contains("@")) {  
        throw new IllegalArgumentException("Invalid email format: " + email);  
    }  
    if (password.length() < 8) {  
        throw new IllegalArgumentException("Password too short (min 8 characters)");  
    }  
    User user = new User(UUID.randomUUID().toString(), email, password);  
    database.save(user);  
    return user;  
}  
=======  
public User register(String email, String password) {  
    logger.info("Registering new user: " + email);  
    User user = new User(UUID.randomUUID().toString(), email, password);  
    database.save(user);  
    logger.info("User registered successfully: " + user.getId());  
    return user;  
}  
>>>>>>> feature-logging  

git は「同じ関数が変更されている」を提示

開発者は:

  1. マーカーを読んで、2つの変更の意図を把握する
  2. 「バリデーションはログより前に置くべきだ」と判断する
  3. 「開始ログはバリデーション後、完了ログは save 後」という順序を確認する
  4. 手動で組み合わせて書き直す
  5. マーカー行を削除してコミット

今回の例は変更行数が少ないので読み解くのは難しくないが、実際のコードで同じような状況が起きると「バリデーションの位置がずれていないか」「ログが抜けていないか」を注意深く確認する必要がある。変更量が増えるほど見落としのリスクは上がる。

使ってみての感想

よかった点

  • 「両方の変更を統合できるかどうか」を AI が判断して自動でやってくれる
  • 中央ペインで AI の判断を手動修正してから Apply できる。完全に任せきりにならない

不便だった点

  • 採用理由の説明がない。「なぜこちらを選んだか」「どの順序にしたか」が見えないと、より複雑なコンフリクトで不安が残る
  • AI の出力に手動確認が必要。検証では、統合の方向性は正しいのにコンフリクト範囲外の共通ブロックが重複挿入されてコンパイルエラーになるケースがあった。Apply 前に中央ペインを確認する必要がある

まとめ

公式ドキュメントには、「AI Assistant は、競合しない変更と競合する変更の両方をマージします」と書いてある。今回のテストで実際に確認できた。

AI は「両方の変更を統合する余地があるか」を判断している。余地があれば統合、なければ一方を選択——という挙動を確認した。

役立ちそうな場面は、変更箇所は独立しているのに git が同じ関数内の変更として検出するコンフリクト。バリデーション追加とログ追加、例外ハンドリング追加とメトリクス記録など、責務の異なる変更が同じメソッドに入ったケースで時間を節約できる。

ナットウシステムからのお知らせ

弊社は JetBrains 製品に関するご質問、ご相談等を受け付けております。弊社のXまたはメールでご連絡ください。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?