- Git
ブランチとは|Gitの作成・切り替え・マージと正体を実例で解説
結論
Gitのブランチとは、コミットを指す「名前の付いた目印」です。中身はコミットのID(40文字)を書いた41バイトのファイルです。
この記事でわかること
- .git/refs/headsを開いて見た41バイトの実物
- 作成・切り替え・マージ・削除の早見表12行
- エラー原文12件の意味と直し方
ブランチ(main・feature/login)はそれぞれ1つのコミットを指し、HEAD は「いま作業中のブランチ」を指します。コミットは1つ前のコミット(親)を指していて、たどると履歴になります。
flowchart TD
H([HEAD]) --> M[main]
M --> C3((e1e6963))
F[feature/login] --> C4((034b6be))
C3 --> C2((2a699d9))
C4 --> C2
よく使う操作とコマンドは次のとおりです。
| やりたいこと | コマンド | 補足 |
|---|---|---|
| ブランチを作って切り替える | git switch -c 名前 |
git checkout -b 名前 と同じ |
| ブランチを切り替える | git switch 名前 |
git checkout 名前 と同じ |
| 一覧と今いるブランチを見る | git branch |
* が今のブランチ |
| リモートも含めて一覧 | git branch -a |
remotes/origin/… がリモート追跡 |
| 作ったブランチを初めて push | git push -u origin 名前 |
追跡先も同時に設定 |
| 今のブランチに取り込む | git merge 名前 |
先に取り込む側へ切り替える |
| 取り込み済みのブランチを消す | git branch -d 名前 |
未マージなら止まる |
| 作るだけ(切り替えない) | git branch 名前 |
HEAD は動かない |
| 直前のブランチに戻る | git switch - |
2つを行き来するとき |
| 名前を変える | git branch -m 前 後 |
今のブランチなら -m 後 |
| 未マージでも消す | git branch -D 名前 |
reflog から戻せる |
| リモートのブランチを消す | git push origin --delete 名前 |
他の人は fetch --prune |
確認環境:Ubuntu 24.04.4・Git 2.43.0。新しいリポジトリを作り、ブランチの作成・切り替え・マージ・削除・復元、.git の中のファイル、ローカルに作ったリモート(ベアリポジトリ)との push・fetch・追跡、ブランチ名の判定(git check-ref-format)、エラー文を実際に実行して確かめています。コマンドの仕様は Git 公式マニュアル(git-branch・git-switch は 2.56.0 時点)、ブランチの仕組みは Pro Git(日本語版)、Git 3.0 の予定は Git の BreakingChanges、GitHub の画面と既定のブランチ名は GitHub Docs、Subversion のブランチは Subversion の公式の本で確かめました(確認日 2026年10月22日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ブランチとは|Gitの作成・切り替え・マージと正体を実例で解説」
ブランチとは(意味と「ブランチを切る」)
この節では、ブランチという言葉の意味と、Git での役割が分かります。
ブランチ(branch)は英語で「枝」です。 Git では、1本の履歴から枝分かれさせて、別々の作業を並行して進めるための仕組みを指します。新しいブランチを作ることを、木の枝を分けることにたとえて「ブランチを切る」と言います。
| 言葉 | 意味 | Git のコマンド |
|---|---|---|
| ブランチを切る | 今のコミットから新しいブランチを作る | git switch -c 名前 |
| ブランチを切り替える | 作業するブランチを変える | git switch 名前 |
| ブランチをマージする | 別のブランチの変更を今のブランチに取り込む | git merge 名前 |
| ブランチを消す | 目印を消す(コミットはすぐには消えない) | git branch -d 名前 |
| main(master) | 最初からある、本流として使うことが多いブランチ | git init で作られる |
IT 以外では「ブランチ」は銀行や店の「支店」の意味でも使われます。食事の「ブランチ(brunch)」は綴りが違う別の言葉です。この記事のブランチは、Git などのバージョン管理の「枝」です。
ブランチが必要な理由
この節では、ブランチを使うと何がうれしいかが分かります。
1本流を壊さない
作りかけの変更は作業用のブランチに置く。main はいつでも動く状態を保てる。
2並行して進める
機能Aと不具合修正Bを別のブランチで進め、終わった順に取り込める。
3レビューの単位になる
GitHub のプルリクエストは「このブランチを main に取り込みたい」という依頼。
4気軽に試して捨てられる
試しのブランチは消せば終わり。作るのも消すのも一瞬(後の節で実測)。
ブランチの正体は「コミットを指す41バイトのファイル」
この節では、ブランチが .git の中にどう保存されているかを、実際にファイルを開いて確かめます。
新しいリポジトリを作り、2回コミットしました。
$ git init -q -b main
$ git log --oneline
2a699d9 app.txt を追加
2b62bb1 最初のコミット
ブランチは .git/refs/heads/ の下にファイルとして置かれています。main ブランチのファイルを開くと、中身は1行だけでした。
$ ls .git/refs/heads
main
$ cat .git/refs/heads/main
2a699d9267d022e872a9e4d71d78430b8b702936
$ wc -c .git/refs/heads/main
41 .git/refs/heads/main
中身は、最新のコミット(2a699d9)の40文字の ID と改行です。 40 + 改行1 で41バイトになります。od -c で見ると、最後が改行(\n)でした。
$ od -c .git/refs/heads/main | tail -3
0000020 7 2 a 9 e 4 d 7 1 d 7 8 4 3 0 b
0000040 8 b 7 0 2 9 3 6 \n
0000051
その ID が指すのはコミットで、コミットは「親(1つ前のコミット)」の ID を持っています。
$ git cat-file -t main
commit
$ git cat-file -p main
tree c86b34cab9be418aad13d362f6ab237cfe942e2f
parent 2b62bb1a1c6164998fc3d783626e80b948f8f416
author rjc <rjc@example.com> 1792630920 +0900
committer rjc <rjc@example.com> 1792630920 +0900
app.txt を追加
つまり、ブランチは「履歴のコピー」ではなく、「最新のコミットはどれか」を覚えている目印です。履歴は、そのコミットから親をたどって得られます。Pro Git にも、ブランチは「コミットを指す40文字の SHA-1 チェックサムを記録したファイル」で、41バイトのデータだから作成も削除も一瞬で終わる、と書かれています。
ファイルの中身(コミット・ツリー・blob)は共有したまま。違いが出るのは、そのブランチでコミットしてから
ブランチを作ると、同じ ID のファイルが1つ増える
git branch feature/login でブランチを作ると、feature というフォルダの下に login というファイルができました。名前に / を入れると、フォルダとして保存されます。
$ git branch feature/login
$ find .git/refs/heads -type f
.git/refs/heads/feature/login
.git/refs/heads/main
$ cat .git/refs/heads/feature/login
2a699d9267d022e872a9e4d71d78430b8b702936
中身は main と同じ ID です。作った直後のブランチは、main と同じコミットを指しているだけです。
コミットすると、今のブランチのファイルだけが書き換わる
feature/login に切り替えてコミットすると、feature/login のファイルだけが新しいコミットの ID に変わり、main はそのままでした。
$ git switch feature/login
Switched to branch 'feature/login'
$ git log --oneline --all --decorate
034b6be (HEAD -> feature/login) ログイン画面を追加
2a699d9 (main) app.txt を追加
2b62bb1 最初のコミット
$ cat .git/refs/heads/feature/login
034b6be9048cb16180f1f6f390e3007047f219f7
$ cat .git/refs/heads/main
2a699d9267d022e872a9e4d71d78430b8b702936
main に戻って別のコミットをすると、履歴が2つに分かれました。冒頭の図はこの状態です。
$ git switch main
Switched to branch 'main'
$ ls
README.md
app.txt
$ git log --oneline --graph --all --decorate
* e1e6963 (HEAD -> main) app.txt を修正
| * 034b6be (feature/login) ログイン画面を追加
|/
* 2a699d9 app.txt を追加
* 2b62bb1 最初のコミット
main に戻ると、feature/login で足した login.txt は作業フォルダから消えます。切り替えると、作業フォルダのファイルがそのブランチの最新コミットの状態に置き換わるためです。ファイルは feature/login のコミットに残っていて、戻れば現れます。
ファイルを手で書いてもブランチになる
ブランチがただのファイルであることは、ファイルを直接作ると分かります。今のコミットの ID を書いたファイルを置くと、git branch の一覧に現れました。
$ git rev-parse HEAD > .git/refs/heads/handmade
$ git branch
feature/login
handmade
* main
$ git branch -d handmade
Deleted branch handmade (was e1e6963).
これは仕組みを確かめるための操作です。普段はファイルを直接いじらず、git branch(スクリプトなら git update-ref)を使います。Git は書き込み中のロックや、次の節の packed-refs への対応を、コマンドの中で行っているためです。
ファイルが見当たらないとき(packed-refs)
ブランチが多いリポジトリや git gc の後では、refs/heads/ の下にファイルが無いことがあります。ブランチの情報が .git/packed-refs という1つのファイルにまとめられているためです。git pack-refs --all で同じ状態にしました。
$ git pack-refs --all
$ find .git/refs -type f
$ cat .git/packed-refs
# pack-refs with: peeled fully-peeled sorted
034b6be9048cb16180f1f6f390e3007047f219f7 refs/heads/feature/signin
e4c898fa5c45ade112446a9635343997623704f5 refs/heads/main
9d3b685058764f15afc38c1dc8c752e3ff02e2b4 refs/heads/spike/try
bc8cd47197c89e97d819d6ae3cd474d8ea6eae5f refs/remotes/origin/main
$ git branch
feature/signin
* main
spike/try
refs/heads/ は空ですが、git branch は同じ一覧を出しました。保存の形が変わっても、「名前 → コミットの ID」という中身は同じです。スクリプトでブランチの一覧と ID を取るときは、ファイルを読まずに次のコマンドを使います。
$ git for-each-ref --format='%(refname) %(objectname:short)' refs/heads
refs/heads/feature/signin 034b6be
refs/heads/main e4c898f
refs/heads/spike/try 9d3b685
Git の BreakingChanges には、Git 3.0 で新しいリポジトリの参照(ブランチなど)の保存形式を「files」から「reftable」に変える予定が書かれています(2026年10月22日時点で、Git 3.0 の公開日は決まっていません)。reftable 形式のリポジトリでは refs/heads/ にファイルができません。どちらの形式でも、上の git branch・git for-each-ref は使えます。
作るのも消すのも一瞬:1000本で実測
git branch を1000回呼んでブランチを1000本作り、git update-ref --stdin でまとめて消しました。
ファイルの中身(コミット)は増えないので、ブランチの本数でリポジトリが重くなることはほとんどありません。Subversion では、ブランチはリポジトリの中のディレクトリを svn copy で複製して作ります(Subversion の本は、内部では元のツリーを指すだけなので「時間も容量も安い」と説明しています)。
| 項目 | Git | Subversion |
|---|---|---|
| ブランチの実体 | コミットを指す参照(41バイトのファイルなど) | リポジトリ内のディレクトリのコピー |
| 作り方 | git branch 名前(手元だけで完了) |
svn copy 元URL 先URL(サーバーにコミット) |
| 切り替え | git switch 名前(同じフォルダのまま) |
svn switch URL |
| ブランチという概念 | Git が持っている | 持たない。ディレクトリに人が意味を与える |
HEADとは(今いるブランチの目印)
この節では、HEAD が何を指しているか、detached HEAD とは何かが分かります。
HEAD は「今どのブランチで作業しているか」を指す目印です。 中身は .git/HEAD というファイルで、ブランチの名前が書かれています。
$ cat .git/HEAD
ref: refs/heads/main
$ git switch feature/login
Switched to branch 'feature/login'
$ cat .git/HEAD
ref: refs/heads/feature/login
HEAD → ブランチ → コミット と2段で指しています。コミットすると、HEAD が指しているブランチのファイルが新しいコミットの ID に書き換わります。HEAD 自体は書き換わりません。
flowchart TD
H([.git/HEAD]) -->|ref: refs/heads/main| B[.git/refs/heads/main]
B -->|コミットのID| C((最新のコミット))
C -->|parent| P((1つ前のコミット))
| 状態 | .git/HEAD の中身 | コミットすると |
|---|---|---|
| ブランチにいる | ref: refs/heads/main |
main が新しいコミットに進む |
| detached HEAD | コミットの ID(40文字)そのもの | どのブランチも進まない |
| 作ったばかりのリポジトリ | ref: refs/heads/main |
最初のコミットで main ができる |
detached HEAD(ブランチにいない状態)
ブランチではなくコミットを直接指定して切り替えると、HEAD にコミットの ID が直接書かれます。これを detached HEAD(切り離された HEAD)と呼びます。
$ git switch --detach HEAD~1
HEAD is now at bc8cd47 Merge branch 'feature/login'
$ cat .git/HEAD
bc8cd47197c89e97d819d6ae3cd474d8ea6eae5f
$ git branch
* (HEAD detached at bc8cd47)
feature/signin
main
spike/try
過去の状態を見るだけなら問題ありません。この状態でコミットすると、どのブランチもそのコミットを指さないので、別のブランチに切り替えた後に見失いやすくなります。残したいときは git switch -c 新しい名前 でブランチを作ります。戻し方は、関連記事「detached HEADの戻し方|gitのコミットが消えたとき」で扱っています。
ブランチの作成・切り替え・一覧・マージ・削除の早見表
この節では、ブランチの基本操作を1つの表で引けます。各操作の実行結果は、この後の節にあります。
| 操作 | git switch 系(推奨) | git checkout・branch 系 |
|---|---|---|
| 作成だけ | git branch 名前 |
git branch 名前 |
| 作成して切り替え | git switch -c 名前 |
git checkout -b 名前 |
| 起点を指定して作成 | git switch -c 名前 origin/main |
git checkout -b 名前 origin/main |
| 切り替え | git switch 名前 |
git checkout 名前 |
| 直前のブランチへ | git switch - |
git checkout - |
| コミットを見に行く | git switch --detach ID |
git checkout ID |
| 一覧(ローカル) | git branch |
git branch |
| 一覧(リモート含む) | git branch -a |
git branch -a |
| 今のブランチ名だけ | git branch --show-current |
git rev-parse --abbrev-ref HEAD |
| 名前の変更 | git branch -m 前 後 |
git branch -m 前 後 |
| マージ | git merge 名前 |
git merge 名前 |
| 削除(マージ済み) | git branch -d 名前 |
git branch -d 名前 |
| 削除(強制) | git branch -D 名前 |
git branch -D 名前 |
| 既にあれば作り直して切り替え | git switch -C 名前 |
git checkout -B 名前 |
ブランチを使った1つの作業は、次の流れで進みます。
main を最新にする
git switch main のあと git pull。起点が最新でないと、後で取り込むときの差が大きくなります。
作業用のブランチを切る
git switch -c feature/login-form。作業の内容が分かる名前にします。
コミットして push する
初回は git push -u origin feature/login-form。2回目からは git push だけで送れます。
取り込む
GitHub ならプルリクエストを作ってレビュー後にマージ。手元なら git switch main → git merge feature/login-form。
使い終わったブランチを消す
git branch -d feature/login-form と git push origin --delete feature/login-form。
ブランチの作成(git branch・git switch -c)
この節では、ブランチを作る3つの書き方と、その違いが分かります。
| 書き方 | 作る | 切り替える | 主な場面 |
|---|---|---|---|
git branch 名前 |
○ | × | 目印だけ残したい |
git switch -c 名前 |
○ | ○ | 新しい作業を始める |
git checkout -b 名前 |
○ | ○ | Git 2.23 より前からある書き方 |
git branch 名前 は作るだけで、HEAD は動きません。作った直後も * は main のままでした。
$ git branch feature/login
$ git branch
feature/login
* main
$ cat .git/HEAD
ref: refs/heads/main
git switch -c は作成と切り替えを一度に行います。
$ git switch -c fix/typo
Switched to a new branch 'fix/typo'
公式マニュアルには、git switch -c は git branch と git switch を続けて行うのと同じで、切り替えに失敗したときはブランチも作られない、とあります。
起点(どこから切るか)を指定する
名前の後にコミットやブランチを書くと、そこを起点にします。省略すると今の HEAD が起点です。
git switch -c hotfix/login origin/main # リモートの main の最新から切る
git switch -c review/old 2a699d9 # 過去のコミットから切る
git branch release/1.2 v1.2.0 # タグから切る
ブランチの切り替え(git switchとgit checkout)
この節では、切り替えのコマンドと、切り替えたときに作業中の変更がどうなるかが分かります。
ブランチの切り替えは git switch 名前 です。 git checkout 名前 でも同じ結果になります。git switch は Git 2.23 で、git checkout の役割のうち「ブランチを切り替える」部分を分けて作られたコマンドです(ファイルを戻す部分は git restore)。
ブランチ名を打ち間違えたとき
error: pathspec 'nothing' did not match any file(s) known to gitfatal: invalid reference: nothingcheckout はファイル名としても解釈を試すので、エラーが「ファイルが無い」になる。switch はブランチしか扱わない
2つの違いの詳細は、関連記事「git switchとcheckoutの違い|切り替え・作成・restore」で扱っています。
作業中の変更は、ぶつからなければ持ち越される
コミットしていない変更があっても、切り替え先と同じファイルを変えていなければ、変更はそのまま切り替え先に持ち越されます。
$ git switch spike/try
Switched to branch 'spike/try'
M app.txt
$ git status --short
M app.txt
?? memo.txt
M app.txt は「app.txt の変更を持ったまま切り替えた」という表示です。変更はどのブランチのものでもなく、作業フォルダにあるだけです。
ぶつかるときは切り替えが止まる
切り替え先のブランチで同じファイルが変わっていると、手元の変更が上書きされるので、Git は切り替えを止めます。
$ git switch spike/try
error: Your local changes to the following files would be overwritten by checkout:
app.txt
Please commit your changes or stash them before you switch branches.
Aborting
直し方は3つです。
| 直し方 | コマンド | 向いている場面 |
|---|---|---|
| コミットしてから切り替える | git commit -am "作業中" |
変更を今のブランチに残したい |
| 退避してから切り替える | git stash → 切り替え → 戻って git stash pop |
一時的に別のブランチを見たい |
| 変更を持って行く | git switch -m 名前 |
変更を切り替え先で続けたい |
| 変更を捨てる | git switch --discard-changes 名前 |
変更が要らない(元に戻せない) |
git stash で退避すると、切り替えられました。
$ git stash
Saved working directory and index state WIP on main: bc8cd47 Merge branch 'feature/login'
$ git switch spike/try
Switched to branch 'spike/try'
$ git switch main
Switched to branch 'main'
$ git stash pop
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (5539a0a198a8bb299a7f0e8234ddcef8d3284a99)
直前のブランチに戻る(git switch -)
git switch - は直前にいたブランチへ切り替えます。2つのブランチを行き来するときに使います。
$ git switch -
Switched to branch 'spike/try'
$ git switch -
Switched to branch 'main'
ブランチの一覧と確認(git branch -a・-v・--merged)
この節では、ブランチの一覧と、どれがマージ済みかを確かめる方法が分かります。
| 見たいもの | コマンド | 表示 |
|---|---|---|
| ローカルのブランチ | git branch |
* が今のブランチ |
| リモート追跡ブランチも | git branch -a |
remotes/origin/… が増える |
| リモート追跡ブランチだけ | git branch -r |
origin/… |
| 最新コミットも | git branch -v |
ID と件名 |
| 追跡先と差も | git branch -vv |
[origin/main: ahead 1] |
| 今のブランチ名だけ | git branch --show-current |
detached HEAD なら空 |
| マージ済み | git branch --merged |
消してよい候補 |
| 未マージ | git branch --no-merged |
まだ取り込んでいない |
| あるコミットを含む | git branch --contains ID |
修正が入ったブランチ |
マージの後に実行した結果です。
$ git branch -v
feature/login 034b6be ログイン画面を追加
fix/typo 52f7792 README の誤字を修正
* main bc8cd47 Merge branch 'feature/login'
$ git branch --merged
feature/login
fix/typo
* main
$ git branch --show-current
main
$ git branch --contains 034b6be
feature/login
* main
--merged に出たブランチは、変更がすべて main に入っているので、-d で消せます。
ブランチのマージ(fast-forwardとマージコミット)
この節では、ブランチを取り込む git merge の2通りの結果が分かります。
マージは「今いるブランチ」に、指定したブランチの変更を取り込む操作です。 main に取り込むなら、先に main へ切り替えます。
$ git switch main
Switched to branch 'main'
$ git branch --no-merged
feature/login
fix/typo
main が進んでいなければ fast-forward
fix/typo は main から切った後、main 側にコミットが無かったので、main の目印を fix/typo の位置まで進めるだけで済みました。これを fast-forward(早送り)と呼びます。新しいコミットはできません。
$ git merge fix/typo
Updating e1e6963..52f7792
Fast-forward
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
両方が進んでいればマージコミット
feature/login は、分かれた後に main 側も進んでいます。この場合は、2つの親を持つ マージコミット が作られました。
$ git merge --no-edit feature/login
Merge made by the 'ort' strategy.
login.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 login.txt
$ git log --oneline --graph --all --decorate
* bc8cd47 (HEAD -> main) Merge branch 'feature/login'
|\
| * 034b6be (feature/login) ログイン画面を追加
* | 52f7792 (fix/typo) README の誤字を修正
* | e1e6963 app.txt を修正
|/
* 2a699d9 app.txt を追加
* 2b62bb1 最初のコミット
図にすると次のとおりです(fix/typo は fast-forward で main の一部になったので、main の線の上に並びます)。
gitGraph
commit id: "2b62bb1"
commit id: "2a699d9"
branch feature/login
commit id: "034b6be"
checkout main
commit id: "e1e6963"
commit id: "52f7792"
merge feature/login id: "bc8cd47"
同じファイルの同じ場所を両方で変えていると、コンフリクト(衝突)になり、手で直してからコミットします。取り込み方を選ぶ判断は次の表を目安にします。
| やりたいこと | 使うもの | 結果 |
|---|---|---|
| 分かれた履歴をそのまま残して取り込む | git merge |
分岐とマージコミットが残る |
| 履歴を1本の線にしてから取り込む | git rebase main → git merge |
fast-forward で1本の線になる |
| fast-forward できてもマージコミットを残す | git merge --no-ff |
取り込んだ単位が履歴に残る |
| 1つのコミットだけ持ってくる | git cherry-pick ID |
同じ変更の新しいコミットができる |
merge と rebase の使い分けとコンフリクトの直し方は、関連記事「git mergeとrebaseの違い|使い分けとコンフリクト解消」で扱っています。
ブランチの削除と名前の変更(間違えて消したときの戻し方)
この節では、ブランチの消し方と、消してしまったブランチを戻す手順が分かります。
-d はマージ済みのブランチだけを消し、-D はマージしていなくても消します。 公式マニュアルには、-d で消すにはブランチが追跡先(無ければ HEAD)に完全にマージされている必要がある、とあります。
$ git branch -d fix/typo
Deleted branch fix/typo (was 52f7792).
$ git branch -d spike/try
error: the branch 'spike/try' is not fully merged.
If you are sure you want to delete it, run 'git branch -D spike/try'
$ git branch -D spike/try
Deleted branch spike/try (was 972ab06).
消したブランチは reflog から戻せる
ブランチを消しても、消えるのは41バイトの目印だけです。コミットはしばらく残っています。消したときに出た (was 972ab06) の ID か、git reflog に残る HEAD の移動の記録から、同じ位置にブランチを作り直せます。
$ git reflog | head -5
bc8cd47 HEAD@{0}: checkout: moving from spike/try to main
972ab06 HEAD@{1}: commit: 試し
bc8cd47 HEAD@{2}: checkout: moving from main to spike/try
bc8cd47 HEAD@{3}: merge feature/login: Merge made by the 'ort' strategy.
52f7792 HEAD@{4}: merge fix/typo: Fast-forward
$ git branch spike/try HEAD@{1}
HEAD@{1} は「1つ前の HEAD の位置」で、消したブランチの最後のコミット 972ab06 です。ID を直接書いて git branch spike/try 972ab06 としても同じです。
名前を変える
$ git branch -m feature/login feature/signin
$ git branch
feature/signin
* main
spike/try
今いるブランチの名前を変えるときは git branch -m 新しい名前 です。リモートにあるブランチの名前を変える手順と、-d・-D の細かい違いは、関連記事「gitブランチの削除と名前変更|-d・-D・-mとリモートブランチ削除」で扱っています。
消せないブランチ
今いるブランチは消せません。
$ git branch -d main
error: cannot delete branch 'main' used by worktree at '(作業フォルダのパス)'
別のブランチに切り替えてから消します(実際の表示ではパスが出ます。ここでは省いています)。
ブランチ名の付け方(命名ルールと判定結果)
この節では、使えるブランチ名・使えない名前と、よく使われる命名の形が分かります。
Git は git check-ref-format --branch で、名前がブランチに使えるかを判定できます。14個の名前を判定しました。
| ブランチ名 | 判定 | 理由 |
|---|---|---|
feature/login-form |
OK | 英小文字・ハイフン・スラッシュ |
fix/123-null-check |
OK | 数字も使える |
release/1.2 |
OK | 途中のドットは使える |
Feature/Login |
OK | 大文字も使える |
feature/ログイン |
OK | 日本語も使える |
feature/login form |
NG | 空白は使えない |
feature/login. |
NG | ドットで終われない |
feature/login.lock |
NG | .lock で終われない |
foo..bar |
NG | ドット2つが続く |
feature//login |
NG | スラッシュ2つが続く |
feature/~x |
NG | ~ ^ : ? * [ \ は使えない |
feature@{1} |
NG | @{ は使えない |
-feature |
NG | ハイフンで始まれない |
HEAD |
NG | 特別な名前 |
使えない名前で作ろうとすると、次のエラーになります。
$ git branch foo..bar
fatal: 'foo..bar' is not a valid branch name
$ git switch -c 'feature/a b'
fatal: 'feature/a b' is not a valid branch name
$ git branch HEAD
fatal: 'HEAD' is not a valid branch name
同じ名前で「フォルダ」と「ファイル」は両立しない
feature/login があるときに feature というブランチは作れません。feature がフォルダとして使われているので、同じ名前のファイルを置けないためです。
$ git branch feature
fatal: cannot lock ref 'refs/heads/feature': 'refs/heads/feature/login' exists; cannot create 'refs/heads/feature'
よく使われる命名の形
使える名前の中で、チームで揃えておくと迷わない形です。
- 1種類を前に付けるfeature/・fix/・hotfix/・release/・docs/ など
- 2英小文字とハイフンで書くWindows・Mac の標準のファイルシステムは大文字と小文字を区別しない。Feature と feature の混在を避ける
- 3課題の番号を入れる例:fix/123-null-check。課題管理と結び付けやすい
- 4種類だけのブランチを作らないfeature を作ると feature/〜 が作れなくなる(上のエラー)
main・develop・release などをどう組み合わせて運用するか(Git Flow・GitHub Flow など)は、ブランチ戦略と呼ばれます。
| 運用の形 | 主なブランチ | 向いている場面 |
|---|---|---|
| GitHub Flow | main と作業ブランチ | main をいつでもデプロイする |
| Git Flow | main・develop・feature・release・hotfix | 版を決めて定期的に出す |
| GitLab Flow | main と環境ごとのブランチ(production など) | 環境ごとに反映の時期が違う |
それぞれの流れと選び方は、関連記事「Gitのブランチ戦略|Git Flow・GitHub Flowの違いと選び方」で扱っています。
リモートブランチと追跡(origin/main・push -u)
この節では、origin/main が何か、git push -u が何を設定するかが分かります。
ブランチには3種類あります。
| 種類 | 例 | どこにあるか | 動く時 |
|---|---|---|---|
| ローカルブランチ | main |
自分の .git/refs/heads | 自分がコミット・マージしたとき |
| リモート追跡ブランチ | origin/main |
自分の .git/refs/remotes | git fetch・git pull・git push のとき |
| リモートのブランチ | origin にある main |
GitHub などのサーバー | 誰かが push したとき |
ローカルブランチ(main)
自分で切り替えてコミットできる
push するまで他の人には見えない
リモート追跡ブランチ(origin/main)
最後に fetch したときの、サーバーの main の位置の記録
直接コミットはしない。fetch で更新される
flowchart TD
A[ローカルの main] -->|git push| R[(サーバーの main)]
R -->|git fetch| T[origin/main<br>リモート追跡ブランチ]
T -->|git merge・pull| A
push -u で追跡先(upstream)を設定する
ローカルに作ったリモート(origin)へ main を push しました。-u を付けると、「main の追跡先は origin/main」という設定も行われます。
$ git push -u origin main
To ../origin.git
* [new branch] main -> main
branch 'main' set up to track 'origin/main'.
$ find .git/refs -type f | sort
.git/refs/heads/feature/signin
.git/refs/heads/main
.git/refs/heads/spike/try
.git/refs/remotes/origin/main
$ cat .git/refs/remotes/origin/main
bc8cd47197c89e97d819d6ae3cd474d8ea6eae5f
リモート追跡ブランチも、.git/refs/remotes/origin/ の下の41バイトのファイルでした。 追跡の設定は .git/config に書かれます。
$ sed -n '/branch/,$p' .git/config
[branch "main"]
remote = origin
merge = refs/heads/main
[branch "feature/signin"]
remote = origin
merge = refs/heads/feature/signin
追跡先が無いブランチで git push だけを打つと、次のエラーになりました。
$ git push
fatal: The current branch feature/signin has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin feature/signin
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
git push -u origin feature/signin で送ると、一覧に remotes/origin/feature/signin が増えました。
$ git branch -a
* feature/signin
main
spike/try
remotes/origin/feature/signin
remotes/origin/main
ahead・behind で「どれだけずれているか」を見る
main で1つコミットした後の表示です。ahead 1 は「origin/main より1コミット先にある(まだ push していない)」という意味です。
$ git branch -vv
feature/signin 034b6be [origin/feature/signin] ログイン画面を追加
* main e4c898f [origin/main: ahead 1] README を更新
spike/try 9d3b685 spike で app.txt を変更
$ git status -sb
## main...origin/main [ahead 1]
| 表示 | 意味 | 次の操作 |
|---|---|---|
[origin/main] |
差が無い | ― |
[origin/main: ahead 1] |
自分だけにあるコミットが1つ | git push |
[origin/main: behind 2] |
サーバーにだけあるコミットが2つ | git pull |
[origin/main: ahead 1, behind 2] |
両方が進んでいる(実際に出た表示) | git pull で統合してから push |
[origin/feature/x: gone] |
サーバーのブランチが消えた | ローカルも消してよいか確かめる |
他の人が push したブランチで作業する
別の場所で clone すると、ローカルのブランチは main だけで、他は remotes/origin/… として見えます。その名前で git switch すると、追跡つきのローカルブランチが自動で作られました。
$ git branch -a
* main
remotes/origin/HEAD -> origin/main
remotes/origin/feature/signin
remotes/origin/main
$ git switch feature/signin
Switched to a new branch 'feature/signin'
branch 'feature/signin' set up to track 'origin/feature/signin'.
公式マニュアルでは、同じ名前の追跡ブランチが1つのリモートにだけあるとき、git switch 名前 は git switch -c 名前 --track リモート/名前 と同じに扱われます(--guess。既定で有効)。サーバーで新しく作られたブランチが見えないときは、先に git fetch します。
リモートのブランチを消す・消えたものを片付ける
$ git push origin --delete spike/try
To ../origin.git
- [deleted] spike/try
$ git fetch --prune
From ../origin
- [deleted] (none) -> origin/spike/try
サーバーで消されたブランチは、他の人の手元では origin/… として残り続けます。git fetch --prune で片付き、それを追跡していたローカルブランチは -vv で gone と表示されます。fetch と pull の違いは、関連記事「git fetchとpullの違い|図解とpull --rebaseの使い分け」で扱っています。
GitHubでブランチを作る・確かめる
この節では、GitHub の画面でブランチを扱う場所が分かります。
GitHub Docs によると、新しいリポジトリの既定のブランチ名は main です。画面では次の場所で操作します(日本語の表記は GitHub Docs の日本語版のとおりです)。
| やりたいこと | 画面での操作 |
|---|---|
| ブランチを作る | ファイル一覧の上のブランチのドロップダウンで、「ブランチの検索または作成...」に名前を入れ、「ブランチの作成」 |
| 一覧を見る | ブランチのドロップダウンから「View all branches」 |
| ブランチを消す | 一覧で、消すブランチの横のごみ箱アイコン |
| 既定のブランチを変える | リポジトリの Settings から既定のブランチを変更 |
GitHub でブランチを作れるのは、書き込みの権限があるリポジトリだけです。開いているプルリクエストのブランチを消すと、そのプルリクエストは閉じられます。
main と master の違い(既定のブランチ名)
この節では、最初のブランチが main だったり master だったりする理由が分かります。
main と master は名前が違うだけで、機能は同じです。 Git 2.43.0 で -b を付けずに git init すると、master で作られ、次のヒントが出ました。
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
| 場面 | 最初のブランチ名 | 変え方 |
|---|---|---|
Git の git init(Git 2.x) |
master | git config --global init.defaultBranch main |
git init -b main |
main | ― |
| GitHub で作ったリポジトリ | main | 組織・個人の設定で変更できる |
| Git 3.0(予定) | main | BreakingChanges に記載。公開日は未定 |
GitHub の main と手元の master がずれていると、push 先を間違えやすくなります。git config --global init.defaultBranch main を1回設定しておくと、以降の git init が main になります。
ブランチのよくあるエラーと直し方
この節では、ブランチ操作で出るエラーの原文と、原因・直し方を引けます。すべてこの記事の手順で実際に出たものです。
| エラー(原文) | 原因 | 直し方 |
|---|---|---|
fatal: a branch named 'feature/login' already exists |
同じ名前のブランチがある | 別の名前にするか git switch feature/login |
fatal: invalid reference: nothing |
git switch の名前が無い |
git branch -a で名前を確かめる。リモートなら git fetch |
error: pathspec 'nothing' did not match any file(s) known to git |
git checkout の名前が無い |
同上 |
error: Your local changes to the following files would be overwritten by checkout: |
切り替えると手元の変更が上書きされる | commit・stash・switch -m |
error: the branch 'spike/try' is not fully merged. |
未マージのブランチを -d で消そうとした |
マージするか、要らなければ -D |
error: cannot delete branch 'main' used by worktree at '…' |
今いるブランチは消せない | 別のブランチに切り替えてから消す |
fatal: cannot lock ref 'refs/heads/feature': 'refs/heads/feature/login' exists; … |
フォルダとして使われている名前 | feature/〜 の形にする |
fatal: 'foo..bar' is not a valid branch name |
名前に使えない文字・並び | 命名ルールの表を見る |
fatal: a branch is expected, got commit '52f7792' |
git switch にコミット ID を渡した |
git switch --detach 52f7792 |
fatal: The current branch feature/signin has no upstream branch. |
追跡先が無いまま git push |
git push -u origin feature/signin |
error: src refspec nothere does not match any |
push したブランチ名がローカルに無い | git branch で名前を確かめる |
fatal: the requested upstream branch 'origin/nothere' does not exist |
-u で指定した追跡先が無い |
git fetch するか、先に git push -u |
迷ったときの判断表
この節では、よくある状況ごとに、どのコマンドを使うかを引けます。
| 状況 | 使うコマンド |
|---|---|
| 新しい機能を作り始める | git switch main → git pull → git switch -c feature/名前 |
| 作業中に急ぎの修正が入った | git stash → git switch -c hotfix/名前 main |
| 間違えて main でコミットしてしまった(push 前) | git branch feature/名前 → git reset --hard origin/main → git switch feature/名前 |
| 他の人のブランチを手元で動かしたい | git fetch → git switch 名前 |
| どのブランチがマージ済みか知りたい | git branch --merged main |
| 過去のコミットを見るだけ | git switch --detach ID → 見終わったら git switch - |
| ブランチを消してしまった | git reflog で ID を探し git branch 名前 ID |
| サーバーで消えたブランチを片付けたい | git fetch --prune → git branch -vv の gone を -d |
「間違えて main でコミットした」ときの手順は、今のコミットに新しいブランチの目印を残してから、main の目印だけを origin/main まで戻す、という操作です。ブランチがコミットを指す目印だと分かっていると、何が起きるかが読めます。git reset --hard は作業中の変更も消すので、先に git status で変更が無いことを確かめます。手順を実行した結果、間違えたコミットは新しいブランチに移り、main は origin/main と同じ位置に戻りました。
$ git branch feature/oops
$ git reset --hard origin/main
HEAD is now at 00d3d37 c2
$ git switch feature/oops
Switched to branch 'feature/oops'
$ git log --oneline -2 --decorate
3a32814 (HEAD -> feature/oops) 間違えてmainで
00d3d37 (origin/main, main) c2
よくある質問
Q. ブランチとは何ですか? A. Git で、1本の履歴から枝分かれさせて作業を並行して進めるための仕組みです。中身は、最新のコミットの ID を書いた41バイトのファイルです。「ブランチの正体は「コミットを指す41バイトのファイル」」の節で実物を見られます。
Q. 「ブランチを切る」とはどういう意味ですか?
A. 今のコミットから新しいブランチを作ることです。コマンドでは git switch -c 名前(または git checkout -b 名前)です。
Q. ブランチの作成と切り替えを一度に行うには?
A. git switch -c 名前 です。作るだけなら git branch 名前、作った後の切り替えは git switch 名前 です。
Q. 今どのブランチにいるかを確認するには?
A. git branch で * が付いているのが今のブランチです。名前だけ欲しいときは git branch --show-current です。リモートのブランチも見るなら git branch -a です。
Q. git switch と git checkout はどちらを使えばいいですか?
A. ブランチの切り替えだけなら結果は同じです。git switch は Git 2.23 でブランチ操作専用として作られたコマンドで、ファイルを戻す操作と混ざりません。
Q. ブランチとマージの違いは?
A. ブランチは枝分かれさせる目印、マージは分かれた枝の変更を1つに取り込む操作です。取り込む側のブランチに切り替えて git merge 取り込むブランチ を実行します。
Q. ブランチはいくつ作ってもいいですか?
A. 1本41バイトなので、本数で容量が問題になることはほとんどありません(1000本で 41,000 バイト)。使い終わったブランチは git branch --merged で確かめて消すと、一覧が見やすく保てます。
Q. ブランチとフォーク(fork)の違いは? A. ブランチは同じリポジトリの中の枝分かれです。フォークは GitHub などでリポジトリ全体を自分のアカウントに複製することで、書き込み権限が無いリポジトリに変更を提案するときに使います。
Q. ブランチとタグの違いは?
A. どちらもコミットを指す目印ですが、ブランチはコミットするたびに進み、タグは同じコミットを指したまま動きません。タグは .git/refs/tags/ に置かれ、版(v1.2.0 など)の印に使います。
Q. main と master の違いは?
A. 名前だけの違いで、機能は同じです。Git 2.x の git init は master、GitHub の新しいリポジトリは main で作られます。git config --global init.defaultBranch main で揃えられます。
Q. 消したブランチは戻せますか?
A. コミットが消える前なら戻せます。削除時に出た (was 972ab06) の ID か、git reflog で見つけた ID を使って git branch 名前 ID で作り直します。
まとめ
- ブランチはコミットを指す目印。中身は
.git/refs/heads/名前にある、コミット ID 40文字+改行の41バイトのファイル(packed-refs にまとめられることもある)。 - HEAD は今いるブランチを指す。
.git/HEADの中身はref: refs/heads/main。コミットすると HEAD が指すブランチだけが進む。 - 作成と切り替えは
git switch -c、切り替えはgit switch、一覧はgit branch -a、取り込みはgit merge、削除はgit branch -d。 - 作業中の変更は、ぶつからなければ持ち越され、ぶつかると切り替えが止まる。commit・stash・
switch -mで進める。 - 消したブランチは reflog の ID から戻せる。
origin/mainは最後に fetch したときのサーバーの位置の記録。初回の push はgit push -u origin 名前で追跡先も設定する。
参考・出典
確認日はいずれも 2026年10月22日です。
- Pro Git(日本語版)「3.1 Git のブランチ機能 - ブランチとは」:https://git-scm.com/book/ja/v2/Git-のブランチ機能-ブランチとは
- Git 公式マニュアル「git-branch」:https://git-scm.com/docs/git-branch
- Git 公式マニュアル「git-switch」:https://git-scm.com/docs/git-switch
- Git 公式マニュアル「git-check-ref-format」:https://git-scm.com/docs/git-check-ref-format
- Git 公式マニュアル「gitrepository-layout」:https://git-scm.com/docs/gitrepository-layout
- Git「BreakingChanges」(Git 3.0 の予定):https://git-scm.com/docs/BreakingChanges
- Git 2.23.0 リリースノート:https://github.com/git/git/blob/master/Documentation/RelNotes/2.23.0.adoc
- GitHub Docs「リポジトリ内でブランチを作成および削除する」:https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository
- GitHub Docs「About branches」:https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches
- GitHub Docs「デフォルトブランチを変更する」:https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/changing-the-default-branch
- Version Control with Subversion「Using Branches」:https://svnbook.red-bean.com/en/1.7/svn.branchmerge.using.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ブランチとは|Gitの作成・切り替え・マージと正体を実例で解説」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。