Git add, commitをした時、中でどんな事が起こっているのか

[Git][備忘録]Git add, commitをした時、中でどんな事が起こっているのか

あらすじ

いまだにファイルがどういうタイミングでリポジトリ、インデックス、ワーキングエリア間を行き来しているのかわからんので色々調べてみることに。

参考資料、サイト

やってみる

まずは、空の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

色々確認

※確認スクリプト

[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]

でいいのかなあ。

関連記事(この記事の初版より古い記事はリンクがグレーで表示されます)

  1. 2012/12/12 [Git] [Subversion] git-svnインストールからgit svn dcommit完了までの手順
  2. 2012/04/24 [Git] [Windows] Pro Gitと入門Gitと入門gitと実用GitでGitの復習 無名ブランチ(detached HEAD)からの復活編
  3. 2012/04/23 [Git] [Windows] Pro Gitと入門Gitと入門gitと実用GitとGit道場#1でGitの復習 rebase編
  4. 2012/04/22 [Git] [イベント] Git道場#1に参加しました と、pullとpull --rebase備忘録 #gitdojo
  5. 2012/04/10 [Git] [Windows] Pro Gitと入門Gitと入門gitでGitの復習 HEADのキャレットとかチルダとか補講編
  6. 2012/03/15 [Git] [Windows] Pro Gitと入門gitでGitの復習 マージ編
  7. 2012/03/11 [Git] [Windows] Pro Gitと入門gitでGitの復習 ブランチ編
  8. 2012/03/05 [Git] [Windows] Pro Gitと入門gitでGitの復習 基本操作編
  9. 2012/02/23 [Jenkins] [Git] GitプロジェクトをコミットしたタイミングでJenkinsにビルドをしてもらいたい!
  10. 2013/12/14 [Git] Gitの.git/objectsの中身を追ってみる
  11. 2013/09/07 [Ruby] [Git] [Jekyll] Jekyllバージョンアップの際に思いのほか手こずった話 てっく煮さん製プラグインの更新に追従したい編
  12. 2013/09/05 [Git] [Subversion] Subversionのproxy設定でいつもハマるやつ
  13. 2013/08/07 [Ruby] [Jekyll] [Git] Jekyllバージョンアップの際に思いのほか手こずった話 Jekyll Bootstrapの更新に追従したい編
  14. 2013/05/21 [Jekyll] [Git] GitHub PagesでJekyllプラグインを使えるようにするには…
  15. 2011/01/30 [JavaScript] [Git] [イベント] BPStudy#41に参加しました