世界を動かす技術を、日本語で。

職人手作りのGitリポジトリ

概要

gitリポジトリ を手作業で作成する方法の解説 gitの内部構造 や「plumbing」と呼ばれる仕組みの基礎説明 Content Addressable Storage (CAS) の仕組みと利点の紹介 commitオブジェクトtreeオブジェクト の中身の確認方法 gitの設計思想やシンプルさへの理解を深める内容

gitリポジトリを手作業で作る

  • 現代のgitリポジトリ は自動化されており、手作りの温かみが失われている現状
  • gitコマンド に頼らず、手作業でリポジトリを構築する流れの紹介
  • gitでは 「porcelain」コマンド (ユーザ向け)と 「plumbing」コマンド (内部用)という区別がある
  • 今回はplumbingコマンドすら使わず、 git内部構造の仕組み を理解する入門として実践
  • gitの 設計の美しさ やシンプルさを体感できる内容

前提条件

  • gitの基礎知識シェル操作 に慣れていることが必要

手動でgitリポジトリを初期化

  • mkdir artisanal-gitで新規ディレクトリ作成
  • cd artisanal-gitで移動
  • .gitディレクトリを作成し、 リポジトリ情報の格納場所 を用意
  • .git/hooks .git/info .git/objects/info .git/objects/pack .git/refs/heads .git/refs/remotes .git/refs/tags .git/logsなど、 必要なサブディレクトリ を作成
  • .git/configファイルを作成し、 リポジトリ設定 を記述
  • .git/HEADファイルを作成し、 デフォルトブランチ(main) を指し示す内容を記述
    • 例:echo "ref: refs/heads/main" > .git/HEAD

状態確認

  • git statusを実行し、 リポジトリが正しく認識 されているか確認
  • 「On branch main」「No commits yet」などが表示されれば成功
  • .gitディレクトリ内でコマンドを実行するとエラーになるので、 一つ上の階層で実行 すること

gitオブジェクトとContent Addressable Storage

  • gitは全ての情報(コミット、ファイル、ブランチ等)を「オブジェクト」として保存
  • オブジェクトの保存場所は 内容自体のSHA-1ハッシュ値 によって決定される
  • この仕組みは Content Addressable Storage(CAS) と呼ばれる
    • DockerやIPFS、BitTorrent、Nixでも利用される一般的な手法
  • 同一内容のファイルは重複保存されず、効率的なストレージ利用 が可能

commitオブジェクト

  • コミットは SHA-1ハッシュ で一意に識別される
  • .git/objects/xx/yyyyyyyy...という形式で保存され、 zlibで圧縮 されている
  • 解凍すると、 コミットのメタ情報やメッセージ などが格納されている
  • 形式は「commit (内容のバイト数)\x00(コミット内容)」となる

treeオブジェクト

  • treeオブジェクト は、コミットで管理するファイルやディレクトリ情報を保持
  • commitオブジェクト内の「tree xxxxxxxx...」が該当するtreeオブジェクトのハッシュを示す
  • treeオブジェクトの内容は 混在したバイナリ・テキスト形式 で、
    • ファイル名、パーミッション、ファイルのSHA-1ハッシュなどを含む
  • hexエディタ等で内容を確認すると、 ファイル構造や属性情報 が読み取れる

git設計思想の理解

  • gitの強み は複雑なコードではなく、 シンプルでエレガントな設計 にある
  • 内容ベースのアドレッシング により、分散環境や履歴管理に強い特徴
  • 手作業でのリポジトリ構築 を通じて、gitの内部動作や設計哲学を体感できる
  • plumbingコマンドや内部ファイル形式 の理解は、トラブルシュートや高度な運用にも役立つ

この一連の流れは、 gitの本質や仕組み を深く理解したい開発者や技術者にとって、 非常に有益な学習体験となる。

Hackerたちの意見

サイトの作者へ:MBP M1マックを使ってるんだけど、正直言って文字が読みにくい。サイズが小さすぎて、ズームを上げても文字が大きくなるだけで、余白が狭くなっちゃう。Firefoxのリーダーモードもひどい表示になるし。目が悪くなってきた古いコーダーや高解像度のディスプレイを使ってる人たちのために、レイアウトをもうちょっと良くしてくれたら嬉しいな。

でも、AndroidのFirefoxではめっちゃ良く動くよ!)

ちなみに、モバイルブラウザのピンチ・トゥ・ズームジェスチャー(ウェブサイトがモバイル対応になる前からあるやつ)は、今やすべての現代のデスクトップブラウザでも実装されてるよ。これはビューポートズームで、Cmd-+を押して得られるフォントスケーリングズームよりもずっと良いから、このサイトが読みやすくなるんだ。(あまり知られていないけど、モバイルのテキストをダブルタップするジェスチャーもデスクトップブラウザに移植されてる。これは、タップした要素をビューポートの幅に合わせてズームするやつ。ただ、デスクトップでタッチパッドを使うときは、2本指でダブルタップしないといけないから、誰も試そうとは思わないだろうね。)

自分にとっては、テキストサイズは大丈夫だけど、コントラストがもっと良ければいいな。背景色がテキストの非中央ピクセルの色に似てて、中央のピクセルも黒じゃなくてグレーなんだよね。

Gitのデータ構造が分かりやすくて透明性があるところがすごく好き。どうやって動いてるかを読めば、既存のGitディレクトリと互換性のある自分だけの「Git」を作ることもできるんだよね。

理論上は同意するけどね。gitoxideみたいなプロジェクトはもう何年も開発されてるし。

Gitのシンプルさは素晴らしい。いい記事だね!リモートのGitリポジトリで特定のファイルを見つけるにはどうすればいいか調べたことがあるんだけど、直接Gitプロトコルを使うのはやめて、リポジトリ全体をチェックアウトして一つのファイルを取得することにしたんだ。これを読んで、もう少し頑張れたかもしれないなって思った。いくつかのGitホスティングプロバイダーに聞いたら、みんな内部で開発したプライベートAPIがあるって言ってたよ。

手作業でこれをやってるのを見るのは面白い!Gitコマンドの背後にある魔法を解明するのに役立つね。これが好きなら、「Write Yourself a Git」もおすすめだよ。Pythonを使ってミニマルなGit実装を作るんだ:https://wyag.thb.lt/

すごい!ありがとう!

同じようなプロジェクトにCodeCraftersの「Build Your Own Git」があるよ:https://app.codecrafters.io/courses/git/overview

ジェームズ・コグランの「Building git」って本も読んだんだけど、質が高いって保証できるよ。

これ、LLMなしでプログラミングすることについての皮肉な記事になると思ってた。

最近、こういう言い回しがユニークなセールスポイントになってるのを感じる。ソフトウェア(記事、ビジュアルアートなど)がAI生成じゃなくて、手作りでアーティザナルだって。 「すべての言葉は私、人間が書いたものです!」今の技術の流れでは、直感的に違いが分かるけど、いつかは見分けがつかなくなるかもね。「手作り」のクオリティは、ニッチなファンにとってはブランドの問題になるだけかも、レコードみたいに。

コンセプトはすごく似てるけど、DockerがOverlayFSを使ってイメージをどう保存するかについての解説を見てみたいな。結構メタデータがあるしね!

最近考えてることがあるんだけど、GitがrsyncのContent Defined Chunkingアルゴリズムを使うことってできるのかな?クリーンやスマッジを使って何とかできるかも?もしGitじゃなければ、MercurialやFossil、他のDVCSでもいいんだけど。大きなバイナリアセットを扱うのに、LFSのゴタゴタを避けられるし、アセットが圧縮されてなければね。

確か、オブジェクトのデルタを見つけるために、コンテンツ定義のチャンク化を既に使ってるはず。

最近のGit作業での恐怖は、Gitがツリーオブジェクトをどうソートするかを発見したことだ。ドキュメントにはCロケールでソートするって書いてある(バイト順ソート)。簡単だと思ったら、Gitが時々パックファイルを不正だと拒否してきて、ツリーが順序を間違えてるって言われた。実は、文書化されてないルールがあった:ディレクトリツリーエントリ名の前に暗黙のスラッシュを追加しないといけないんだ。そのスラッシュはツリーオブジェクトにはエンコードされてないし、エントリのタイプもそう。20バイトのSHA1ハッシュを入れるだけで、blobかハッシュ(サブモジュールのコミット)になる。だから、ディレクトリ「testing」とファイル「testing.md」がある場合、2つのファイル「testing」と「testing.md」があるディレクトリとはソートが違うんだ。再現例はここにあるよ:https://gist.github.com/bradfitz/4751c58b07b57ff303cbfec3e39...(ツリーオブジェクトが正しくフォーマットされているか確認するには、ツリー内のすべてのエントリのblobが必要だよ、少なくとも1レベルはね)

ディレクトリツリーのエントリ名 でも… gitって実際にはディレクトリを保存してないよね?

git cloneを実装したときに、まさにこのバグに遭遇したことがあるよ。Githubがプッシュを拒否し続けて、後で気づいたんだけど、gitの履歴が無効になってたのは、スラッシュの要件でエントリが正しくソートされてなかったからだった。実際のgitを使えば解決できたかもしれないけど、最初から自分のツールだけでバージョン管理をするつもりだったから、.gitフォルダを削除しちゃった。だから、gitの履歴は全体のサイクルの終わり近くから始まってるみたい。でも、gitについても、自分が実装した言語についても、たくさん学べたよ。

Gitはユーザーフレンドリーなコマンドを「ポーセリン」と呼ぶんだ。あははは…「ユーザーフレンドリー」ね。手でリポジトリをコーディングするのと比べると、そういうことかな。

OSカーネルの人にCLIを書かせるとこうなるんだね。

「プランビング」コマンドと比べるとね。gitのプランビングとポーセリンのメタファーについてもっと知りたいなら、これが良い概要だよ: https://stackoverflow.com/a/39848551

モバイルでサイトに問題があるのは俺だけ? decentなAndroidフォンでFirefox使ってるんだけど、スクロールがすごくカクカクしてて、記事に集中できないんだよね。

このサイトはコンテンツ作成ツールで作られてて、たくさんのJSとCSSを使ってるんだけど、CSSの自動出力がひどくて、ブラウザがコードブロック内の指示のゴチャゴチャを解釈しなきゃいけなくなってる。ツールはHTMLのゴミみたいなのを生成してて(コメント用にブラケットを置き換えたけど): [span style="--0:#E1E4E8;--1:#24292E"] [/span] ...これが何度も繰り返されてて、コードブロック内の空白にスタイル指示を与えてる感じ。性能の低いモバイルCPUだと、こんなにゴミCSSがあるとサイトのレンダリングに問題が出るかもしれないね。$0.02 参考になれば。