Gitでバージョン管理されたプロジェクトを扱うと、必ず .git
というディレクトリがあります。
このディレクトリを使ってGitがバージョン管理をしているらしい、ということはなんとなく知っています。でも、具体的になにが入っていて、どう管理されているんだろう?
このアドベントカレンダーは、そんな疑問からGitを深堀りしていきます。
.git
の中身を見てみる
まずは、Git管理するディレクトリを作成します。
$ mkdir git-study # ディレクトリ作成
$ cd git-study # 作成したディレクトリに移動
$ ls -la # ディレクトリの中身を隠しディレクトリも含めて表示
合計 0
drwxr-xr-x 1 user group 0 12月 1 15:36 .
drwxr-xr-x 1 user group 1292 12月 1 15:36 ..
$
上記はディレクトリを作成しただけなので、まだ何も入っていません。
$ git init # カレントディレクトリをGit管理下に置く
Initialized empty Git repository in /home/user/git-study/.git/
$ ls -la # 再度、ディレクトリの中身を表示する
合計 0
drwxr-xr-x 1 user group 8 12月 1 15:38 .
drwxr-xr-x 1 user group 1292 12月 1 15:36 ..
drwxr-xr-x 1 user group 98 12月 1 15:38 .git
$
カレントディレクトリ直下に .git
ディレクトリが出来ました。
ではいよいよ、 .git
ディレクトリの中を覗いてみます。
$ ls -lRa .git # `.git` ディレクトリの中身を再帰的に表示する
.git:
合計 12
drwxr-xr-x 1 user group 98 12月 1 15:38 .
drwxr-xr-x 1 user group 8 12月 1 15:38 ..
-rw-r--r-- 1 user group 21 12月 1 15:38 HEAD
drwxr-xr-x 1 user group 0 12月 1 15:38 branches
-rw-r--r-- 1 user group 92 12月 1 15:38 config
-rw-r--r-- 1 user group 73 12月 1 15:38 description
drwxr-xr-x 1 user group 506 12月 1 15:38 hooks
drwxr-xr-x 1 user group 14 12月 1 15:38 info
drwxr-xr-x 1 user group 16 12月 1 15:38 objects
drwxr-xr-x 1 user group 18 12月 1 15:38 refs
.git/branches:
合計 0
drwxr-xr-x 1 user group 0 12月 1 15:38 .
drwxr-xr-x 1 user group 98 12月 1 15:38 ..
.git/hooks:
合計 60
drwxr-xr-x 1 user group 506 12月 1 15:38 .
drwxr-xr-x 1 user group 98 12月 1 15:38 ..
-rwxr-xr-x 1 user group 478 12月 1 15:38 applypatch-msg.sample
-rwxr-xr-x 1 user group 896 12月 1 15:38 commit-msg.sample
-rwxr-xr-x 1 user group 4655 12月 1 15:38 fsmonitor-watchman.sample
-rwxr-xr-x 1 user group 189 12月 1 15:38 post-update.sample
-rwxr-xr-x 1 user group 424 12月 1 15:38 pre-applypatch.sample
-rwxr-xr-x 1 user group 1643 12月 1 15:38 pre-commit.sample
-rwxr-xr-x 1 user group 416 12月 1 15:38 pre-merge-commit.sample
-rwxr-xr-x 1 user group 1374 12月 1 15:38 pre-push.sample
-rwxr-xr-x 1 user group 4898 12月 1 15:38 pre-rebase.sample
-rwxr-xr-x 1 user group 544 12月 1 15:38 pre-receive.sample
-rwxr-xr-x 1 user group 1492 12月 1 15:38 prepare-commit-msg.sample
-rwxr-xr-x 1 user group 2783 12月 1 15:38 push-to-checkout.sample
-rwxr-xr-x 1 user group 3650 12月 1 15:38 update.sample
.git/info:
合計 4
drwxr-xr-x 1 user group 14 12月 1 15:38 .
drwxr-xr-x 1 user group 98 12月 1 15:38 ..
-rw-r--r-- 1 user group 240 12月 1 15:38 exclude
.git/objects:
合計 0
drwxr-xr-x 1 user group 16 12月 1 15:38 .
drwxr-xr-x 1 user group 98 12月 1 15:38 ..
drwxr-xr-x 1 user group 0 12月 1 15:38 info
drwxr-xr-x 1 user group 0 12月 1 15:38 pack
.git/objects/info:
合計 0
drwxr-xr-x 1 user group 0 12月 1 15:38 .
drwxr-xr-x 1 user group 16 12月 1 15:38 ..
.git/objects/pack:
合計 0
drwxr-xr-x 1 user group 0 12月 1 15:38 .
drwxr-xr-x 1 user group 16 12月 1 15:38 ..
.git/refs:
合計 0
drwxr-xr-x 1 user group 18 12月 1 15:38 .
drwxr-xr-x 1 user group 98 12月 1 15:38 ..
drwxr-xr-x 1 user group 0 12月 1 15:38 heads
drwxr-xr-x 1 user group 0 12月 1 15:38 tags
.git/refs/heads:
合計 0
drwxr-xr-x 1 user group 0 12月 1 15:38 .
drwxr-xr-x 1 user group 18 12月 1 15:38 ..
.git/refs/tags:
合計 0
drwxr-xr-x 1 user group 0 12月 1 15:38 .
drwxr-xr-x 1 user group 18 12月 1 15:38 ..
$
結構いろいろ入っていてログが長くなりました。
でも、空のディレクトリやフォルダも多いので、現時点で意味がありそうなファイルは下記くらいみたいです。
.git/HEAD
.git/config
.git/description
.git/info/exclude
( .git/hooks
ディレクトリ配下はサンプルっぽいので割愛します)
1. .git/HEAD
.git/HEAD
はファイルなので、試しに cat
してみます。
$ ls -l .git/HEAD # 対象ファイルを確認する
-rw-r--r-- 1 user group 21 12月 1 15:38 .git/HEAD
$ cat .git/HEAD # 対象ファイルの中身を表示する
ref: refs/heads/main
$
ふつうに人間が読める感じの文字列が出てきました。
refs/heads/main
がパスっぽいので、何があるか確認してみます。
(カレントディレクトリが .git
の外なので、 .git
を補ったパスで確認する)
$ ls -l .git/refs/heads/main # 対象ファイルを確認する
ls: '.git/refs/heads/main' にアクセスできません: そのようなファイルやディレクトリはありません
$ ls -l .git/refs/heads # ファイルがなかったので、試しに1つ上のディレクトリを確認する
合計 0
$
refs/heads/main
は存在しないらしい。(refs/head/
まではある)
もしかして、 git init
しただけでコミットが1つもないからHEADもない、みたいな状況なのか?
試しに git status
, git log
をしてみます。
$ git status # ディレクトリのGitステータスを確認する
On branch main
No commits yet
nothing to commit (create/copy files and use "git add" to track)
$ git log # ディレクトリのGitログを確認する
fatal: your current branch 'main' does not have any commits yet
$
どちらもコミットがないって言ってますね。
試しにコミット作ったらどうなるか試したいけど、それは後日に回します。
(初期状態を全部確認しておきたいので)
2. .git/config
.git/config
は名前からして設定ファイルっぽいです。
cat
してみましょう。
$ ls -l .git/config # 対象ファイルを確認する
-rw-r--r-- 1 user group 92 12月 1 14:51 .git/config
$ cat .git/config # 対象ファイルの中身を表示する
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
$
これも人間が読める感じですね。
各設定値の意味を調査したのですが、難しくてよくわからなかったので公式ドキュメントだけ置いておきます。
3. .git/description
これも中身を見てみます。
$ ls -l .git/description # 対象ファイルを確認する
-rw-r--r-- 1 user group 73 12月 1 15:38 .git/description
$ cat .git/description # 対象ファイルの中身を表示する
Unnamed repository; edit this file 'description' to name the repository.
$
関連する公式ドキュメントは下記。
The description file is used only by the GitWeb program, so don’t worry about it.
(Google翻訳)説明ファイルは GitWeb プログラムによってのみ使用されるため、心配する必要はありません。
(心配する必要はないとは……?)
「GitWeb」で調べたら下記ドキュメントが出ました。
If you want to check out what GitWeb would look like for your project, Git comes with a command to fire up a temporary instance if you have a lightweight web server on your system like lighttpd or webrick. On Linux machines, lighttpd is often installed, so you may be able to get it to run by typing git instaweb in your project directory.
(Google翻訳)GitWeb がプロジェクトでどのように機能するかを確認したい場合は、lighttpd や webrick などの軽量 Web サーバーがシステムにある場合に一時的なインスタンスを起動するコマンドが Git に付属しています。Linux マシンでは、lighttpd がインストールされていることが多いため、プロジェクト ディレクトリで git instaweb と入力すると実行できる場合があります。
やってみる。
$ git instaweb # ドキュメントに従ってコマンドを実行してみる
lighttpd not found. Install lighttpd or use --httpd to specify another httpd daemon.
$ apt install lighttpd # lighttpdをインストール
#
# ログ省略
#
$ git instaweb # 再実行
Webページが表示されました。
「Description」欄に、 .git/description
と同じような文字列が表示されています。
「Description」欄をクリックして詳細表示すると、全く同じ文字列が表示されました。
試しに .git/description
を編集してみます。
$ cat .git/description # 変更前確認
Unnamed repository; edit this file 'description' to name the repository.
$ vi .git/description # viで編集
$ cat .git/description # 変更後確認
A project for learning Git.
$ git instaweb # 再起動
Instance already running. Restarting...
GitWeb上でも「Description」欄が更新されました。
ここに表示されるだけの機能のようです。
4. .git/info/exclude
$ ls -l .git/info/exclude # 対象ファイルを確認する
-rw-r--r-- 1 user group 240 12月 1 15:38 .git/info/exclude
$ cat .git/info/exclude # 対象ファイルの中身を表示する
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~
$
コメントアウトされているっぽい文字列が出てきました。
公式ドキュメントを確認してみます。
.git/info/exclude ファイルは .gitignore と同様の働きをしますが、コミットには含まれません。
これは、後日動作確認することにします。
本日はここまで!
参考書籍・参考資料
- git 公式サイト
- エンジニアのためのGitの教科書[上級編] Git内部の仕組みを理解する