第7章 ブランチを切る
ブランチはポインタである
ブランチは「コードの派生線」と説明されることが多いが、Git の実装レベルでは単なる「コミットハッシュを指している名札」である。 名札が貼り変わるだけで、コミット本体は不変のまま履歴に残り続ける。
図の例では、main ブランチは C3 というコミットを、feature ブランチは C4 を指している。
HEAD は「現在チェックアウト中のブランチ」を指す特別なポインタで、いまは feature を向いている。
この状態でコミットを作ると、feature のポインタが新しいコミットへと進み、main は動かない。
.git/refs/heads/main というテキストファイルを覗くと、そこに 40 文字のコミットハッシュがただ 1 行書かれている。
ブランチの実体は「1 行のテキストファイル」と言い切ってしまってもよいくらい軽い存在である。
だから Git ではブランチをいくら切っても、ほぼ容量コストがゼロで済む。
git switch --detach <コミットハッシュ> のように、特定のコミットに直接チェックアウトすると、
HEAD がどのブランチも指していない detached HEAD 状態になる。
この状態でコミットを作ると、そのコミットはどのブランチにも属さず、あとで辿りつけなくなる危険がある。
過去コミットの中身を一時的に確認したいだけなら問題ないが、作業を積み上げたいときは必ず git switch -c <new-branch> で新しいブランチを切ってから動くこと。
ブランチを作る、切り替える
ブランチの一覧と現在地
# ローカルブランチの一覧 (現在地に * が付く)
git branch
# リモート追跡ブランチも含めて表示
git branch -a
新しいブランチを作る
git branch <name> は「作るだけ」で、現在のブランチは切り替わらない。
ほとんどの場合は作ったら即そこに入りたいので、git switch -c (作成 + 切り替えを同時) が実用的である。
# 作成のみ (現在地は変わらない)
git branch feature/add-user-login
# 作成 + 即切り替え (推奨)
git switch -c feature/add-user-login
既存のブランチに切り替える
git switch main
git switch feature/add-user-login
# 直前にいたブランチへ戻る (cd - と同じ感覚)
git switch -
git switch - は地味だが便利で、main と feature/xxx を行ったり来たりするときにブランチ名を打ち直さずに済む。
年季の入ったチュートリアルだと git checkout -b feature/add-user-login という書き方をよく見かける。
checkout は歴史的に「ブランチ切替」と「ファイル復元」を兼ねる万能すぎるコマンドで事故が多かったため、
Git 2.23 以降では switch (ブランチ切替) と restore (ファイル復元) に役割分担された。
いまから覚えるなら switch / restore に寄せるのがおすすめである。
リモートのブランチに切り替える
GitHub 側にすでに存在するブランチに手元で乗り換えたいときは、git switch <name> を打てば Git が賢く origin/<name> を検出して追跡してくれる。
# origin/feature/add-user-login が存在する前提
git fetch
git switch feature/add-user-login
# => Switched to a new branch 'feature/add-user-login'
# branch 'feature/add-user-login' set up to track 'origin/feature/add-user-login'
ローカルのブランチを GitHub に公開する
逆に、手元で作ったブランチをまだ GitHub が知らない状態で、共有可能な場所に送りたいときは、初回 push のときに -u で upstream を紐づける。
これは第 6 章で触れた main の初回 push と同じパターンである。
# 手元で作った feature/add-user-login を GitHub に送る
git push -u origin feature/add-user-login
# 2 回目以降は引数なしで OK
git push
ブランチを切る動機と命名
ブランチを切る理由はだいたい次のどれかに収まる。
- 新機能を試作したい (
mainを汚したくない) - ひとつのバグ修正に集中したい (他の変更と混ざらないように)
- レビューに出す単位を区切りたい (のちの PR のため)
命名に厳密なルールはないが、実務では一貫性を保つための緩やかな慣習が存在する。 読み手 (チームメンバー、将来の自分) がブランチ名だけで「何をしようとしているか」を数秒で把握できる命名が望ましい。
用途別プレフィックス
先頭に用途プレフィックスをつけて、スラッシュで概要と分ける形式が広く使われる。
feature/<概要>: 新機能の追加fix/<概要>: 通常のバグ修正hotfix/<概要>: 本番障害などの緊急修正 (通常main/masterから分岐)chore/<概要>: 依存更新、設定変更、ビルドまわりの雑務refactor/<概要>: 機能変更なしの内部構造整理docs/<概要>: ドキュメントのみの更新
概要部分の書き方
スラッシュ以降の概要部分には、おおむね次のような慣習がある。
- 英小文字 + ハイフン区切り (kebab-case) が主流。アンダースコアや CamelCase もたまに見かけるが少数派
- 動詞 + 目的語の形にすると、ブランチ名だけで「何をするブランチか」が読み取れる
- 短く、かつ具体的に。
newやupdateだけだと情報量ゼロ - Issue / チケット管理を使う組織では、番号を頭に挟むと GitHub や Redmine との相互リンクが自動で張られる
- 複数人が同時並行で作業するプロジェクトでは、作業者名をスラッシュで挟む流儀もある (例:
feature/space/add-user-login)。誰の作業か一目で分かり、放置されたブランチの担当者を突き止めるのも楽になる
良い例と避けたい例
以下の 2 つを見比べると、命名の差がそのまま「あとで見返したときの読みやすさ」の差になっているのが分かる。
良い例:
feature/add-user-login— 動詞 + 対象で何を作るかが一目で分かるfeature/space/add-user-login— 作業者名を挟んで担当が明確feature/123-add-user-login— Issue #123 に紐付く新機能として追跡できるfix/password-reset-email— どの機能のバグ修正かが明確hotfix/auth-bypass-2026-04— 緊急性・対象・発生時期が揃っているchore/update-react-18— 依存更新の具体的な内容が書かれているrefactor/extract-payment-service— リファクタリングの意図が伝わる
避けたい例:
feature/new— 何が新しいのか読み取れないfeature/hoge/feature/wip— 意味を持たないプレースホルダで残りがちfix_bug— プレフィックス無し、どのバグか不明、区切りもアンダースコアで統一感が崩れるtaro-wip— 個人名「だけ」で完了条件が曖昧 (feature/taro/add-user-loginのように用途を足せば問題ない)feature/ログイン機能— 日本語はシェル・CI・ツールによって文字化けやエンコード問題の原因になる
本教材ではこれ以降、サンプルのブランチ名に feature/add-user-login を使う。
「動詞 + 目的語 + kebab-case」でブランチ名に情報を載せる流儀に慣れておくと、実務で命名に迷う回数が減る。
main と master — 2 種類の「本流」ブランチ
Git でデフォルトブランチに相当するものには、プロジェクトによって main と master の 2 つの名前が登場する。
最初に触ったリポジトリで見かけた方と違う名前に出くわして戸惑うことは少なくないので、両者の関係を整理しておく。
歴史的な経緯
Git は長らく、新規リポジトリの最初のブランチを master という名前で作る仕様だった。
2020 年に GitHub が新規リポジトリのデフォルトを main に変更したのを皮切りに、GitLab や Bitbucket など主要ホスティングサービスも追随し、
Git 本体もデフォルトブランチ名の設定 (init.defaultBranch) 未指定時に警告を出すようになった。
その結果、新規プロジェクトは main、歴史あるプロジェクトは master のまま、という現状の二分が生まれている。
技術的な違いは「無い」
両者は単にブランチ名が違うだけで、機能・挙動・操作方法にはいっさい差がない。
git switch main と git switch master は「そのリポジトリにどちらの名前のブランチが存在しているか」だけの違いである。
既存リポジトリを master から main に揃えたい場合
チームの合意が取れているなら、改名して統一するのも手軽にできる。
# ローカルで改名
git branch -m master main
# 新しい名前で GitHub に push して upstream を張り直す
git push -u origin main
# GitHub 上のリポジトリ設定で Default branch を main に変更
# (Settings → Branches → Default branch)
# 旧 master を削除
git push origin --delete master
個人開発なら好きな方を選べばよい。既存プロジェクトに参加する場合は、そこで採用されている名前に合わせる。
本教材では第 2 章で init.defaultBranch = main に揃える想定で進めているが、手元のリポジトリが master だった場合は読み替えてほしい。
統合ブランチ (main と develop) の使い分け
複数人で開発していると、全員が main をそのまま作業場にすると不安定になりがちである。
そこで多くのプロジェクトでは、「完成した機能を積み上げていく統合用のブランチ」を別に用意する運用が採られる。それが develop ブランチである。
典型的な役割分担
main: 常にリリース可能な状態を保つ本番用ブランチ。未完成の機能は入れないdevelop: 次のリリースに向けた統合の場。feature ブランチの取り込み先feature/xxx:developから分岐する個別の作業ブランチ
流れとしては feature/xxx → develop (統合) → main (リリースのタイミングで) の順にマージしていく。
これにより main は「いつ見ても動く状態」が維持され、開発途中の未完成機能が混ざらない。
この 3 層 (さらに release/* や hotfix/* を足した 5 層) を定式化したものに Git-flow という有名なパターンがある。
一方、GitHub 自身が薦める GitHub Flow は main + feature/* の 2 層だけでシンプル。
プロジェクトの規模・リリースサイクル・チーム人数によって向き不向きが分かれるので、これもチームの流儀に合わせる。
ブランチの改名
切ったあとに命名を誤ったと気づいたときは、改名で対処できる。
# 現在いるブランチを改名
git branch -m feature/new-name
# 別ブランチを改名 (現在地は動かない)
git branch -m feature/old-name feature/new-name
既に GitHub に push 済みのブランチを改名した場合、リモート側には旧名のブランチが残り続ける。
改名後に git push -u origin feature/new-name で新名を push し、
古い方は git push origin --delete feature/old-name で明示的に消す必要がある。
ブランチ同士を比較する
マージや PR を出す前に、対象ブランチに「main より何が増えたか」を眺めておくと安心である。A..B という書き方で、
A にはないが B にはあるコミットを抽出できる。
# main にないが feature/add-user-login にはあるコミット一覧
git log main..feature/add-user-login --oneline
# 上と同じ範囲のコード差分 (patch)
git diff main..feature/add-user-login
# ファイル名だけ一覧したい場合
git diff main..feature/add-user-login --stat
逆向きの feature/add-user-login..main にすれば、「feature 側から取り残されている main の新着コミット」が見える。
マージ前に「自分のブランチが遅れていないか」の確認に使える。
ブランチの削除
作業が終わって本流 (たいていは main) にマージしたら、役目を終えたブランチは消してしまってよい。
マージ前に消そうとすると Git は警告してくれる。
# マージ済みブランチを削除 (安全)
git branch -d feature/add-user-login
# 未マージでも強制削除 (使いどころは慎重に)
git branch -D feature/add-user-login
ローカルを削除しても、GitHub 側のブランチは残ったまま。GitHub 側も消したいなら git push origin --delete feature/add-user-login を別途実行する。
まとめ
- ブランチは「コミットを指す名札」。切っても容量はほぼかからない
HEADは現在チェックアウト中のブランチを指す。コミットするとその先に進む- 作成 + 切替は
git switch -c <name>、切替のみはgit switch <name>、直前に戻るならgit switch - - ローカル作成ブランチの初回公開は
git push -u origin <name> - 命名は
feature/xxx/fix/xxxなどの用途別プレフィックスが慣習、改名はgit branch -m mainとmasterは名前が違うだけで挙動は同じ。新規はmain、既存のmasterもそのままでよいmain+develop+feature/*の 3 層は Git-flow、main+feature/*だけで済ませるのが GitHub Flow。チームの流儀に合わせる- マージ前の確認には
git log main..feature/xxx --oneline/git diff main..feature/xxx - 役目を終えたブランチは
git branch -dで気軽に消す。detached HEAD 中は新しいブランチを切ってから作業