前提知識
gitでは、gitリポジトリにコミットを積み上げることで、プロジェクトの各時点での状態及びその変更の軌跡を辿ったり、任意の時点の状態を復元することができる。
コミット同士の前後関係は、コミット自体が「直前のコミット(親コミットと言う)は何か」という情報を持っているため、親コミットを辿っていくことにより知ることができる。
ブランチ
概要
ブランチとは、特定のコミットへの参照を保持するポインタのような領域である。
このように説明すると「ブランチとは枝分かれするための機能である」というイメージと乖離しているかもしれないが、結果的にはこの「特定のコミットへの参照を保持するポインタ」がコミットの軌跡を枝分かれさせることを可能にしている。
説明
では、ブランチとはどのような役割を果たす機能なのか、改めて説明していく。
デフォルトブランチ
git initを実行して空のgitリポジトリを作成した時、まだコミットもブランチもない状態である。
最初のコミットを実行した時、同時にブランチが1つ作成される。
これがデフォルトブランチである。
デフォルトブランチは、通常masterやmainという名前が付けられる。
※デフォルトブランチの名称はgit config
による設定で変更可能である。
この時、デフォルトブランチは最初に作成したコミットへの参照を保持している。
その後、新しいコミットを作成する度に、デフォルトブランチの参照先は自動的に新しいコミットに切り替わっていく。
新しいブランチの作成
ここから下記のgit branch
コマンドでgitリポジトリに新しいブランチを作成することができる。
git branch topic_1
このコマンドでは、topic_1という名前で現在のブランチ(デフォルトブランチ)と同じコミットを参照するブランチが作成される。
この時点ではデフォルトブランチとtopic_1は同じコミットを指しているが、この後、"現在のブランチの切り替え"を行うことによって、コミット履歴を枝分かれさせることができる。
現在のブランチの切り替え
gitリポジトリには、「今どのブランチで作業しているか」という情報を保持する領域がある。
それは"HEAD"と呼ばれており、こちらもポインタのような領域で、今作業しているブランチへの参照を保持している。
"現在のブランチの切り替え"とは、HEADが参照しているブランチを変更することを意味している。
現在のコミット、ブランチ、HEADの状態の確認。
git log --oneline --decorate
下記のgit checkout
コマンドで現在のブランチをtopic_1に切り替えることができる。
git checkout topic_1
これにより、HEAD領域はtopic_1を指した状態となる。この状態でコミットを実行すると、topic_1が参照するコミットが新規コミットへと更新されていく。
本流とは別のコミット履歴の積み上げ
ここから、topic_1が参照するコミットを起点として新しいコミットを実行していくことで、本流とは異なるコミット履歴を積み上げていくことができる。
例えば、現在のブランチがtopic_1の状態で3回コミットを実行したとしよう。
この時、全体のコミット履歴の中で、topic_1ブランチは最新のコミットを、デフォルトブランチはその3回前のコミットを参照している状態である。(コミットは親コミットを参照することでコミットの歴史を作り上げていくことを思い出そう。)
ここで、現在のブランチをデフォルトブランチに切り替える。この時、HEAD領域の参照先はtopic_1からデフォルトブランチに切り替わり、ワーキングディレクトリもデフォルトブランチが参照するコミットの状態に復元される。
すると、デフォルトブランチが今参照しているコミットから、topic_1ブランチとは別の流れ(デフォルトなので立ち位置的には本流)のコミット履歴を積み上げていくことができる。
これで、デフォルトブランチとtopic_1ブランチは最初は同じコミットを参照していたが、そこから別々にコミットを積み上げていくことにより、ある時点からコミット履歴を枝分かれさせるという状態を実現することができた。
ここまで述べたのブランチ機能の要点を下記にまとめておく。
- gitリポジトリでは、コミットが親コミットを参照していることにより、1本のコミット履歴を作ることができる。
- ブランチとは特定のコミットへの参照を保持する領域である。
- HEAD領域が参照するブランチを変更することで、現在作業しているブランチを切り替えることができる。
- 現在のブランチを切り替えると、ワーキングディレクトリにブランチが参照するコミット時点のスナップショットが復元される。
- 現在のブランチが参照するコミットから新規コミットを実行し、独自にコミット履歴を積み上げていくことができる。この時、他のブランチが参照するコミットは変わらない。
- 他のブランチに切り替えた時、既に作成したコミット履歴とは別の流れのコミット履歴を積み上げていくことができる。結果、gitリポジトリ内のコミット履歴を複数本に枝分かれさせることができる。