プログラミングプロジェクトを構成するのに Git ブランチを使用する方法

映画やテレビでは、プログラミングは必死の作業として描かれています。爆弾のタイマーがカウントダウンし、それまで邪魔だったオタクの相棒がラップトップで必死に作業します。彼女は満足のいくカチャという音とともに最後のリターンキーを押すまで、コードが画面を飛び交います。タイマーが止まり、世界が再び正常になります。しかし、プログラミングはそんなものではありません。設計書、UI モックアップ、コードレビューが含まれます。そして、特に初心者 (私のような) の場合は、試行錯誤が何よりも重要です。

現在、コーディングプロジェクトをソース管理に保存する価値については、すでに確信しているかもしれません。すべての試行錯誤をリポジトリにコミットすると、多くのリビジョンを含む、大きくて整理されていないプロジェクトになります。コミットするほとんどは壊れたもので構成されているので、なぜ保存する必要があるのでしょうか? Git のbranch機能を使用すると、このすべての乱雑なコードを、機能することがわかっているものから遠ざけることができます。

この記事では、コードのブランチ化の意味、その方法、および「メイン」ブランチの更新を管理する方法について説明します。

Git ブランチを作成する

ソース管理の概要から、ターミナルで次のコマンドを使用して新しいリポジトリを作成できることを学びました:

git init

これを実行すると、現在のパスに「.git」という名前の隠しディレクトリが作成されます。これが表示されない場合は、隠しファイルを表示する方法に関する以前の記事を参照してください。このディレクトリには、ファイルのリビジョン履歴を保持するために必要なすべての情報が含まれています。ファイル マネージャーを隠しファイルを表示するように設定したら、.git フォルダーを開いて、多くのサブディレクトリを表示できます。そのうちの 1 つは「refs」(下の画像に示されています) であり、その「heads」サブディレクトリにはプロジェクト内のすべてのブランチの一覧が含まれています。最初は「master」という名前のものが 1 つだけです。

refs ディレクトリはブランチの記録を保持しますが、ブランチ自体ではありません。少なくとも、現在使用しているブランチではありません。これらのファイルは作業ディレクトリ (上記の例では「~/Temp/post-programming-git-branch」) に保持されるため、通常の方法でアクセスできます。まさにそれを行い、作業ディレクトリ (つまり、.git ディレクトリの外側) に最初のファイル (「first-file.txt」という名前) を作成します。git に関する以前の紹介記事の信頼できるコマンドを使用して、これをチェックインします:

作業ディレクトリには 2 つのファイルがあることがわかります。1 つはコミットしたもので、もう 1 つは git によって自動的に作成されたものです (入力したコミット メッセージが含まれています)。

それでは、「testing」という名前の新しい git ブランチを作成してみましょう:

git branch testing

ブランチをチェックアウトして作業する

上記のすべてのコマンドを名前なしで発行して、すべてのブランチのリストを取得し、現在使用しているブランチ (つまり「チェックアウト」されているブランチ) を取得できます:

次に、ディレクトリ構造を調べると、「.git/refs/heads」に「master」と「testing」のそれぞれに 1 つずつ、合計 2 つのファイルがあることがわかります。

これらはそれぞれ、ブランチを構成するコミットのリストです。たとえば、「git log」コマンドで「master」ブランチを調べると、そのブランチに対して行われた各コミットの行が表示されます。

ブランチを「チェックアウト」するプロセスでは、ファイルに加えた変更はそのブランチに含まれますが、他のブランチには含まれません。たとえば、次のコマンドを使用して testing git ブランチをチェックアウトするとします:

git checkout testing

次に、もちろん、first-file.txt にテキストの行を追加して、その後でコミットします。master ブランチに戻ると、ファイルがまだ空白であることがわかります (catコマンドはターミナルにファイルの内容を表示します):

しかし、「testing」ブランチに戻ると、ファイルには追加されたテキストがまだ残っています:

しかし、ディレクトリ自体に表示されるのは常に「first-file.txt」という単一のファイルです。では、同じファイルのこれらの 2 つの代替バージョンはどこにあるのでしょうか? .git ディレクトリはこれらの変更を考慮していますが、期待するような方法ではありません。

Git が物事を保存する方法

Subversion のような他のバージョン管理システムのリポジトリを調べると、個々のファイルごとにリビジョンごとに 1 つのコピーが維持されていることがわかります。つまり、1 つのファイルのリポジトリがあり、2 つのブランチを作成すると、リポジトリにはそのファイルの 2 つの異なるコピーが含まれます。実際、Subversion でブランチを作成するコマンドとして「svn copy」を使用します。一方、git は「変更」の概念に基づいて動作します。

上記の出力は、「trunk」(「master」の SVN バージョン) のすべてのコンテンツがコピーされたことを示しています。ファイル マネージャーで確認すると、これが確認されます:

.git/objects」ディレクトリにはこれらすべての小さな変更が含まれており、それぞれが ID で追跡されます。たとえば、以下の画像では、長い ID スタイルの名前を持つファイルが表示されます。それぞれは、2 つの 16 進文字 (下の8c8d) で名前が付けられたフォルダー内にあります。

これらのフォルダー名とファイル名を組み合わせると、特定の変更の ID (実際には SHA1 ハッシュ) が作成されます。git cat-fileコマンドを使用してその内容を調べることができます。変更された日付に基づくと、「8d」で始まるものが最初に表示され、何も表示されません。「8c」で始まるものには、「testing」ブランチのファイルに追加したテキストの行が含まれています。

重要な点は、git ブランチ (デフォルトの「master」を含む) は、ファイルのコピーを含む個別の「フォルダー」ではないということです。むしろ、それらは時間の経過とともにファイルに加えられた変更のリストです。これは保存の面ではより効率的ですが、結果は同じです。git ブランチで行ったことはすべて (壊した?) マージされるまでそこに残ります。

メイン ブランチへのマージ戦略 (削除するか、削除しないか?)

多数のファイルを含む既存のプロジェクトがあり、それを「testing」に分岐させて、そこで作業を行ったとします。これで、「master」ブランチにそれらの変更を戻したいと考えています。次の「master」ブランチから行うことができます:

git merge testing

競合がなければ、新しいテキストで構成される変更が「master」に適用されます。その結果、「first-file.txt」は両方のブランチで同一になります。それでも、ファイルの代替バージョンは実際にはありませんでした。

ここで、ブランチをどうするかという疑問が生じます。ブランチを扱うための一般的な戦略は 2 つあります。

  1. 1 つは、「testing」のような git ブランチを維持して、遊びます (上記を参照)。いくつかのことを試してみて、うまくいけば変更を「master」にマージします。その後、そのブランチでの作業を終了したり、完全に削除したりできます。つまり、「master」はコードの最も安定したバージョンであり、機能することがわかっているもののみが含まれている必要があります。このアプローチを「機能ブランチ」を使用することと考えることもできます。これは、その目的がコードへの 1 つ (または複数) の特定の追加を改善することであるためです。
  2. 別の方法は、「master」ブランチですべてのメイン作業を行い、その過程でコミットを行うことです。機能に満足したら、その中でバグ修正などを実行するブランチを作成します。これは、リリースで終了するため、より多くの「リリース ブランチ」 (以下を参照) が得られます。また、「master」ブランチは通常、コードの最も不安定なバージョンであることを意味します。

自分に最適な方法を使用してください

最初の方法は、git で作業する場合により一般的です。そのほかの機能 (特にタグ) を使用すると、コードの特定のスナップショットを「安定」として簡単にマークできます。また、大規模な共同プロジェクトにも適しています。ただし、個人的なプロジェクトに取り組む場合は、自分に最も理にかなっていると思われる方法を自由に使用してください。git を使用することの利点は、すべての変更をキャプチャできるため、いつでも戻って何かを見つけることができることです。また、git ブランチを使用してプロジェクトを整理すると、それが少し簡単になります。

プロジェクトでブランチにどのようにアプローチしますか? 実験に使用して、その後はゴミ箱に捨てますか? それとも、プロジェクトでの作業の詳細な履歴を表していますか?

git プロジェクトのブランチを扱う賢い方法があれば、以下のコメントでお知らせください!