ブランチを作成するとき、仮定を確認/修正する必要があります。私がマスターブランチにいる場合、次のことをした後:
git checkout -b some_branch
マスターから新しいブランチを開始したことを意味します。
一方、別のブランチをチェックアウトして、そこにブランチを作成すると:
git checkout some_branch
git checkout -b other_branch
これは、some_branchからコミットされた現在のコードをすべて使用してother_branchを作成したことを意味します。
そして、現在のブランチに関係なく、これが行われる場合:
git branch branch_2 branch_1
次に、branch_1をベースとしてbranch_2が作成されます。これらの仮定は正しいですか?
Gitには、ブランチのbase branchのようなものはありません。代わりに、Gitがブランチのヒントと呼ぶcurrent commitのみがあります。
これを視覚的に理解するには、Gitのcommit graphから(少なくとも一部を)描画することから始めます。コミットが3つしかない小さなリポジトリの例を次に示します。
A <-B <-C <--master
特定のコミットの「本当の名前」は、これらの大きないハッシュID、c0ffeeface1deadbead...
などの1つです。このハッシュIDは、特定のコミットを一意に識別し、実際にはmadeは、そのコミットのcontentsをハッシュすることにより(したがって、「ハッシュID」という名前です)。それらはランダムに見え、覚えることができないため、ここでは単一の大文字を使用します。
Gitがグラフを「見る」方法は、master
などのブランチ名を読み取ることから開始することです。このブランチ名には、C
のようなコミットのハッシュIDが含まれます。 master
points to commit C
と言います。
一方、コミットC
自体には、以前の(またはparent)コミットB
のハッシュIDが含まれています。したがって、C
はB
がmaster
を指すのと同じように、C
を指すと言います。
同様に、コミットB
はA
を指します。 A
はこれまでで初めてのコミットであるため、それを指す場所がどこにもないので、そうではありません。 A
a root commitを呼び出すと、逆方向での作業を停止できます(Git)。
これらの内部矢印は描画するのが面倒で、B
のハッシュIDは実際にはの一部C
であるため、変更することはできません(C
のこの部分を変更しようとすると、新しい、different commit)。したがって、わざわざ描画をやめ、代わりに次のように記述できます。
A--B--C <-- master
ブランチ名から出てくる矢印はnot定数であり、それがtip commitの考え方全体の由来です。
master
に新しいコミットを追加するとします。 Gitが必要とする通常のセットアップをすべて行い(いくつかのファイルを追加または変更し、git add
を使用)、git commit
を実行します。ギット:
新しいコミットD
(新しい一意のハッシュIDを取得)を書き出します。この新しいコミットはC
を指し示しています。
A--B--C <-- master
\
D
次に、changesmaster
(より正確には、保存されたハッシュID)を作成して、作成したばかりの新しいコミットを指すようにします。
A--B--C
\
D <-- master
そしてもちろん、このキンクを図面に保持する理由はもうありません。
A--B--C--D <-- master
Gitでは、これがブランチの成長方法です。
newブランチを作成するには、Gitは単にブランチ名を作成します既存のコミットを指す:
A
\
B
\
C
\
D <-- master
これらのコミットのいずれかを選択して、そこに新しいブランチ名を指定できます。 B
を選択して、newbr
がそこを指すようにします。
A
\
B <-- newbr
\
C
\
D <-- master
これはgit branch newbr <thing-that-finds-B>
で行います。
B
を見つける方法1つの方法は、git log
を実行し、ハッシュIDをカットアンドペーストすることです。しかし、別の方法はブランチ名を使用することです。名前newbr
がB
を指すようになりました。 B
もコミットする別の分岐点を作成する場合:
git branch thirdbr newbr
これにより、Gitはnewbr
を参照するB
を検索し、thirdbr
を指す新しい名前B
を作成します。
A--B <-- newbr, thirdbr
\
C--D <-- master
これが、Gitでブランチを作成するのが非常に速い理由です。ほとんど何もしません。既存のコミットを指すラベルを作成するだけです。
一部のブランチ名が指すコミットは、そのブランチのtip commitと呼ばれます。 1つのコミットが同時に複数のブランチの先端になる可能性があることに注意してください。これはGitの大きな部分の一部です。一部のコミットはmanyブランチですべて同時に実行されます。たとえば、A
のコミット(ルートコミット)はeveryブランチにあります。 (リポジトリには複数のルートコミットを設定することができますが、少し注意が必要です。これについて心配する必要はありません。ここまでに示したコマンドでは実行できません。)
ただし、ブランチラベルの特別なプロパティは、moveです。彼らは動くだけでなく、動く自動的に。
新しいコミットD
を作成したときに、すでにこれを確認しました。 Gitは新しいコミットのIDをmaster
に書き込みました。しかし:Gitはどのようにmaster
を使用することを知っていましたか?それに関して、GitはどのようにしてD
の親をC
にすることを知っていましたか?
もちろん、その時点でブランチは1つしかありませんでしたが、新しいコミットを作成しましょうnow、3つのラベルmaster
、newbr
、およびthirdbr
があります。ただし、最初にgit checkout thirdbr
を実行して、結果を描画します。
A--B <-- newbr, thirdbr (HEAD)
\
C--D <-- master
図面に実際に変更はありませんが、1 ここでWord HEAD
を追加したことを除きます。 HEADは、Gitがどのブランチとコミットがcurrentブランチとコミットであるかを知る方法です。
そこで、通常の一部変更ファイル、git add
、およびgit commit
を実行します。 Gitは新しいコミットを書き出し、その親はB
をコミットするように設定します。 Gitはcurrentブランチがthirdbr
であり、thirdbr
がB
を指しているため、現在のcommitはB
であると認識します。新しいコミットE
を描画しましょう:
E
/
A--B <-- newbr
\
C--D <-- master
残っているのは、現在のブランチnamethirdbr
を移動して、新しいコミットE
を指すようにすることだけです。
E <-- thirdbr (HEAD)
/
A--B <-- newbr
\
C--D <-- master
そして、すべて完了しました。ブランチthirdbr
に新しいコミットを追加しました(これはまだHEADであり、現在のブランチのままですが、現在はE
が現在のコミットです)。
現在のブランチにコミットを追加すると、現在のコミットが何であり、新しいコミットがどこに行くかを示すHEADです。 HEADは通常名前を含みますそれはgit checkout
が行うことです。特定のコミット(通常、既存のブランチのチップコミット)をチェックアウトし、ファイルHEAD
をセットアップしてnameを記憶しますブランチ。 tip commitを覚えているのはブランチ名そのものです。
git checkout -b newnamecommit
の使用は、「指定されたcommitをチェックアウトし、そのブランチを指す新しいブランチ名を作成しますnewnameそのコミットをポイントし、HEADその新しい名前に。」 commit部分を省略すると、デフォルトではHEADが使用されます。 HEAD is(常に)現在のコミットなので、Gitは「チェックアウト」部分をスキップして新しいブランチ名を作成し、HEAD
ファイルに保存します。
1graphでは何も変更されていませんが、Gitはワークツリーとindexを更新する必要があったため、コミット時のファイルを保持できましたB
。