.gitディレクトリが私たちから隠しているもの

それで、私はgitに会えるほど幸運でした。 Subversionを使用して後悔し、IDEAまたはTortoiseSVNで必要なことを行う方法を知っていましたが、舞台裏で何が起こっているのかわかりませんでした。 この場合、私はgitにもっと責任を持ってアプローチし、使用前に徹底的に研究することにしました。 これで、計画を実行するためにどのコマンドを使用する必要があるかはわかりましたが、IDEAまたはTortoiseSVNでこれを行う方法はわかりません。
しかし、さらに進んで、.gitディレクトリ自体で何が起こっているのかを調べることにしました。 すべてが非常に面白くてシンプルであることが判明したので、私はこれをあなたと共有することにしました。

これは、git initコマンドの後の.gitの外観です。



これ以上見ると他のファイルやディレクトリが表示されるため、これだけではありません。 たとえば、私の作業プロジェクトでは.gitは次のようになります。



各ファイルの目的については説明しませんが、主なポイントに焦点を当てます。

最も重要な要素は、オブジェクト、参照、HEAD、インデックスです。 それが何で何を食べるのかを理解するために、いくつかのファイル、ディレクトリを作成し、それらをリポジトリに追加します。

オブジェクト


最初、objectsディレクトリには空のサブディレクトリpackとinfoが含まれ、ファイルは含まれません。

作業ディレクトリに「テストファイルバージョン1」の内容を含むtest.txtファイルを作成します。
$ echo 'test file version 1' > test.txt 

このファイルをインデックスに追加します。
 $ git add test.txt 

次に、リポジトリの変更点を見てみましょう。
 $ find .git/objects .git/objects/27/703ec79a98c1d097d5b1cd320befffa376e826 

ファイルがオブジェクトディレクトリに追加されました。 このディレクトリ内のすべてのファイルは、特定のタイプのgitオブジェクトであると言う必要があります。
cat-fileコマンドを使用して、このオブジェクトの内容とタイプを見てみましょう。
 $ git cat-file -p 2770 test file version 1 $ git cat-file -t 2770 blob 

このオブジェクトのタイプはblobです。 これは、Gitのデータの初期表現です。ストレージユニットごとに1つのファイルがあり、名前はオブジェクトのコンテンツとタイトルのSHA1ハッシュとして計算されます。 SHAの最初の2文字はファイルのサブディレクトリを定義し、残りの38文字は名前です。 このオブジェクトは、test.txtファイルの内容のスナップショットを保存するだけです。

次に、インデックスファイルが表示されていることがわかります。 これは、インデックス付きファイルとそれに関連付けられたblobオブジェクトのリストを含むバイナリファイルです。
 $ git ls-files --stage 100644 27703ec79a98c1d097d5b1cd320befffa376e826 0 test.txt 

つまり、インデックスには、後続のコミット中にツリーオブジェクトを作成するために必要なすべての情報が含まれます。 ツリーオブジェクトは、gitの別のタイプのオブジェクトです。 後で彼に会います。
次に、新しいディレクトリと新しい/ new.txtファイルを追加します
 $ mkdir new $ echo "new file" > new/new.txt $ git add . $ find .git/objects -type f .git/objects/27/703ec79a98c1d097d5b1cd320befffa376e826 .git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 

新しいオブジェクトのタイプとその内容を調べてみましょう。
 $ git cat-file -p fa49 new file $ git cat-file -t fa49 blob 

インデックスをもう一度見てください。
 $ git ls-files --stage 100644 fa49b077972391ad58037050f2a75f74e3671e92 0 new/new.txt 100644 27703ec79a98c1d097d5b1cd320befffa376e826 0 test.txt 

そして今、これはすべてコミットされています。
 $ git commit -m "first commit" [master (root-commit) cae1990] first commit 2 files changed, 2 insertions(+), 0 deletions(-) create mode 100644 new/new.txt create mode 100644 test.txt 

現在、リポジトリには5つのオブジェクトが含まれています。
 $ find .git/objects -type f .git/objects/27/703ec79a98c1d097d5b1cd320befffa376e826 .git/objects/49/66bf4e5c88c5f9d149b45bb2f3099644701d93 .git/objects/ca/e19909974ee9e64f5787fe4ee89b9b8fe94ccf .git/objects/eb/85079ce7fd354ffc630f4a8e2991196cb3807f .git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 

さらに3つのファイルが追加されました。 これらのファイルが何であるかを見てみましょう。
 $ git cat-file -t 4966 tree $ git cat-file -p 4966 040000 tree eb85079ce7fd354ffc630f4a8e2991196cb3807f new 100644 blob 27703ec79a98c1d097d5b1cd320befffa376e826 test.txt $ git cat-file -t eb85 tree $ git cat-file -p eb85 100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt 

これは別のタイプのgitオブジェクト-ツリーオブジェクトです。 このタイプのオブジェクトには、別のツリーまたはblobオブジェクトを指す1つ以上のエントリが含まれます。
最後に、最後のタイプのオブジェクトはコミットオブジェクトです。
 $ git cat-file -p cae1 tree 4966bf4e5c88c5f9d149b45bb2f3099644701d93 author Ivan Ivanov <i_ivanov@adam.net> 1335783964 +0300 committer Ivan Ivanov <i_ivanov@adam.net> 1335783964 +0300 first commit 

先ほど述べた最上位ツリー、作成者とコミッターの名前、コミットのメッセージが表示されます。
新しい変更を加えて(test.txtでテキストを「テストファイルバージョン2」に変更します)、コミットします。 ツリー参照に加えて、以前のコミットへのリンクが表示されました。
 $ git cat-file -p b303 tree 42e998096f18d4249dc00ec89eaaadc44a8bf3cb parent cae19909974ee9e64f5787fe4ee89b9b8fe94ccf author Ivan Ivanov <i_ivanov@adam.net> 1335786789 +0300 committer Ivan Ivanov <i_ivanov@adam.net> 1335786789 +0300 second commit 


すべてを適切に配置するには、オブジェクトのグラフを描きます


参照資料


gitでは、リンクはSHA-1ハッシュの値を含む単純な名前のポインターファイルです。 これらのファイルは.git / refs /ディレクトリにあります
 $ find .git/refs .git/refs .git/refs/heads .git/refs/heads/master .git/refs/tags 

マスターブランチは1つしかないため、リンクも1つだけであり、最後のコミットを指します。
最初のコミットを指すリリースブランチを作成しましょう。
 $ git branch release cae1990 $ find .git/refs .git/refs .git/refs/heads .git/refs/heads/master .git/refs/heads/release .git/refs/tags $ cat .git/refs/heads/release cae19909974ee9e64f5787fe4ee89b9b8fe94ccfa 

これは基本的にgitブランチとは何か-特定のコミットへの単純なポインターです。
もっとはっきり見てみましょう


ヘッド


このファイルには、ハッシュではなく現在のブランチへのリンクが含まれています。
 $ cat .git/HEAD ref: refs/heads/master 

別のブランチに切り替えると、このファイルの内容が変更されます。
 $ git co release Switched to branch 'release' $ cat .git/HEAD ref: refs/heads/release 


合計ではなく


また、タグ、削除されたリンク、情報ディレクトリ、および多くの便利な機能もあります。

Source: https://habr.com/ru/post/J143079/


All Articles