Git ブランチは、単にポインターである限り「軽量」です。git は、特定のコミットで「master」、「development」、「trunk」、または「myfeature」を指すだけです。ブランチで新たにコミットすると、ポインターが進みます。この主題に関する優れたリソースであるgit-scm docsのこの図を検討してください。

この図の 'master' ブランチは commit を指していf30ab
ます。「testing」ブランチは commit を指していc2b9e
ます。HEAD
この図の は特別なポインタです。ほとんどの場合、作業ディレクトリの現在チェックアウトされた状態を示すために、別のブランチ (git 用語では「シンボリック参照」) を指しています。たとえば、を発行すると、git checkout f30ab
リポジトリが「切り離された HEAD」状態になります。つまり、ポインターをシンボリック参照「テスト」からコミットに移動しますf30ab
。
例を挙げてみましょう。ローカルで自分自身をセットアップできるはずです。
git init /tmp/test && cd /tmp/test ;# make a repo and cd to it
echo A > A ;# add a file
git add A && git commit -m "first commit" ;# make the first commit
echo B > B ;# add another file
git add B && git commit -m "second commit" ;# commit that one too
git checkout -b development ;# now let's checkout development
echo C > C ;# commit one more file
git add C && git commit -m "third commit" ;# and commit that final one
あなたは今、以下のようなものを手に入れました。私は omnigraffle を持っていないので、有向グラフに固執しています:
* 93e71ee - (HEAD, development) third commit
/
* 6378754 - (master) second commit
* d2b4ba9 - first commit
括弧から推測できるように、'master' は commit を指し6378754
、'development' は commit93e71ee
をHEAD
指し、'development' を指します。私の言葉を鵜呑みにしないでください。自分でポインターを調べます。
$ cat .git/refs/heads/master ;# cat the 'master' pointer
5a744a27e01ae9cddad02531c1005df8244d188b
$ cat .git/refs/heads/development ;# now cat the 'development' one
93e71ee0a538b0e8ac548e3936f696fa4936f8dc
$ cat .git/HEAD ;# note that 'HEAD' points at 'development'
ref: refs/heads/development
$ git symbolic-ref HEAD ;# as we can also show with 'symbolic-ref'
refs/heads/development
ブランチが単なるポインタである場合、ブランチ間の切り替えは簡単です。1 つの特別なケースはHEAD
. マスターをチェックアウトするとどうなるかを考えてみましょう:
$ git checkout master ;# checkout master...
$ cat .git/HEAD ;# where are we now?
ref: refs/heads/master
コミットをチェックアウトするのはどうですか?
$ git checkout d2b4ba9 ;# this will throw some advice
Note: checking out 'd2b4ba9'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
$ cat .git/HEAD ;# 'HEAD' points at a commit
d2b4ba97698d7f528f9ba1e08d978a70651b3b1d
$ git symbolic-ref HEAD ;# and thus isn't a symbolic reference
fatal: ref HEAD is not a symbolic ref
そのアドバイスはどういう意味ですか?「切り離されたHEAD」状態のリポジトリに対してコミットすると、どのブランチからも到達できないコミットが生成されるということです。HEAD
( などのチェックアウト操作から) 変更するgit checkout master
と、それらのコミットは失われます。これは、グラフで見ると簡単です。
echo D > D ;# add another file
git add D && git commit -m "fourth commit" ;# and commit it
グラフを見てみましょう。git コマンドは、以下に表示されるものを生成しないことに注意してください。この例のために、既存の出力を変更しました。
* 93e71ee - (development) third commit
/
* 6378754 - (master) second commit
/
* / 72c1f03 - (HEAD) fourth commit
|/
* d2b4ba9 - first commit
HEAD
まだ離れています。を指してい72c1f03
ます。'master' と 'development' は、予想される場所ですが72c1f03
、どのブランチからも到達できません。それは問題だ。維持したい場合は72c1f03
、ブランチを作成する必要があります。
$ git checkout -b experimental ;# checkout 'experimental' based on '72c1f03'
$ cat .git/HEAD ;# HEAD is once again pointed at a branch
ref: refs/heads/experimental
$ git symbolic-ref HEAD ;# and is a symbolic ref
refs/heads/experimental
そしてグラフ:
* 93e71ee - (development) third commit
/
* 6378754 - (master) second commit
/
* / 72c1f03 - (HEAD, experimental) fourth commit
|/
* d2b4ba9 - first commit
Git は分岐を容易にします。ポインターに関する情報のプッシュとプルは、ファイル セット全体のプッシュとプルよりもはるかに高速です。ブランチのカットには数ミリ秒かかります。とても簡単で、ほとんど間違っているように感じます。その結果、git はより多くの分散型ワークフロー オプションを許可しますが、集中型のものも確実に処理できます。