FOR BEGINNERS未経験向け

D開発の道具段1入口層仕組み

Git のブランチとマージの仕組み|main を直接触らない理由と、プルリクエスト・衝突の意味

Git のブランチとマージの仕組み|main を直接触らない理由と、プルリクエスト・衝突の意味

Git で add と commit はできるようになった。でも、チームの開発に入ると「ブランチを切ってからやって」「プルリクを出して」「コンフリクトしてるよ」と言われて手が止まる。そういう人に向けた記事です。ブランチは何を分けているのか、なぜ main を直接触ってはいけないと言われるのか、マージのときに Git の中で何が起きているのか、衝突(コンフリクト)はなぜ起きるのか。どれも、コミットが順につながった履歴と、それを指す目印の関係として見ると、一続きで説明できます。この記事では、Git と GitHub の公式ドキュメントを根拠に、ブランチ・マージ・衝突・プルリクエストの仕組みを順に整理します。コマンドの暗記ではなく、「いま自分がどの枝にいて、何をどこに入れようとしているか」が分かることを目指します。

この記事の結論

  • Git のブランチとは、あるコミットを指している動かせる目印で、枝を切ってもファイル一式は複製されません。
  • main を直接触らないのは、チームが使う「いま動いている版」に、作業途中の変更や誤りを混ぜないためです。
  • マージには、枝の先へ目印を進めるだけの早送り(fast-forward)と、2つの枝をまとめるマージコミットを作る形の2つがあります。
  • 衝突(コンフリクト)とは、同じ箇所への別々の変更をどちらにするか Git が決められず、人に判断を求めている状態です。
  • プルリクエストは GitHub の機能で、作業ブランチの変更を main に入れる前に、差分を見せて確かめてもらう場です。

ブランチとは(コミットを指す「しおり」)

READ ALSO — 未経験向け・段0 土台 Git とは何か|「上書き保存」と「版を残す」の違いを、最初の3つの動作で理解する

Git では、コミットのたびにその時点のファイルの写し(スナップショット)が残り、コミットは「1つ前のコミット」を覚えながら順につながっていきます。この一続きが履歴です。

ブランチは、その履歴の中のあるコミットを指している目印です。Git の公式ドキュメント(Pro Git)は、ブランチを「コミットを指す、軽くて動かせるポインタ」と説明しています。本にはさむしおりにたとえると分かりやすく、しおりを1枚増やしても本は複製されません。新しいコミットを作ると、いま使っているしおり(ブランチ)が、新しいコミットへ自動で1つ進みます。

「いまどのしおりを使っているか」を Git は HEAD という特別な目印で覚えています。ブランチを切り替えると HEAD が別のブランチを指すようになり、作業フォルダの中身もそのブランチが指すコミットの状態に入れ替わります。

git branch                 # ブランチの一覧(* が付いているのがいまのブランチ)
git switch -c fix-typo     # fix-typo という枝を作って、そこへ移る
git switch main            # main に戻る

git switch は枝の切り替え専用のコマンドで、古い資料では同じことを git checkout -b fix-typo と書いていることもあります。

言葉 何か たとえ
コミット ある時点のファイル一式の写しと、1つ前のコミットへのつながり 本の1ページ
ブランチ あるコミットを指す動かせる目印 しおり
HEAD いま使っているブランチを指す目印 いま開いているしおり
main チームが「いま動いている版」として扱う決まりのブランチ 正本のしおり

いちばん最初のブランチの名前は、GitHub で作ったリポジトリなら多くは main です。Git そのものの既定は master で、設定(init.defaultBranch)で変えられます。この記事では main と呼びます。

CHECK 1ここまでの確認

Git のブランチの正体として正しいのはどれ?

答えと解説

答え: 2. あるコミットを指している、動かせる軽い目印

Git の公式ドキュメントは、ブランチを「コミットを指す、軽くて動かせるポインタ」と説明しています。枝を切ってもファイルは複製されません。最初の章の「しおり」のたとえを読み直してください。

なぜ main を直接触らないのか?

main は、チームの全員が「ここから始めれば動く」と信じて使う版です。そこへ作業途中のコミットや、まだ誰も確かめていない変更を直接入れると、次のことが起きます。

  • 途中の変更が、ほかの人の作業にそのまま混ざる
  • 誤りに気づいたとき、どこまで戻せばよいかが分かりにくい
  • 本番に出す仕組みが main を見ていると、確かめていないものが出ていく

そこで、作業は main から枝を切った作業ブランチの上で進めます。枝の上なら、何度コミットしても main は動きません。できあがったら、確かめてから main に入れます。Git の公式ドキュメントも、ブランチを切ってはマージする作業の流れを、1日に何度も行うことをすすめています。枝を切る操作が軽いからこそできるやり方です。

BRANCH TO MAIN変更が main に入るまで

変更は枝の上で育て、見てもらってから main に入れる

  1. 枝を切る

    main から作業ブランチ

  2. コミット

    枝の上で積む

  3. push

    枝を GitHub に送る

  4. プルリクエスト

    差分を見せて確かめる

  5. マージ

    承認のあと main へ

「触らない」を運用だけでなく設定で守る

「main に直接 push しない」を人の注意だけで守るのは限界があります。GitHub には保護されたブランチ(protected branches)の設定があり、main へのマージの前にプルリクエストを必須にする、決まった人数の承認を必須にする、といったルールを掛けられます。GitHub Docs によると、承認が足りないプルリクエストを保護されたブランチにマージしようとすると、エラーになります。

PROTECTED BRANCHmain の門

main には、確かめたプルリクエストだけが入る

保護された main(ルールを満たしたものだけ通る)

  • push直接の push 通さない作業途中の変更をそのまま
  • PR承認待ち 待つレビューがまだ
  • PRテスト失敗 直す必須のチェックが失敗
  • PR承認・テスト済み マージレビュー済み
GitHub の保護されたブランチの設定で、プルリクエスト・承認・チェックの通過を必須にできる(GitHub Docs)

CHECK 2ここまでの確認

チームで開発するとき、main に直接コミットせず枝を切って作業する一番の理由はどれ?

答えと解説

答え: 2. 作業途中の変更を、ほかの人が使う main に混ぜずに、見てもらってから入れるため

main はチームの「いま動いている版」です。途中の変更や誤りを混ぜないために、枝の上で作業し、確かめてから main に入れます。書き込めないわけではなく、運用とブランチの保護の設定で守っています。

マージとは何をすることか?

マージは、別の枝で積んだ変更を、いまの枝に取り込む操作です。main に作業ブランチを取り込むなら、main に移ってから git merge 作業ブランチ名 を打ちます。Git の中で起きることは、枝の状態によって2通りあります。

早送り(fast-forward)

作業ブランチを切ってから main に誰もコミットしていないとき、main の先に作業ブランチのコミットがそのまま続いています。この場合、Git は main の目印を作業ブランチの先まで進めるだけで終わります。Pro Git はこれを、分かれた作業が無いので目印を前に進めるだけで済む「fast-forward」と説明しています。新しいコミットは作られません。

マージコミット(3つを比べてまとめる)

作業ブランチを切ったあとに、main にもほかの人の変更が入っていると、履歴は二股に分かれています。この場合 Git は、2つの枝の先と、分かれる前の共通の祖先の3つを比べて、両方の変更をまとめた新しいコミットを作ります。これをマージコミットと呼び、1つ前のコミットを2つ持つ特別なコミットになります。

TWO WAYS TO MERGEマージの2つの形

main が動いていなければ進めるだけ、動いていればまとめる

早送り(fast-forward)

取り込む側に新しいコミットが無い

  • 目印を先へ進めるだけ
  • 新しいコミットは作られない
  • 衝突は起きない

マージコミット

両方の枝に新しいコミットがある

  • 共通の祖先と2つの枝先を比べる
  • まとめたコミットを1つ作る
  • 同じ箇所の変更は衝突になる
Pro Git「Basic Branching and Merging」
比べるところ 早送り(fast-forward) マージコミット
起きる条件 枝を切ったあと、取り込む側に新しいコミットが無い 両方の枝に新しいコミットがある
Git がすること 目印を先へ進めるだけ 共通の祖先と2つの枝先を比べて、まとめたコミットを作る
新しいコミット 作られない 作られる(1つ前が2つある)
衝突 起きない 同じ箇所を別々に変えていると起きる

衝突(コンフリクト)とは何か?

マージコミットを作るとき、Git はほとんどの変更を自動でまとめます。別のファイルや、同じファイルでも離れた行の変更なら、両方を取り込めるからです。まとめられないのは、同じファイルの同じ箇所を、2つの枝が別々に書き換えていたときです。どちらが正しいかは中身の意味で決まるので、Git には判断できません。このとき Git はマージを途中で止め、人に判断を求めます。これが衝突(コンフリクト)です。

GitHub Docs は、衝突がよく起きる場面として、別々の人が同じファイルの同じ行を変えたときと、一方がファイルを書き換え、もう一方が同じファイルを消したときを挙げています。

衝突したファイルには、次のような印が書き込まれます。

<<<<<<< HEAD
タイムアウトは 30 秒
=======
タイムアウトは 60 秒
>>>>>>> fix-timeout

上の段がいまの枝(HEAD)の内容、下の段が取り込もうとした枝の内容です。直し方の流れは次のとおりです。

  1. ファイルを開いて、残す中身を決める(片方を残す、両方を合わせて書き直す)
  2. <<<<<<<・=======・>>>>>>> の印を消す
  3. git add で「このファイルは解決した」と Git に伝え、git commit でマージを終える

衝突のときにやってはいけない3つ

  • 印(«««< など)を消し忘れたままコミットする。ファイルが壊れたまま main に入ります。
  • 中身を読まずに、自分の側だけを残す。相手の直しを黙って消すことになります。
  • 分からないまま作業フォルダを消して作り直す。まず git status で、どのファイルが衝突しているかを確かめます。

衝突は失敗ではありません。2人が同じ場所を直したことを、Git が見落とさずに知らせてくれた、という意味です。衝突を小さく保ついちばんの方法は、枝を短命にして、こまめに main に入れることです。長く生きた枝ほど、main とのずれが大きくなり、衝突も大きくなります。

CHECK 3ここまでの確認

同じファイルの同じ行を、2つのブランチで別々に書き換えてからマージすると何が起きる?

答えと解説

答え: 2. Git がどちらを残すか決められず、衝突(コンフリクト)として人に判断を求める

同じ行に別々の変更があると、Git はどちらが正しいかを決められません。衝突の印(<<<<<<< と ======= と >>>>>>>)を付けて止まり、人が中身を決めてからマージを終えます。

プルリクエストとは(マージの前に見てもらう場)

プルリクエスト(PR)は、GitHub の機能です。GitHub Docs は、プルリクエストを「変更を提案し、話し合い、マージするためのもの」と説明しています。Git 本体のコマンドではないので、手元のターミナルだけでは作れません。

プルリクエストでは、2つのブランチを比べます。取り込ませたい作業の枝を head ブランチ、取り込む先(多くは main)を base ブランチと呼びます。画面には、マージしたら何が変わるかの差分が出て、レビューする人は行ごとにコメントを付けられます。

比べるところ main に直接 push プルリクエストを通す
誰が見るか 自分だけ レビューする人も差分を見る
誤りに気づく時点 main に入ったあと main に入る前
話し合いの記録 残らない 差分にコメントが残る
衝突 push のときに自分で解く プルリクエスト上で分かり、マージの前に解く
自動のテスト 仕組みしだい プルリクエストごとに回して、通ったものだけマージする設定もできる

流れを1本にまとめると、次のようになります。

  1. main から作業ブランチを切る(git switch -c 枝の名前)
  2. 枝の上でコミットを積む
  3. 枝を GitHub に送る(git push)
  4. 枝から main へのプルリクエストを作り、変更の目的を書く
  5. レビューを受けて直し、承認とテストが通ったらマージする
  6. 手元の main を最新にして(git pull)、使い終わった枝を消す

プルリクエストの作り方や画面の操作は、GitHub の画面が変わると手順も変わるので、GitHub Docs を見てください。仕組みとして押さえておきたいのは、「main に入る前に、差分を人とテストに見せる関所がある」という一点です。

CHECK 4ここまでの確認

プルリクエストについて正しいのはどれ?

答えと解説

答え: 1. 作業ブランチの変更を、マージする前に見せて話し合い、確かめてからマージするための場

プルリクエストは GitHub の機能で、head ブランチ(作業の枝)の変更を base ブランチ(多くは main)に入れる前に、差分を見せて確かめる場です。Git 本体のコマンドではありません。

まとめ

Git のブランチは、コミットを指す動かせる目印です。枝を切ってもファイルは複製されないので、気軽に切って、短い間だけ使って、main に戻せます。main を直接触らないのは、チームが「いま動いている版」として使う場所に、確かめていない変更を混ぜないためです。

マージには、目印を進めるだけの早送りと、共通の祖先と2つの枝先を比べてまとめるマージコミットの2つの形があります。同じ箇所を別々に変えていると衝突になり、Git は人に判断を求めます。衝突は、2人が同じ場所を直したことを知らせる合図です。

プルリクエストは、その変更を main に入れる前に、差分を人とテストに見せる場です。この流れが分かると、AWS の設定をコードで書いてチームで直していく段階に進んだときも、同じやり方で変更を扱えます。

参照ソース

SCOREこの記事の確認テスト

0/4問 正解

各章の「ここまでの確認」に答えると、ここに集まります。結果はこの端末のブラウザにだけ残り、サーバには送りません。

FAQよくある質問

ブランチを増やすとリポジトリが重くなりますか?

ほとんど重くなりません。Git のブランチは、あるコミットを指す小さな目印にすぎず、ファイル一式を複製しないからです。重くなるのは、大きなファイルをコミットしたときです。

1人で使うときもブランチを切ったほうがよいですか?

切っておくと便利です。試したい変更を枝で進めて、うまくいかなければ枝ごと捨てられます。main がいつも動く状態のままなので、途中で別の直しが入っても困りません。

マージとリベースはどちらを使えばよいですか?

最初はマージから覚えれば足ります。リベースは枝の履歴を付け替えて一直線にする操作で、使いどころと注意点があります。チームにルールがあればそれに合わせ、無ければマージで始めるのが無難です。

SAME TRACK同じ領域の記事

JSON と YAML の読み方|設定ファイルが「入れ子の名前と値」でできている仕組み
JSON と YAML の読み方|設定ファイルが「入れ子の名前と値」でできている仕組み 段0 土台仕組み
Git とは何か|「上書き保存」と「版を残す」の違いを、最初の3つの動作で理解する
Git とは何か|「上書き保存」と「版を残す」の違いを、最初の3つの動作で理解する 段0 土台とは
AWS CLI とは何か|画面で押すことをコマンドで書く意味と、最初の1行
AWS CLI とは何か|画面で押すことをコマンドで書く意味と、最初の1行 段1 入口とは