[Git][備忘録]Git add, commitをした時、中でどんな事が起こっているのか
あらすじ
いまだにファイルがどういうタイミングでリポジトリ、インデックス、ワーキングエリア間を行き来しているのかわからんので色々調べてみることに。
参考資料、サイト
- 実用Git
- http://www8.atwiki.jp/git_jp/pub/Documentation.ja/tutorial-2.html:title
- http://keijinsonyaban.blogspot.jp/2011/05/git.html:title
- http://git-scm.com/book/ja/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88:title
やってみる
まずは、空のREADMEファイルを作ってFirst commit。
$ git init
Initialized empty Git repository in /tmp/repos/.git/
$ touch README
$ git add README
$ git commit -m "first commit"
[master (root-commit) b0d99b3] first commit
0 files changed
create mode 100644 README
$ git log --graph --date-order --all --date=short -C -M --pretty=format:"%h"\ %t\ %ad\ %Cblue%cn%Creset\ %Cgreen%d%Creset\ %s
* b0d99b3 543b9be 2012-08-29 kk_Ataka (HEAD, master) first commit
色々確認
※確認スクリプト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
echo "------------------------" | |
echo "$1 のコミットオブジェクトを調べます。" | |
echo "- git rev-parse $1" | |
git rev-parse $1 | |
echo "------------------------" | |
echo "$1 のコミットオブジェクトの内容を調べます。(特にツリーオブジェクトのSHA1値)" | |
echo "- git cat-file -p $1" | |
git cat-file -p $1 | |
echo "------------------------" | |
echo "$1 のツリーオブジェクトにどんなブロブオブジェクトがぶら下がっているか調べます。" | |
TREE=`git cat-file -p $1 | grep tree | awk '{ print $2 }'` | |
echo "- git ls-tree -r ${TREE}" | |
git ls-tree -r ${TREE} | |
echo "------------------------" | |
echo "インデックスの情報を調べます。変更がaddされていれば、上記と異なる点があるはず。" | |
echo "- git ls-files --stage" | |
git ls-files --stage | |
echo "------------------------" | |
echo "$1 とインデックスのdiffをとってみます。" | |
echo "- git diff --staged $1" | |
git diff --staged $1 | |
echo "------------------------" | |
echo ".git/objectsの中身を見てみます。" | |
echo "- find .git/objects" | |
find .git/objects -type f |
[f:id:kk_Ataka:20120829192353j:image]
- rev-parse コマンドはタグとかブランチとかHEAD、HEAD^^など指定したらそのコミットのSHA1が返ってくる
- 最初のコミットオブジェクトは b0d99b3
- cat-file コマンドでコミットオブジェクトの内容を確認できる
- コミットオブジェクトに関連付いているツリーオブジェクトは 543b9be
- ls-tree コマンドで上のツリーオブジェクトにぶら下がっているツリーオブジェクト、ブロブオブジェクトを確認できる
- 今は直下にREADMEファイルしかないから e69de29
- コミットすると.git/objects/の下に3つファイルが作られる
- SHA1の先頭2桁でディレクトリを作り、その下に残りのSHA1でファイル作成
ゆっくり
READMEを編集してみる。
$ echo "このリポジトリはテスト用です" > README
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: README
#
no changes added to commit (use "git add" and/or "git commit -a")
で、色々確認。まだ作業エリア(ワーキングツリー)内での変更しかしてない(git addしてない)ので特に変わらず。
[f:id:kk_Ataka:20120829192354j:image]
addしたとき
ここでREADMEファイルをadd。
$ git add README
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: README
#
再度、色々確認。
[f:id:kk_Ataka:20120829192355j:image]
リポジトリにコミットされているREADME e69de29 の他にde7e855 というオブジェクトがステージされている。おまけに.git/objectsの下にも。
- addした時点で、gitリポジトリの中に入れ込まれている?
- リセットしても.git/objectsの下からは消えない(ただ、この状態でほったらかしておくとどこからも参照されないからいずれgcされて死ぬ?)
$ git reset HEAD README
Unstaged changes after reset:
M README
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: README
#
no changes added to commit (use "git add" and/or "git commit -a")
$ find .git/objects
.git/objects/de/7e8558a365886d75f9c1ac6861693be19bdc53
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
.git/objects/54/3b9bebdc6bd5c4b22136034a95dd097a57d3dd
.git/objects/b0/d99b34f1e2497a78619de4fde08b62f2d851f7
$ git cat-file -p de7e8558
このリポジトリはテスト用です
commitしたとき
もう一回addして今度はコミット。
$ git add README
$ git commit -m "README追記"
[master 30eab42] README追記
1 file changed, 1 insertion(+)
すごい見づらいけど、.git/objectsの下に2つファイルが増えている。追ってみると今回のコミットオブジェクト 30eab42 と ツリーオブジェクト 9dd7dd4 …の下にさっきaddした時にできていたREADME(de7e855)。
[f:id:kk_Ataka:20120829192357j:image]
まとめ
以上の事から
- addした時、既にリポジトリにファイルは追加されている。また、インデックスの参照先も更新されている
初期状態
[f:id:kk_Ataka:20120829203645p:image:w360]
addした後
[f:id:kk_Ataka:20120829203647p:image:w360]
- commitした時、インデックスがそのまま次のコミットのツリーオブジェクトになる。そのツリーオブジェクトを取りまとめるコミットオブジェクトを作成し、tree情報とparent情報を持たせる
- で、ブランチの参照先を更新してやる
commitした後
[f:id:kk_Ataka:20120829203648p:image:w360]
でいいのかなあ。