\r\n\r\n
映画やテレビでは、ショーは熱狂的な活動として描かれていた。**タイマーがカウントダウンし、それまで雑用をこなしていたオタクな相棒は、ノートパソコンに熱中していた。コードが画面上を飛び交い、最後のエンターキーが「カチッ」と音をたてて押される。タイマーが止まり、世界が元に戻った。しかし、プログラミングはそういうわけにはいきません。デザインドキュメント、UIモデル、コードレビューなどが含まれます。最も重要なのは、特に(私のような)初心者の場合、反復を伴うことです。
ここまでで、あなたはコーディングプロジェクトをソース管理することの価値を確信されたことでしょう。このような試行錯誤をすべてリポジトリにコミットすると、多くのリビジョンを持つ大規模で整頓されていないプロジェクトになってしまいます。あなたが行ったコミットのほとんどは、破損した内容を含んでいます。 では、なぜそれを保存するのでしょうか。git のブランチ機能は、このような厄介なコードを、あなたが知っている有用なものから切り離すのに役立ちます。
今回は、コードを分岐させる意味、方法、「main」ブランチへの更新を管理する方法について見ていきます。
ソースコード管理の紹介で、ターミナルで次のコマンドを使って新しいリポジトリを作成できることを学びました。
git init
このとき、カレントパスの中に".git "という隠しディレクトリが作成されます。表示されない場合は、隠しファイルの表示に関する過去の記事もご覧ください。このディレクトリには、ファイルの改訂履歴を記録するために必要なすべての情報が含まれています。ファイルマネージャーで隠しファイルを表示するように設定すると、.git フォルダーを開いていくつものサブディレクトリーを見ることができます。そのうちのひとつが 'refs' (下図) で、その 'heads' サブディレクトリにプロジェクト内の全ブランチのリストが格納されています。最初は "マスター "と呼ばれる1つしか持っていません。
refsディレクトリはブランチの記録を保持しますが、ブランチそのものを保持するわけではありません。少なくとも、現在使用しているブランチではありません。これらのファイルは作業ディレクトリ(上記の例では "~/Temp/post-programming git-branch")に保存されるので、通常の方法でアクセスすることができます。このようにして、.gitディレクトリの外にある最初のファイル("first-file.txt "と呼ぶ)を作成したのです。前回のgit紹介記事で紹介したtrustyコマンドで確認してみてください。
作業ディレクトリには、私たちがコミットしたファイルと git が自動的に作成したファイル (先ほど入力したコミットメッセージが含まれています) のふたつがあることがわかります。
では、"testing" という名前の新しい git ブランチを作成しましょう。
ギットブランチテスト
上記のコマンドを名前なしで実行すると、すべてのブランチと現在使用中のブランチ (すなわち「チェックアウト済み」ブランチ) の一覧を得ることができます。
ディレクトリ構造を確認すると、".git/refs/heads" には "master" 用と "testing" 用のふたつのファイルがあることがわかると思います。"
それぞれ、そのブランチを構成するコミットのリストです。たとえば、"gitlog" コマンドで "master" ブランチを調べると、そのブランチの各コミットの行があることがわかります。
ブランチを「チェックアウト」するということは、あなたがファイルに加えた変更が、他のブランチの一部ではなく、そのブランチの一部になることを意味します。例えば、次のようなコマンドでテスト用のgitブランチをチェックアウトするとします。
git checkout テスト
そして、最初の行にtext-file.txtを追加し、もちろんその後にコミットします。masterブランチに戻ると、ファイルがまだ空であることがわかります(ターミナルにファイルの内容が表示されるのはcatコマンドです)。
しかし、"testing "ブランチに戻ると、ファイルにはまだ追加されたテキストが残っています。
しかし、ディレクトリにあるのは「first"-file.txt」というファイルだけです。では、この同じファイルの2つの別バージョンはどこにあるのでしょうか?.gitディレクトリでこれらの変更点を説明していますが、あなたが期待するような方法ではありません。
他のバージョン管理システム(Subversionなど)のリポジトリを確認すると、個々のファイルに対して各バージョンのコピーを1つずつ管理していることがわかります。つまり、あるファイルのリポジトリを作成し、その後2つのブランチを作成した場合、リポジトリにはそのファイルの2つの異なるコピーが含まれることになります。事実上、あなたは実際に Subversion でブランチを作成するコマンドとして "svn copy" を使っているのです!一方、gitは "変更 "という概念で動作します。
上の出力は、"trunk"("master "のSVN版)の全内容がコピーされたことを示しています。これは、ファイルマネージャーを見れば確認できます。
.git/objects "ディレクトリには、これらの小さな変更がすべて保存され、それぞれがIDによって追跡されます。例えば、下の画像では、ID風の長い名前のファイルが表示されています。各フォルダーは、16進数で2文字(以下8c、8d)の名前を持つフォルダーに配置されています。
これらのフォルダは、ファイル名とともに、特定の変更のIDを形成します(実際にはSHA1ハッシュ)。git cat file コマンドでその内容を参照することができます。変更された日付によって、"8d "で始まるものが先に表示され、何も表示されないことがわかる。8c "で始まるものには、"testing "ブランチでファイルに追加したテキスト行が含まれています。
重要なのは、gitブランチ(デフォルトの「master」を含む)は、ファイルのコピーを含む個別の「フォルダー」ではないということです。その代わり、時間の経過とともにファイルに加えられた変更のリストである。この方がストレージの面では効率的ですが、結果は同じです。何をしたのか(壊したのか?)gitでは、ブランチはマージするまでそこに留まります。
例えば、いくつかのファイルを含む既存のプロジェクトがあり、それを「テスト」用に拡張し、いくつかの作業を行ったとしましょう。ここで、これらの変更を 'master' ブランチに戻す必要があります。master」ブランチからは、以下のようになります。
ギットマージテスト
競合がなければ、新しいテキストからなる変更が「master」に適用され、結果として「first"-file.txt」は両方のブランチで同じになります。しかし、実際には代替バージョンのファイルが存在することはない。
さて、この枝をどうするかという問題が生じます。枝の処理には、一般的に2つの戦略があります。
ここでは、gitを使用する場合、最初のアプローチが一般的です。また、他の機能(特にマークアップ)により、コードの特定のスナップショットを「安定版」としてマークすることが容易であり、大規模な共同プロジェクトに適しています。しかし、個人で作業する場合は、自分にとって最も理にかなったものを自由に使ってください。gitを使うことの素晴らしい点は、自分の変更点をすべて記録できることで、いつでも戻って何かを見つけることができます。gitのブランチでプロジェクトを整理すれば、この作業はさらに簡単になります。
プロジェクトにおいて、ブランチはどのようにアプローチしていますか?実験して、捨ててしまうのですか?それとも、プロジェクトにおけるあなたの仕事の詳細な履歴を表しているのでしょうか?
git プロジェクトでブランチを処理するための賢い方法があれば、ぜひ以下のコメント欄で教えてください。