3 ポイント 投稿者 GN⁺ 2025-06-23 | 1件のコメント | WhatsAppで共有
  • Git notesは、Gitオブジェクトを変更せずに別の名前空間でメタデータを付与する機能だが、使い勝手の低さと採用の限定性から広く使われていない
  • 古いコミットメッセージを修正しなくても新しい情報を追記できるため、レビュー・ビルド・チケット情報のように自動化システムが残す記録に向いている
  • GitプロジェクトとGerritはnotesを実際に活用し、コミットごとのメーリングリストでの議論、テスト結果、レビュアー情報をgit logで確認できるようにしている
  • Googleのgit-appraiseはgit notesの上に分散コードレビューを実装し、レビュー依頼、コメント、レビュー、マージをローカルで行えるようにしている
  • GitHubは2014年にコミットnotesの表示を停止し、blob・tree notesはGit内部コマンドに慣れている必要があるため、プロジェクト履歴の分散という可能性があっても使いにくい

Gitオブジェクトを変更しないメタデータ

  • Git notesは、Gitが追跡するオブジェクトに別のメタデータを保存する機能
    • 対象はコミットだけでなく、blobtreeも含まれる
    • オブジェクト自体を変更せず、別の名前空間に情報を付与する
  • すでに履歴に入ったコミットメッセージは通常、安全に修正するのが難しいが、notesを使えば古いコミットにも新しい情報を追加できる
    • 次のようにgit notes add -mでメモを付けられる
      git notes add -m 'Acked-by: <tyler@tylercipriani.com>'
      
    • その後、git logでは該当コミットの下にNotes:ブロックとして表示される
  • Scott Chaconは2010年のGitHub.blogで、notesを他の開発者との会話よりも、チケット・ビルドシステムのような自動化記録を付ける用途により適した機能だと見ていた

実際の活用と行き詰まる点

  • Gitプロジェクトは、各コミットをメーリングリストでの議論と結び付けるためにnotesを使っている
  • notesは、コミットやブランチごとの作業時間追跡、git logへのレビュー・テスト情報の追加、完全分散コードレビューといった用途にも使われる
  • Gerritのreviewnotesプラグインは、コードレビューメタデータをGit内でオフライン表示できるようにする
    • notesを取得して表示するコマンドは次のとおり
      git fetch origin refs/notes/review:refs/notes/review
      git log --show-notes=review
      
    • 表示情報にはVerified+1Verified+2Code-Review+2Submitted-bySubmitted-atReviewed-onProjectBranchなどが含まれる
  • Googleのgit-appraiseは、git notesの上に構築された「fully distributed code review」システム
    • GitHub、GitLabのようなコードforgeから独立して動作する
    • 変更レビューの依頼、変更へのコメント、レビューとマージをローカルコンピュータ上で実行できる
    • Webインターフェースも含む
  • 最大の弱点は使い勝手
    • GitHubは2014年にコミットnotesの表示を停止した
    • コミットnotesはgitconfig設定により、自動fetchとgit log表示をある程度簡単にできる
      git config --add \
      remote.origin.fetch \
      '+refs/notes/*:refs/notes/*'
      
      git config \
      notes.displayRef \
      'refs/notes/*'
      
    • blobやtreeにnotesを保存するには、Gitのplumbingに慣れている必要がある
  • Gitはコード履歴を分散するが、Gitリポジトリの多くの価値はGitHubのようなforgeの中に閉じ込められている
    • git notesは、コードだけでなくプロジェクト全体の履歴を分散する道になり得る

1件のコメント

 
GN⁺ 2025-06-23
Hacker News のコメント
  • あまり知られていない別の機能として git trailers がある: https://alchemists.io/articles/git_trailers
    コミット作成時に含められるキー・バリュー形式の構造化データで、一部のシステムはこれをメタデータの付与に使っている。たとえば Gerrit は Change-Id を付けるためにこの機能を使っている

    • 他のシステムの似た機能として PostgreSQL COMMENT がある: https://www.postgresql.org/docs/17/sql-comment.html
      PostgreSQL のさまざまなデータベースオブジェクトにテキストを付けられるようにするもの。PostgreSQL にも、編集可能な構造化キー・バリュー形式のデータベースオブジェクト用メタデータ機能があるとよさそう
    • GitHub が [skip ci] を入れる代替として git trailers を使うことを最近知った。おそらくコミットメッセージを消費する下位システム側で、より簡単に取り除けるようにするためだと思う: https://docs.github.com/en/actions/managing-workflow-runs-an...
      なぜ最後の trailer でなければならないと強制しているのかは分からない。正規表現の都合かもしれない
    • 自分のブランチのコミットのうち、ユニットテストを実行したコミットに印を付けるために git notes を使い、スクリプトがそうしたコミットをスキップするようにしていた
      オープンソースの upstream と作業しながら、git rebase -i でブランチを完璧に整えたいときに便利だった。今なら、その情報は git trailers に入れるほうがよさそうに見える。Change-Id については、Git 自体にこの種の識別子があればツールも理解できるので良いと思う。コミットメッセージでコミットを識別するのは、特に MR でメッセージを変更できる場合には脆弱だ。コミット ID はコミットを一意に識別するが、同じ変更を別のコミットの上に移せる場合には有用な識別子ではない。ただし trailers は実際のコミットの一部で、notes はそうではないので、自分が使っていた用途には良い代替にはならなさそう
    • 興味深い。この機能は知らなかった。conventional commits が好きなのだが、trailers はそうしたメタデータを追加するより良い方法に見える
      コミットメッセージに手で入れるのと --trailer フラグを使うのが、機能的に同じなのか気になる
    • GOOG で働いていたときに使っていた Gerrit が本当に恋しいが、2020年代の基準で見るとデプロイの話はかなり微妙だ
      ローカルでインスタンスを立てて、GitHub にホストされたリポジトリと統合しようとして、ただ挫折しただけだった。コミットをまたいだ変更追跡などを GitHub よりうまく扱い、なおかつより活発に開発されていて GitHub 連携にも親和的な代替があるのか気になる。GitHub のコードレビュー用ツールは本当に嫌いだ
  • Forgejo も今年1月に出たバージョン 10 から対応している: https://forgejo.org/2025-01-release-v10-0/#new-features
    https://codeberg.org/forgejo/forgejo/pulls/4753

  • 本当にすごく良さそうだが、amend や rebase のように、実質的にコミットを修正済みコピーに置き換える履歴の書き換え機能と notes がどう一緒に動くのか気になる
    notes は特定のコミット、ツリー、blob ID に付くもののように聞こえる。git rebase などが notes を新しいコミットへコピーするほど賢いのか、それとも単に消えてしまうのか気になる。インタラクティブ rebase で複数のコミットを1つに squash したらどうなるのかも疑問だ。blob やツリーに notes を付ける場合も同じ問題がありそう。リポジトリ内のファイルやディレクトリにメタデータを付けているように感じるが、実際には特定の内容に付けていることになる。たとえば "Hello world!" という文字列を含む blob に note を付けた場合、Git はその内容を持つすべてのファイルに note を関連付けるのだろうか? また、あるファイルを "Hello, world!" に変更すると notes を失うのだろうか?

    • これは設定可能。デフォルトでは amend と rebase の操作は notes を先へコピーする。notes.rewrite の項目は git-config(1) を見ればよい
  • Git はたぶん10年ほど使ってきたが、git notes があるとは知らなかった。すごい
    「すべての forge がコードレビューメタデータを Git 内でオフライン利用できるようにしてほしい」という要求は、GitHub のような商用 forge にはあまり通じなさそうだ。本人も言っているように、Git リポジトリの価値の多くが GitHub のような forge に閉じ込められているからだ。営利企業は通常、自社の付加価値を汎用化することに積極的ではない。GitHub を責めたいわけではなく、優れたサービスと非常に寛大な無料枠を提供していて、移行したければ API で全データを取り出せるようにしている点ではよくやっていると思う。ただ商業運営の本質がそういうものだというだけ

    • その機能を差別化要素にする新サービスをまず立ち上げる必要があり、そうすれば競合が追いつこうとしてその機能を再び追加するかもしれない
  • Git notes は、コミットがすでに作られて他人の目に触れたあとで、テキストを頻繁に追加する場合にだけ素晴らしい
    Acked-By やメーリングリストでの議論へのリンクの例は、あまり良い例ではないように思う。どちらもコミットを作る時点ですでに分かっている可能性が高い。Git のコミットメッセージには事実上ほとんど長さ制限がないので、forge 上で行われたコミット関連の議論をコミットメッセージ自体にそのままコピーすることもできる。より良い例は、あとで revert されたコミットに git note を追加する場合だと思う

    • よくある失敗パターンは、コミットメッセージが、実際には直せていないバグを修正したと堂々と宣言してしまうこと。そして、その修正が生んだ連鎖的なバグを 1 つのバグに結び付けてしまうこと
      自分が変なのかもしれないが、コードがそもそもなぜ書かれたのかを思い出そうとして、コメントや annotate をちゃんと見ない同僚をあまりにも多く見てきた。とにかくいきなり変更して、問題が自分に結び付かないことを願うようなやり方だ。だが、バグ修正を待ち続けていた怒った顧客を相手にし、その後まもなくそのバグが再発するのを経験すると、バグ修正にはもっと慎重になれる。複数のバグを一度に直すにはリファクタリングが必要なことが多く、リファクタリングは新機能の機会や性能改善につながることもある
    • コミットについての議論、つまりレビューとコミット承認(Ack)は、コミットが作られる前には起こり得ない
      あとで revert されたコミットに印を残す用途なら、コミットメッセージのほうがよい。ファイルに対して blame すればそのファイルの最新の変更が見え、あるコミットが別のコミットの変更を revert しているなら、より新しい revert コミットが blame に現れる
    • コミットが作られたあとでも議論は続き得る
  • これは知識不足ではなく UI の問題。GitHub の UI が notes を表示すれば、利用はすぐにはるかに増えるはず

    • GitHub がこれをサポートしてくれるといいのだが
  • 「Git の最もクールだが愛されていない機能」はたくさんある。たとえば bisect、pickaxe、reflog、range-diff、archive、annotated tags など
    多くの人が Git を派手な Google Drive 程度にしか考えていないため、こうした機能がよく忘れられてしまうのは残念

    • Git notes は、いずれにせよ機能追跡にはより高レベルな プロジェクト管理ツール が必要なので重複している。ロードマップ、機能階層、非技術的な詳細が必要で、大きなトラッカーや Jira を思い浮かべればよい
      それでも問題ないと思う。Unix 哲学は、1 つのことに集中し、それをうまくやることだから
    • 多くの場合、そうした機能は実際にはそれほど有用ではなく、働き者の役割を果たす中核ツールの周辺にある飾りに近いから
    • 挙げられた機能は全部知っているつもりだったが、pickaxe で不意打ちを食らった。あまり自信過剰になってはいけないな
  • LibreOffice プロジェクトでは、Apache OpenOffice リポジトリの各コミットを追跡するために Git notes を使っていた
    そのリポジトリを LibreOffice Git リポジトリのブランチとしてミラーしながら、各コミットが無関係な変更なのか、たとえば LibreOffice がずっと前により良いものへ置き換えたビルドシステムの変更なのか、すでに LibreOffice にあった変更と重複しているのか、あるいはまれなケースとして LibreOffice に取り込まれたのか、どのコミットとして cherry-pick されたのかを記録していた。今でも https://cgit.freedesktop.org/libreoffice/core/log/?h=aoo/tru... で直接見ることができ、この Git フロントエンドはいまも notes を表示する。数年前からはこうした変更追跡をやめているが、おそらく Apache OpenOffice の変更ペースが非常に遅くなり、わずかな変更を cherry-pick して得られるメリットがあまりなくなったためだろう

  • 最もクールだが愛されていない機能というより、会社全体を開発者だけで運営するチームのような、かなり特定のケースではクールだったかもしれない ギミック機能 に近い
    必要なものはコミットメッセージに入るし、別システムのチケットを参照するのはバグではなく機能だ。JIRA や他のシステムは非開発者とコミュニケーションするために使われるからだ。たとえばビジネスアナリストはコードにもリポジトリにもまったくアクセス権がなく、サポート担当者もリポジトリやコードにアクセスできない。非開発者が notes を見たり編集したりできるフロントエンドを作ることはできるが、それでもあまり意味はない。ビジネスアナリストやサポートチームなどは特定のコミットには関心がなく、1 つの機能が 1 つのコミットにぴったり対応することもあるが、普通はそうではない。複数のリポジトリを使い、1 つの機能が複数のサービスにまたがると、git notes はかなり役に立たなくなり、結局は外部システムへの参照が必要になる

    • ビジネスアナリストやサポート担当者がコードとリポジトリへのアクセス権を与えられないほうが、むしろ変ではないかと思う。自分たちの製品を ブラックボックス のように扱って、何の利点があるのだろうか?
      しかし、それが主流だ。ときどき、同じモノレポを共有している別チームのアナリストが、コード 1 行を見ればすぐ答えられる質問を私にしてくる。そのアナリストは技術寄りで SQL も分かるし、私たちのコードは非常に慣用的で高レベルに書かれている。それでも文化というものは、内在する非効率によって死に至るまでは自ら変われない
    • コミットメッセージには属さないが関連のある コミット外データ は多い。テストが通ったかどうか[1]、手動テストの記録、コードレビューの反復過程、6 か月以上前の問題コミットを掘り起こすときに残すメモのようなものだ
      [^1] https://news.ycombinator.com/item?id=44348438
  • GitLab の notes サポートを求める 9 年前の機能リクエスト が最近クローズされた: https://gitlab.com/gitlab-org/gitlab/-/issues/15029
    残念ながら読むにはログインが必要だが、どの gitlab.com アカウントでもよいはず

    • より完成度の高い提案を含む別の issue もある: https://gitlab.com/gitlab-org/gitlab/-/issues/216351
    • 気になる人のために言うと、完了したからクローズされたのではなく、放置されてクローズされたものだ。「現在この領域に注力していないため、この機能リクエストをクローズします」