Git コマンドの裏側で何が起こっているのか?〜init, add, commit 編〜
はじめに
普段何気なく使っている Git コマンドの裏で一体何が起こっているのか?
以下の 3 つのコマンドを対象に、簡単にまとめる。
- git init
- git add
- git commit
参考にさせていただいた他の方の記事は、参考に記載した。
👍 git init
git init すると、.git/
フォルダ[1]が作成される。
.git/
フォルダ内には何が入っているのだろうか。
❯ ls -a .git
./
../
HEAD
config
description
hooks/
info/
objects/
refs
HEAD
中身を見ると、以下のようになっている。
ref: refs/heads/master
HEAD が参照しているものが記録されている。
config
中身を見ると、以下のようになっている。
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
description
中身を見ると、以下のようになっている。
Unnamed repository; edit this file 'description' to name the repository.
hooks/
❯ ls .git/hooks
./
../
applypatch-msg.sample*
commit-msg.sample*
fsmonitor-watchman.sample*
post-update.sample*
pre-applypatch.sample*
pre-commit.sample*
pre-merge-commit.sample*
pre-push.sample*
pre-rebase.sample*
pre-receive.sample*
prepare-commit-msg.sample*
push-to-checkout.sample*
update.sample*
何やらサンプルがたくさんある。
1 つ例にとって見てみる。
❯ cat .git/hooks/commit-msg.sample*
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
An example hook script to check the commit log message.
コミットメッセージを確認するための hook スクリプト[2]が書かれている。
info/
❯ ls .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]
# *~
objects/
./
../
info/
pack/
refs/
./
../
heads/
tags/
👍 git add
❯ echo "hello" >> hello.txt
❯ git add hello.txt
新たに、以下のファイル群が作られた。
.git
(略)
├── index
(略)
├── objects
│ ├── ce
│ │ └── 013625030ba8dba906f756967f9e9ca394464a
│ ├── info
│ └── pack
(略)
git cat-file -t
コマンド[3]で見てみると、
ce/013625030ba8dba906f756967f9e9ca394464a
は blob オブジェクト。
❯ git cat-file -t ce01
blob
git cat-file -p
コマンド[4]で見てみると、
先ほど add した hello.txt の中身が格納されている。
❯ git cat-file -p ce01
hello
👍 git commit
❯ git commit -m "add hello.txt"
[master (root-commit) b364b36] add hello.txt
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
ls -l をしてみる。
❯ ls -l .git
total 40
drwxr-xr-x 12 Macユーザ名 staff 384 1 28 14:20 ./
drwxr-xr-x 4 Macユーザ名 staff 128 1 28 14:08 ../
-rw-r--r-- 1 Macユーザ名 staff 14 1 28 14:20 COMMIT_EDITMSG
-rw-r--r-- 1 Macユーザ名 staff 23 1 28 13:23 HEAD
-rw-r--r-- 1 Macユーザ名 staff 137 1 28 13:23 config
-rw-r--r-- 1 Macユーザ名 staff 73 1 28 13:23 description
drwxr-xr-x 15 Macユーザ名 staff 480 1 28 13:23 hooks/
-rw-r--r-- 1 Macユーザ名 staff 137 1 28 14:20 index
drwxr-xr-x 3 Macユーザ名 staff 96 1 28 13:23 info/
drwxr-xr-x 4 Macユーザ名 staff 128 1 28 14:20 logs/
drwxr-xr-x 7 Macユーザ名 staff 224 1 28 14:20 objects/
drwxr-xr-x 4 Macユーザ名 staff 128 1 28 13:23 refs/
新たに、以下のファイル群に変更があったと分かる。
.git
├── COMMIT_EDITMSG
(略)
├── index
(略)
├── objects
│ ├── aa
│ │ └── a96ced2d9a1c8e72c56b253a0e2fe78393feb7
│ ├── b3
│ │ └── 64b367a98fc9261779eb3af098a520c31e124d
(略)
aa/a96ced2d9a1c8e72c56b253a0e2fe78393feb7
は tree オブジェクト。
❯ git cat-file -t aaa9
tree
b3/64b367a98fc9261779eb3af098a520c31e124d
は commit オブジェクト。
❯ git cat-file -t b364
commit
blob オブジェクト、tree オブジェクト、commit オブジェクトとは、それぞれどのようなオブジェクトなのだろうか?
blob オブジェクト
ファイルの中身のみが書かれている。
❯ git cat-file -t ce01
blob
❯ git cat-file -p ce01
hello
tree オブジェクト
blob オブジェクトを参照するための情報を持っている。
❯ git cat-file -t aaa9
tree
❯ git cat-file -p aaa9
100644 blob ce013625030ba8dba906f756967f9e9ca394464a hello.txt
以下が書かれている。
-
100644
... モード(このファイルが持つ権限)。100644 は、通常のファイルであることを意味する。他にも、100755 (実行可能)、120000(シンボリックリンク)などがある(参考 10.2 Gitの内側 - Gitオブジェクト) -
blob
... blob オブジェクト -
ce013625030ba8dba906f756967f9e9ca394464a
... blob オブジェクトのハッシュ -
hello.txt
... ファイル名
commit オブジェクト
commit した tree オブジェクトや、作者、コミットメッセージの情報を持っている。
❯ git cat-file -t b364
commit
❯ git cat-file -p b364
tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7
author GitHubユーザ名 <GitHubメールアドレス> 1706419205 +0900
committer GitHubユーザ名 <GitHubメールアドレス> 1706419205 +0900
add hello.txt
以下が書かれている。
-
tree
... commit した tree オブジェクトのハッシュ -
author
... commit したコードの最初の作者の情報 -
committer
... commit した人の情報 - コミットメッセージ
Discussion