GitのHEAD、作業ツリー、およびインデックスの違いは何ですか?


488

誰かがHEAD、作業ツリー、インデックスの違いをGitで教えてもらえますか?

私が理解していることから、それらはすべて異なるブランチの名前です。私の仮定は正しいですか?


編集する

私はこれを見つけました

1つのgitリポジトリは任意の数のブランチを追跡できますが、作業ツリーはそのうちの1つ(「現在の」または「チェックアウトされた」ブランチ)に関連付けられており、HEADはそのブランチを指します。

これは、HEADと作業ツリーが常に同じであることを意味しますか?


26
あなたの編集に関して:絶対にそうではありません。HEAD現在のブランチの先端でのコミットです。ブランチをチェックアウトした直後、つまり変更されたファイルがない場合、その内容は作業ツリーと一致します。何かを変更するとすぐに一致しなくなります。
Cascabel

6
私はあなたがこれを読む必要があると思います:think-like-a-git.net
AndrzejDuśApr

5
私もStaging Areaそのリストに追加します。何がHEADWorking TreeIndexおよびStaging Area
グリーン

2
@Jefromiの最後の文は次のように明確になります。>何かを変更するとすぐに、作業ツリーはHEADコミットに一致しなくなります
starscream_disco_party

3
将来これを読む場合、これらの答えのいくつかを本当に理解するための最良の方法は、何が起こっているのかを見て感じ、視覚的に概念化することです。これは、これまでgitを学習するための最良のツールです。onlywei.github.io
BKSpurgeon 2017

回答:


579

これらのトピックに関する他のいくつかの優れたリファレンス:

代替テキスト

インデックスをチェックポイントとして使用します

失敗する可能性のある変更を加えようとしているとき—概念的に要求するリファクタリングや変更など、フォロースルーできるかどうか、またはそれが良いアイデアかどうかわからないような方向性を探りたいとき表現タイプ—作業をインデックスにチェックポイントします。これが最後のコミット以降に行った最初の変更である場合は、ローカルリポジトリをチェックポイントとして使用できますが、多くの場合、一連の小さな手順として実装している1つの概念的な変更があります。各ステップの後にチェックポイントを設定したいのですが、テスト済みの機能するコードに戻るまでコミットを保存します。

ノート:

  1. ワークスペースは、(ソース)あなたが見ることのファイルや編集のディレクトリツリーです。

  2. インデックスは、単一、大規模な、バイナリファイルである<baseOfRepo>/.git/index現在のすべてのブランチ内のファイル、その一覧表示し、SHA1のチェックサム、タイムスタンプとファイル名を-それはそれでファイルのコピーと別のディレクトリではありません。

  3. ローカルレポジトリは、隠しディレクトリである(.gitを含む)objectsの圧縮「ブロブ」ファイルとしてリポジトリ内のすべてのファイルのすべてのバージョン(ローカルブランチ及びリモートブランチのコピー)を含むディレクトリ。

上の画像に示されている4つの「ディスク」をrepoファイルの個別のコピーと考えないでください。

代替テキスト

これらは基本的にGitコミットの名前付き参照です。refには、主にタグとヘッドの2つのタイプがあります。

  • タグは、v2.6.29など、履歴の特定のポイントをマークする固定参照です。
  • それどころか、ヘッドは常にプロジェクト開発の現在の位置を反映するように移動されます。

代替テキスト

(注:Timo Huovinen によってコメントされたように、これらの矢印はコミットが指すものではなく、ワークフローの順序であり、基本的1 -> 2 -> 3 -> 41は最初のコミットと4最後の矢印が矢印であることを示しています

これで、プロジェクトで何が起こっているかがわかりました。
しかし、ここで何が起こっているかを知るために、現在、HEADと呼ばれる特別な参照があります。それは2つの主要な目的を果たします:

  • チェックアウト時にファイルを取得するコミットをGitに指示します。
  • コミットするときに新しいコミットをどこに置くかをGitに指示します。

実行git checkout refするHEADと、指定した参照をポイントし、そこからファイルを抽出します。実行するgit commitと、新しいcommitオブジェクトが作成され、currentの子になりますHEAD。通常HEADは頭の1つを指すので、すべてうまくいきます。

代替テキスト


20
gitについて何度も読んだ後、完全に理解することはできませんでした。fワードを使いたいので、本当にイライラしました。しかし、コミュニティのim!ヘッドについて言及しましたが、上の画像では常に1つのヘッドがあり、残りのヘッドはどこにありますか?「通常、HEADはヘッドの1つを指しているので、すべてうまくいきます。」これを説明するようにお願いします、ウル
Necktwi 2014

12
@neckTwi HEADは現在使用しているコミットです(stackoverflow.com/a/964927/6309)。これは通常、「ブランチヘッド」(ブランチによって参照されるコミットの1つで、ブランチの先端を表す)の1つです。しかし、コミットをチェックアウト(および作業)できます。:あなたは(ブランチ)ヘッドの一つされていないコミットをチェックアウトする場合は、「デタッチHEAD」モードになっているstackoverflow.com/a/3965714/6309
VonC

1
@Imray私は同意するが、それは(私は5年前にこれらの写真を見つけた方法ですhades.name/blog/2010/01/28/...
VonC

11
インデックスに関して言えば、@ ashraf-alamが言ったように、「インデックスはステージング領域の別の名前にすぎない」と言えるでしょう。ディスカッションではほとんどの場合、ステージング領域と呼ばれているように感じます。そのため、インデックスと同じものであるとは自動的に関連付けませんでした。
ピート

1
@ピート同意する。キャッシュとインデックスの違いの詳細については、他の回答を参照してくださいstackoverflow.com/a/6718135/6309
VonC

137

HEAD(現在のブランチまたは現在のブランチで最後にコミットされた状態)、インデックス(別名ステージング領域)、および作業ツリー(チェックアウト中のファイルの状態)の違いについては、「1.3 Gitの基本」の「3つの状態」セクションで説明しています。Scott ChaconによるPro Gitブックの章(クリエイティブ・コモンズライセンス)。

この章の画像は次のとおりです。

ローカル操作-作業ディレクトリとステージング領域(インデックス)とgitリポジトリ(ヘッド)

上の画像の「working directory」は「working tree」と同じで、「ステージング領域」はgit「index」の別名であり、HEADは現在チェックアウトされているブランチを指し、その先端は「 gitディレクトリ(リポジトリ)」

git commit -a変更をステージングし、1つのステップでコミットすることに注意してください。


1
「絵は千の言葉に値する」。Jakubに感謝します。そしてリンクに感謝します。
Joyce Babu

5
注:今日よりworking treeも好まれてworking directoryいるようです。github.com/git/git/commit/…を
VonC

3
ステージング領域は「インデックス」と呼ばれる単一のファイルに含まれており、そのインデックスファイルはたまたま.gitディレクトリのルートにあるため、この図は正確ではありません。したがって、リポジトリを.gitディレクトリとして定義した場合、ステージング領域は技術的にはリポジトリ内にあります。3番目の列には、「HEADのルートツリーオブジェクト」というラベルが付けられ、チェックアウトされたファイルがコミットオブジェクトからのものであり、コミットすると新しいツリーがコミットオブジェクトに書き込まれることを示します。両方のコミットオブジェクトはHEADによってポイントされます。
Jazimov 2017

@Jazimovあなたはおそらく正しいですが、彼が書いたように、彼は有名なプロGitの本からその写真を撮り、リンクを提供しました。したがって、画像が改善されるか、さらには間違っている場合は、誰かがその本の著者に伝える必要があります...一般的に、私はそうしたいと思っていますが、正直なところ、私はまだgit初心者であり、まだあなたが言ったことを理解したので、私はその場合間違いなく間違った人です。
Binarus 2017

@Binarus:このような画像を大量に複製する際の危険性は、1人の著者/本が作成した「不実表示」を広めるのに役立つことです。これは、ここではリテラルと機能の解釈のケースだと思います。リテラルの意味では、実際に.gitフォルダーの下のすべてとしてリポジトリを定義すると、インデックスはリポジトリに含まれます。ただし、機能的な意味では、インデックスはGitがリポジトリ内でDAGを維持するのに役立ち、外部の存在であると考えることができます。
ヤジモフ

64

あなたの作業ツリーは、現在作業していることをファイルに実際にあるものです。

HEAD最後にチェックアウトしたブランチまたはコミットへのポインタであり、作成すると新しいコミットの親になります。たとえば、masterブランチ上にいる場合HEADはをポイントしmaster、コミットすると、その新しいコミットはポイントしたリビジョンの子孫にmasterなります。master新しいコミットを指すように更新されます。

指数新しいが用意されてコミットステージング領域です。基本的に、インデックスの内容は新しいコミットに入る内容です(git commit -aそうすると、コミットする前にGitが認識しているファイルへのすべての変更がインデックスに自動的に追加されるため、作業ツリーの現在の内容がコミットされます)。git add作業ツリーのファイルをインデックスに追加または更新します。


説明ブライアンに感謝します。したがって、作業ツリーにはコミットされていないすべての変更が含まれています。git commit -aを使用して変更をコミットすると、その特定の時点で、作業ツリーとインデックスは同じになります。中央リポジトリにプッシュすると、3つすべてが同じになります。私は正しいですか?
Joyce Babu

3
@Vinodかなり。Gitが認識していないファイルを作業ツリーに含めることができ、それらはコミットされませんgit commit -a(それらをで追加する必要がありgit addます)。そのため、作業ツリーには、インデックス、ローカルリポジトリ、またはリモートリポジトリにはありません。
ブライアンキャンベル

2
@Vinod:作業ツリーとインデックスはコミットせずに同じになる可能性があります(git addは作業ツリーからインデックスを更新し、git checkout <path>はインデックスから作業ツリーを更新します)。HEADは最新のコミットを参照するため、コミットするとHEAD、インデックスに一致する新しいコミットに更新されます。プッシュはそれとはあまり関係がありません-ローカルリポジトリのリモートマッチブランチにブランチを作成します。
Cascabel

45

作業ツリー

作業ツリーは、現在作業中のファイルです。

Gitインデックス

  • git "index"は、コミットしたいファイルをgitリポジトリに配置する場所です。

  • インデックスは、キャッシュディレクトリキャッシュ現在のディレクトリキャッシュステージング領域ステージングファイルとも呼ばれます

  • ファイルをgitリポジトリに「コミット」(チェックイン)する前に、まずファイルをgitの「インデックス」に配置する必要があります。

  • インデックスは作業ディレクトリではありません。のようなコマンドを入力するgit statusと、gitは作業ディレクトリ内のどのファイルがgitインデックスに追加されたかを通知します(たとえば、git add filenameコマンドを使用して)。

  • インデックスはgitリポジトリではありません。gitインデックス内のファイルは、git commitコマンドを使用した場合にgitがgitリポジトリにコミットするファイルです。


1
Git 2.5は複数の作業ツリーをもたらすことに注意してください(stackoverflow.com/a/30185564/6309)。+1
VonC、2015年

3
「インデックスがワーキングディレクトリではない」が100%正しいかどうかはわかりません。「インデックスはワーキングディレクトリではありませんが、ワーキングディレクトリ全体と次にコミットする変更が含まれています」である必要があります。証明?gitリポジトリにreset --hard HEAD移動して、インデックス==作業ツリーであることを確認してください。その後:mkdir history && git checkout-index --prefix history/ -a結果は、history/ディレクトリ内の作業ツリー全体の複製です。Ergo gitインデックス> = git作業ディレクトリ
Adam Kurkiewicz

3
インデックスは作業ディレクトリではなく、作業ディレクトリを含める必要はありません。インデックスは、コミットしたい情報を格納するgitリポジトリ内の単なるファイルです。
ブーン

3
「「インデックス」は作業ツリーの内容のスナップショットを保持し、次のコミットの内容として取得されるのはこのスナップショットです。したがって、作業ディレクトリに変更を加えた後、commitコマンドを実行する前に、 (「インデックスに新規または変更されたファイルを追加するには、addコマンドを使用する必要がありますgit-scm.com/docs/git-add
ANTH

3
@AdamKurkiewicz:とステップのecho untracked-data > untracked-file前または後の最初の場合、証明は失敗git reset --HARDgit checkout-indexます。あなたはわかります人跡未踏のファイルがありませんhistoryディレクトリ。インデックスとワークツリーの両方を個別に変更することもできますが、最初にワークツリーに触れずにインデックスを変更することは困難です(を使用する必要がありますgit update-index --index-info)。
トレック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.