
この記事をシェア
プロローグ:混乱する新人エンジニア

※画像はイメージです(CC0ライセンス)
新入社員の田中くんは、今日もまたターミナルの前で頭を抱えていました。
「うーん、merge...rebase...theirs...ours...一体何がなんだか...」
そんな様子を見かねた先輩の山田さんが声をかけました。
「田中くん、またGitで困ってる?よかったら一緒に整理してみない?」
「あ、山田先輩!実は...コンフリクトが起きるたびに、どの戦略を使えばいいのかわからなくて...」

※画像はイメージです(CC0ライセンス)
「そうだよね。最初は誰でも混乱するよ。まずは整理してみよう。Gitには大きく分けて4つの重要な概念があるんだ」
山田先輩は、ホワイトボードに向かって説明を始めました。
ストーリー:先輩の優しい解説タイム
第1章:mergeとrebaseの基本
「田中くん、まずこんな状況を想像してみて」
A---B---C (feature-branch)
/
D---E---F---G (main)
「feature-branch
で作業していて、main
ブランチに変更を取り込みたい時、2つの方法があるんだ」
1. Mergeの場合
「まずmerge
を使った場合:」
git merge main
「結果はこうなる:」
A---B---C---H (feature-branch)
/ /
D---E---F---G (main)
「Hがマージコミット
で、分岐した履歴がそのまま残るんだ」
2. Rebaseの場合
「次にrebase
を使った場合:」
git rebase main
「結果はこうなる:」
A'--B'--C' (feature-branch)
/
D---E---F---G (main)
「コミットが新しく作り直されて、直線的な履歴になるんだ」
「なるほど!でも、いつどちらを使えばいいんですか?」
「いい質問だね。一般的には:
merge
: チーム開発で履歴を保持したい時rebase
: 個人作業で綺麗な履歴にしたい時
に使うことが多いよ」
第2章:コンフリクトとの戦い
「でも実際の開発では、コンフリクトが起きることが多いよね。そこで登場するのが-X
オプションなんだ」
田中くんは身を乗り出しました。
「例えば、こんなファイルがあったとして:」
main.txt
(初期状態)
Hello World
feature-a
での変更
Hello World
This is feature A
feature-b
での変更
Hello World
This is feature B
「この状況で、feature-a
ブランチからfeature-b
をマージしようとすると...」
第3章:-X theirs と -X ours の魔法
「コンフリクトが起きた時の救世主が、-X theirs
と-X ours
なんだ」
-X theirs の場合
git merge -X theirs feature-b
「結果:」
Hello World
This is feature B # 相手側(theirs)の変更が優先される
-X ours の場合
git merge -X ours feature-b
「結果:」
Hello World
This is feature A # 自分側(ours)の変更が優先される
「あー!theirs
は相手、ours
は自分ってことですね!」
「その通り!覚えやすいでしょ?」
技術解説:実践で使える4つの戦略
ここからは、より技術的な詳細を見ていきましょう。
1. Merge戦略の詳細
基本的な使用方法
# 通常のマージ
git merge feature-branch
# Fast-forwardを無効化(常にマージコミットを作成)
git merge --no-ff feature-branch
# コミットを1つにまとめる
git merge --squash feature-branch
より複雑な例:JSONファイルの競合
初期ファイル(config.json
)
{
"name": "project",
"version": "1.0.0"
}
feature-a
での変更
{
"name": "project-a",
"version": "2.0.0",
"description": "Feature A"
}
feature-b
での変更
{
"name": "project-b",
"version": "1.5.0",
"author": "Team B"
}
-X theirs
を使用した場合:
git merge -X theirs feature-b
結果:
{
"name": "project-b",
"version": "1.5.0",
"author": "Team B"
}
2. Rebase戦略の詳細
インタラクティブrebase
# 直近の3つのコミットを編集
git rebase -i HEAD~3
利用可能なコマンド:
pick
: コミットをそのまま使用reword
: コミットメッセージを変更edit
: コミットを編集squash
: 前のコミットと統合fixup
: メッセージを破棄して統合drop
: コミットを削除
Rebaseでのコンフリクト解決
# rebase中にコンフリクトが発生
git rebase main
# コンフリクトを解決後
git add .
git rebase --continue
# rebaseを中止したい場合
git rebase --abort
3. 使い分けのベストプラクティス
Mergeを使用すべきケース
- 本番ブランチ(
main
/master
)への統合 - フィーチャーブランチの完了
- チーム開発での履歴保持
- リリースタグとの関連付け
Rebaseを使用すべきケース
- ローカルブランチの整理
- プッシュ前のコミット履歴の整頓
- 最新の
main
ブランチへの追従 - 個人作業でのクリーンな履歴作成
4. 安全な運用のための注意点
共有ブランチでのrebase禁止
# 危険:公開ブランチでのrebase
# NG
git checkout main
git rebase feature
# 安全:マージを使用
# OK
git checkout main
git merge feature
バックアップの重要性
# 作業前のバックアップ作成
git branch backup-before-merge
# 問題が発生した場合の復旧
git reset --hard backup-before-merge
変更内容の事前確認
# マージ前の差分確認
git diff feature-branch
# テストブランチでの試行
git checkout -b test-merge
git merge -X theirs feature-branch
実践編:よくあるシナリオ
シナリオ1:定期的なmain
追従
# feature開発中にmainの変更を取り込む
git checkout feature-branch
git rebase main # または git merge main
シナリオ2:大量コンフリクトの一括解決
# 自動的に自分の変更を優先
git merge -X ours main
# 自動的に相手の変更を優先
git merge -X theirs main
シナリオ3:コミット履歴の整理
# 複数コミットを1つにまとめる
git rebase -i HEAD~3
# エディタで "squash" を使用
エピローグ:成長した新人エンジニア
「山田先輩、ありがとうございました!これで自信を持ってGitを使えそうです」
「良かった!でも覚えておいて。これらのコマンドは強力だからこそ、使う前には必ずバックアップを取ることを忘れずに」
「はい!早速明日のタスクで実践してみます」
数週間後、田中くんは同期の新人に自信を持ってGitの使い方を教えている姿がありました。
まとめ:4つの戦略を使い分けよう
今回学んだ4つの概念を振り返ってみましょう:
Merge
: 履歴を保持しながら変更を統合Rebase
: 履歴を直線的に保ちながら変更を統合-X ours
: コンフリクト時に自分の変更を優先-X theirs
: コンフリクト時に相手の変更を優先
これらを適切に使い分けることで、チーム開発がよりスムーズになり、クリーンなGit履歴を維持できます。
最初は混乱するかもしれませんが、実践を重ねることで必ず身につきます。困った時は、まずはドキュメントを確認し、先輩に相談することを忘れずに。
Happy coding! 🚀
この記事が役に立ったら、ぜひチームメンバーとも共有してくださいね!