桜、抹茶、白、日記

名古屋市在住のC++使いのcoderの日記だったもの。

GitHubトレーニングチームから学ぶGitの内部構造@名古屋 に参加

VisualStudio 2013でも標準搭載されていますし、そろそろ勉強しようなかと参加。

GitHubレーニングチームから学ぶGitの内部構造@名古屋
http://connpass.com/event/3971/

開会

40名位は来てたかな。
herokuのgitチートシートgithubのステッカーを頂いた。

Git の内部:グラフ、ハッシュ、圧縮 by Matthewさん([twitter:@matthewmccull])&Johnさん([twitter:@johndbritton])

Hashes
    • 集中型のVCSのリビジョン番号は連番
    • GitはSHA-1ハッシュを使う。
    • グローバルな40桁の16進値で管理される。
    • 連番の識別子ではそのコミットにそのコードが含まれている事を保証しない。
    • Q&A
      • Q:グローバルの範囲とは?リポジトリ内か?
      • A:グローバルとは全世界・全宇宙を指す。
Hashed Content - Git commit without Git
    • $ git init projectName
    • すると.gitフォルダに基本的な管理情報が作成される。
    • .git/config はINIファイル形式となっている
    • git add するとHashが1つ生成される。
    • gitが生成するHashコードは一般的なSHA-1によるものなので、様々な言語から生成する事が出来る。
    • git add helloworld.txt
    • .git/object/55/7d????
    • コミットすると、ツリー表示に1つ、コミット用に1つHashを生成する。
    • gitではHashコードの先頭2桁でフォルダを作成する。残りの38桁をファイル名に使う。
    • gitには、高/低レベルの2つのコマンドを提供している。
    • $ echo 'Hellow World' | git hash-object --stdin
      • 5577d????
    • Gitに書き込みつつ、標準出力。
    • $ echo 'Hellow World' | git hash-object -w --stdin
      • 557d????
    • Hash保存されたコードの中身はZlibで圧縮されている。
    • blob 12Hellow World
      • 「blob」はコンテンツの種類を、「12」はコンテンツのデータサイズを表す。
      • gitでは全ての形式はこの方式で保存される。
    • Q&A
      • Q:Gitはファイルシステムが高速に動作する事を前提に実装されているのか?
      • A:GitHubではPBのSSDディスク容量を持っている。
    • $ git rev-parse 92????
    • このコマンドは全てのgitコマンドで実行されてるコマンド。
    • 40桁未満のHash値から唯一のHashコードを補間して返す。
    • $ git rev-parse master
    • $ git rev-parse HEAD

GitHubのエンジニアの方は、GIF形式画像の事を「ギフ」と発音するようだった。

Storage
    • VCSの多くは差分(delta)を保存している。
    • gitは差分を保存しない。
    • 差分方式は履歴が多くなると遅くなる。
    • 無閉路有効グラフ(DAG:Direct Acyclic Graph)
    • コミット毎に全ての内容がコピーされる。
      • 2つのバージョン間で同内容であった場合は、ハードリンクを作成するのみとする
      • zlibはcommitの際に各blobを解凍する
      • zlibはリポジトリの全てを解凍する
    • GroovyのSVNリポジトリ2100MBがgitに変えたら205MBになった。
      • ブランチ間でのコードの変更量が少ないのはよくある。
    • gitのオブジェクト種類
      1. Blob
      2. Tree
      3. Commit
      4. Tag
    • ファイル内容もHash化されているので、ファイルのコピーでも同じファイルである事を検知して容量を節約出来る。
    • Commitにはコミット者名とコミットメッセージを使ってHash値を算出する。
    • Commitには親コミットの情報が含まれる。gitは常にHEADからリンクリスト的に親コミットを辿る。
    • gitは基本的なコンピュータ科学記述を使っている。
      • ポインタ、INIファイル、圧縮、ZIP、Hash
    • vimからブランチを作成するデモ
    • gitでは削除されたオブジェクトは90日間保存される。
    • 間違った操作を行っても必ずリカバリーをする事が出来る。
    • Q&A
      • Q:空のフォルダを管理できないのはなぜ?
      • A:空フォルダに.gitignoreファイルを置けば管理出来るようになる。
Hash Shortcut
    • commitish
      • コミットを探すコマンド
      • 9999のHashに^をつけて9999^とすると一つ前のコミットを表す。
      • 9999のHashに^^をつけて9999^^とすると二つ前のコミットを表す。
      • 9999のHashに~数字をつけて9999~5とすると五つ前のコミットを表す。
      • 2つのHashに..をつけて8888..9999のように2つの間のコミット全てを表す。
      • HEAD^とすると最近コミットの一つ前のコミットを表す。
      • マージされたコミットの場合、9999のHashに^1をつけて9999^1とするとmasterの一つ前のコミットを表す。9999に^2をつけて9999^2とするとマージ元のブランチの一つ前のコミットを表す。
    • treeish
      • tree hashを探すコマンド
The Graph - verification
    • gitはリポジトリ内のデータのHash値の異常を検知すると操作不能になる。
      • バックアップは取りましょう。
    • $ git fsck
    • リモートリポジトリにアクセスする際にはこのコマンドが実行される。
    • $ git verify-pack -v .git/object/pack/FILENAME
    • master^{tree}
      • このコミットのtreeを検索
    • このコマンドによってファイルを取り出す事が出来る。
    • git discribe HASH
      • $ git discribe master
      • 分かりやすいHash名を返すコマンド
    • :/some message
    • この文字列で始まるコミットメッセージを検索
      • REF:FILE
        • $ git show master:zlib.c
        • コミットに変更のあったファイルを検索する。
        • ファイル名についてはコマンドライン補間で確認する事も可能。
      • :0:FILE
        • staging areaのファイルを表示。
        • 0がステージングのインデックスを表す
      • :1:FILE
        • マージ途中の共通の先祖を探す
      • :2:FILE
        • マージ元
      • :3:FILE
        • マージ先
Q&Aタイム
    • blobデータの持ち方
      • GitHubにおいて、OSSのforkなどではblobのコピーは作成されない。
        • →違法ファイルが既にアップロードされているかどうかのチェックに使えてしまう。
      • 但し、privateリポジトリの場合には挙動が異なり、容量は無駄になるがコピーされる。

参加しての感想等

内部データはzlibで圧縮してるとか、差分管理をしていないのは知っていたけどハードリンクを使っているってのは知らなかったな。
まあ内部構造について理解した所で、gitを使いこなせるようになるかどうかは別な話かと思いますけども。


あと勉強会の最後に逐次通訳して下さった方にも拍手したら良かったのでは?と思いました。とても分かりやすく通訳して頂いていたので。