Git講習会に行ってきた.

kunitさん主催による Git のメンテナ Junio さんの Git 講習会.プレゼン資料が USB メモリで廻ってくると言う,今までにないスタイル*1.最後のデモがかなり良かったです.

  • Git のメンテナの Junio C Hamano さん
  • 元々は Linux Kernel の開発に使われていた.
  • Wine, X.org, RoR などで使われている
メモと感想
  • みんなコミットできる
    • 自分のやった仕事の全てコミットして記録できる.
      • それを人がどう見るかは,人間関係によって決まる?
  • --amend で Commit を修正できるが,内部的には新たな Commit オブジェクトが生成されている.
    • GC で削除される対象とはなる.
歴史を作る方法と構造
  • Concepts
    • コマンドのリファレンスを見てもあまり勉強にはならない.
    • 20 のコマンドだけ使えばハッピー
      • ただし概念を理解しておくのがいい.
  • Blog オブジェクト
    • オブジェクトデータベース
    • 各ファイル毎に Blog データがある.
    • 各ファイルに SHA-1 ハッシュキーがある.
  • Tree オブジェクト
    • ディレクトリ構造などを記録する.
    • ファイルパス名に対応する Blog Hash の対応表
    • パス名から SHA-1 ハッシュがわかり,SHA-1 ハッシュから Blog データがわかる.
  • Commit オブジェクト
    • 状態を記録する.
      • Tree オブジェクトへの参照
    • 誰が,どこから,何を変更したのかの情報
  • リポジトリ
    • 上記オブジェクトの集合体
    • 歴史(Building History)も全てを含んだ,オブジェクトの集合体.
  • Building History
    • HEAD
      • 最新 Commit オブジェクトに対するポインタ
    • Checkout
      • Work tree と HEAD Commit の間に Index というバッファエリアがある.
    • Edit & Test
      • 更新部分のみ Index というバッファ部分に書き戻す.
    • Commit
      • Index を使って次の Tree オブジェクトを作成
      • Tree オブジェクトを使って(?),Commit オブジェクトを作成
      • そこに HEAD ポインタを移動させる.
  • なぜ Stage(Index,バッファエリア)があるのか?
    • バージョン管理システムが管理しているファイルの一覧とその内容まで記録したもの.
    • Commit したい情報だけ Stage エリアに入れて,と言う使い方ができる.
    • 小刻みな開発ができる.
  • A Typical Workflow
    • git clone
      • 全てのオブジェクトが入った,リポジトリ全体を自分のローカルに再構築する.
    • git add
      • 「ファイルを追加する」だけではなく,「ファイルの変更を Index オブジェクトに記録する」こと.
      • 「-p」で interactive mode
    • git diff
      • Index オブジェクトと Working Tree の差分が見れる.
    • git diff --cached
      • Index と HEAD との差分が見れる.
    • git diff --color-words
      • 変更部分の単語単位での色分け表示
  • git stash(1)
    • 日本から来たパッチで追加された機能
    • 今までやってきた作業を中断して保存する機能
      • Index エリアに git add で追加した変更をそのまま保存する機能.
    • 保存後は,今までの変更は巻き戻される.
      • ここで Edit&Commit などする.
    • stash apply で保存した変更を Index/HEAD/Working Tree に適用する.
      • Merge される.
      • stash して保存した変更と Index/HEAD/Working Tree をマージする.
  • git stash save --keep-index(1)
    • オブジェクトの状態を保存するのは git stash と同じだが,Index オブジェクトを Working Tree に再構築する.
      • 例えば,Working Tree にデバッグ用コードがあるが,それは git add してないときなどに,Index = これから Commit する状態を再現して,テストが通るかどうか調べるなどで使える.
      • git stash apply で元に戻せる.
  • git rebase --interactive
    • Commit の順序を変更できる
      • git rebase -i HEAD~4
        • 4つ前までの Commit の順序を変更できる.
        • Commit の合体もできる.
        • 新たに Commit Tree を構築できる.
          • 新たな歴史(Building Histroy)を構築できる.
  • Distributed Development
    • 最初は upstream repository から clone する.
    • 開発を続ける
    • upstream と merge する
    • upstream に push する
  • Central Shared Repository
    • merge が強力なのがいいかな.
  • Push することなく共同開発
    • 他の人のから fetch することで,その人の開発内容を取り込んだり,検証したりできる.
      • 問題ななければ,merge し,その内容を pull したりなど.
Archeology
  • gitk の Commit 間の色は意味がない.区別に使うだけ.
  • git bisect
    • どの Commit でプログラムが破壊されたかを調べる.
    • git bisect run ./runscript
      • runscript で壊れているかどうかを調べる.
  • git blame
    • どの行がいつ変更されたかをを調べる
Further References
デモ
% git clone git://XXXX/
% git chechout -b via8236 master # => 新しい名前が付いただけ
# gitk を Update -> 新しい branch ができた.
% vim foo.c; vim foo.h
% git diff
% git commit -a -s -v  # -s = sign-off, -v = diff を確認できる
# gitk を Update -> 新しい commit ができた.実はミスがあった.
% git show                       # => Commit を見ることができる.
% git grep -n -e VIA --and -e '82[56]' # => git が知ってるファイルだけ grep してくれるコマンド
% vim foo.c                      # => 見つけたミスを修正した.
% git commit --amend -a          # => Commit を書き換える.
# 先ほどの Commit Log が表示され,コミットされる.
% git checkout master            # => master へ戻る.先ほどの変更は適用されていない.
% git format-patch master..via8236     # => master から via8326 までの Commit をパッチ形式にして出力する.
  • パッチが来たときに適用する場合.
% git checkout -b spell master
% git am -i patch.diff
  • マージする
% git checkout master
% git merge spell via8236     # => spell と via8236 の branch を master へマージする
% git pull                    # => upstram の更新を取得する.
# Merge conflict が発生
% vim foo.c
% git commit -a
# gitk で更新すると,ツリーが更新される.
    • rename されたファイルへのマージもできた.
質問
  • 1ファイル1オブジェクトで圧縮保存していたのが,同じような部分をまとめて差分化している.
    • Makefile や Copyright など同じものは全て差分として圧縮する.MPEG のような感じ.
    • Pack するのは Commit 時ではなく,GC の時.
  • Remote Repository の 特定の branch を取ってくるには?
    • nocheckout オプションで,あとで checkout かな?
  • Working Tree を複数持つには?
    • (聞き漏らしたorz)
    • local clone を使って複数 clone を持つ
    • new work gear?
  • (聞き漏らした....きっとwalf443さんの質問)
  • プロトコルの特徴は?またおすすめは?
    • Git Protocol を使ってください.
      • Anonymous/Read-only
      • どのオブジェクトがどの状態かなど,きめ細かいネゴシエーションが行われる.
    • もしくは ssh 経由
    • HTTP はピンポンのように,「これある?」「ないや,ちょうだい」的に通信するので,効率が悪い.
  • Shared Repository に GC とか必要?
    • post-update-fook で自動的に GC を走らせるといいのでは.
    • branch を削除するだけの Commit がある.
  • push 時の排他処理は?
    • オブジェクトを push する時には問題ない.
    • HEAD を変更する時に lock をかける.
      • HEAD を付け替えるときには,HEAD は「前のHEADの直系」でなければならない.

*1:資料って配布して良いのかな?欲しい方は個別にご相談ください.