Git入門:バージョン管理のきほん
ブランチとは何か
この回でやること
ブランチはフォルダのコピーではなく、コミットを指す 41 バイトの付箋にすぎません。この実装モデルを押さえて、ブランチが軽い理由と HEAD との関係を理解しましょう。
- 読む 約 8 分
枝分かれと聞くと、まるごと複製を想像する
「作業を枝分かれさせる」と聞くと、プロジェクト一式がもう 1 セット複製されて、そちらで作業する姿を想像します。だから作るのは重い操作で、たくさん作ると容量を食う、と。
全部違います。ブランチの実体は、コミットの名前が 1 行書かれただけの小さなファイルです。
ターミナル
$ cat .git/refs/heads/main
8f3c1a2b7d4e9c0a5f2b8e6d3c1a4f709b2e5d8c
$ git branch feature/search
$ cat .git/refs/heads/feature/search
8f3c1a2b7d4e9c0a5f2b8e6d3c1a4f709b2e5d8cgit branch で作っても、同じ 41 バイトのファイルが 1 個増えるだけです。1 万ファイルあるプロジェクトでも、作成は一瞬で終わります。
ブランチとは、あるコミットに貼った付箋です。Git から見れば main も feature/search も同じ付箋で、片方が大事に扱われているのはチームがそう決めているからにすぎません。
コミットが動くのではなく、付箋が動く
もう 1 つ HEAD という目印があります。今いる場所を指すもので、ふつうはコミットではなくブランチの名前を指しています。
ターミナル
$ cat .git/HEAD
ref: refs/heads/feature/searchこの状態でコミットすると、順に 3 つのことが起きます。新しいコミットが作られ、親は今のコミットになる。HEAD が指しているブランチ、つまり feature/search が新しいコミットへ進む。そして main は動かない。
プレーンテキスト
8f3c1a2 ── 3e8b2d5 ── 9a1f4c7 ← main
└── 2b8f6a1 ← feature/search ← HEAD枝分かれができました。増えたのはコミット 1 個と、付箋の移動だけです。main に戻ると手元のファイルが元に戻るのは、別のフォルダへ移動しているのではなく、同じフォルダの中身を指し先の内容に入れ替えているからです。
付箋を扱うコマンドは、4 つ覚えれば足ります。
| 打つもの | 何が起きるか |
|---|---|
git branch | 手元の一覧を出す。* が今いるブランチ |
git branch 名前 | 今のコミットに付箋を貼る。移動はしない |
git branch -d 名前 | 付箋をはがす。取り込み済みでないと止まる |
git branch -D 名前 | 止まらずにはがす |
削除は付箋をはがすだけで、コミットは消えません。-d が止まるのは、はがすと誰からも指されなくなるコミットを守るためです。強行したときの出力には消した時点の名前が残るので、戻したくなったらそこから貼り直せます。
作るのも消すのもほぼ無料なので、使い方が変わります。機能ひとつ、不具合ひとつごとに切り、うまくいかなければ消す。危なそうな操作の前に git branch backup と打っておけば、その時点に付箋が残るので、失敗してもそこへ戻るだけで済みます。
作っただけでは、移動していない
いちばん多い失敗がこれです。
ターミナル
$ git branch feature/search
$ git add .
$ git commit -m "検索フォームを実装する"
[main 2b8f6a1] 検索フォームを実装する[main 2b8f6a1] に注目してください。feature/search ではなく main に記録されています。git branch は付箋を貼るだけで、HEAD を動かさないからです。
防ぐには、作成と移動を同時にやる git switch -c feature/search を使います。付箋を貼って、そこへ HEAD を移すところまでやってくれます。
- ブランチの実体はコミットの名前が 1 行だけ書かれたファイル。フォルダのコピーではない
HEADは今いるブランチを指す。コミットすると、HEADが指すブランチだけが進む- 作成も削除もほぼ無料。
git branchは貼るだけで移動しないので、作って移るならgit switch -c