3 ポイント 投稿者 GN⁺ 2024-11-26 | 1件のコメント | WhatsAppで共有
  • 個人・業務リポジトリをすべて ~/workspace に置く環境では、フォルダ位置よりも remote URL を基準に Git アイデンティティを分けるほうが正確
  • Git の includeIfgitdir でパスごとの設定を読み込めるが、同じ作業ディレクトリ内に複数アカウントのリポジトリが混在すると パス基準の分岐 は限界にぶつかる
  • hasconfig:remote.*.url: 条件を使えば、GitHub、GitLab、SourceHut、特定の GitHub 組織のように remote URL パターンに応じて別の設定ファイルを含められる
  • SSH キーは ~/.ssh/configHostHostnameUserIdentityFile を使って別管理する必要があり、同じ github.com でも組織ごとのキーを使うには Host エイリアス が必要
  • url.<base>.insteadOf をあわせて設定すると、普段どおり git@github.com:orgname/project を使いながらも、内部的には gh-work:orgname に置換されて正しい SSH 設定が使われる

remote URL 基準で Git 設定を分ける

  • 既存の includeIf の例では、gitdir:~/code/**gitdir:~/work/** のように ローカルディレクトリのパス に応じて別の設定ファイルを含める
    • ~/code 配下では ~/.config/git/personal~/work 配下では ~/.config/git/work を読み込める
    • 含まれるファイルには通常、user.nameuser.emailuser.signingkey のような Git アイデンティティや署名キーが入る
  • すべてのコードを ~/workspace 配下に置くと、個人、work-1work-2 のリポジトリが同じパス構造に混在し、パスベースの条件だけでは望む区別が難しい
  • Git の hasconfig:remote.*.url: を使うと、現在のリポジトリに特定の remote URL があるときだけ設定ファイルを含められる
    • git@github.com:*/** に一致すれば ~/.config/git/config-gh
    • git@github.com:orgname/** に一致すれば ~/.config/git/config-gh-org
    • git@gitlab.com:*/** に一致すれば ~/.config/git/config-gl
    • git@git.sr.ht:*/** に一致すれば ~/.config/git/config-srht
  • Git は最後にマッチした設定を読み込むため、条件の順序 が重要
    • github.com:orgname/** 条件は一般の github.com:*/** 条件より下に置かないと、組織専用設定が通常の GitHub 設定で上書きされてしまう
  • 結果として、github.com:orgname/** の remote を持つリポジトリは config-gh-org を使い、それ以外の GitHub リポジトリは通常の GitHub 設定を使う

SSH キーと insteadOf で組織別の接続情報を合わせる

1件のコメント

 
GN⁺ 2024-11-26
Hacker News のコメント
  • insteadOf の代わりにリポジトリを gh-work:org/repo としてクローンし、Git 設定には includeIf "hasconfig:remote.*.url:gh-work:**/**" を入れる
    こうすると、gh-work 配下で定義された SSH アイデンティティでクローンしたリポジトリは gh-work.inc 設定を自動的に取り込み、その中には Git のアイデンティティや SSH 設定と同じ署名キーが入る
    結果として gh-work という名前が SSH アイデンティティと Git アイデンティティを区別する基準になり、より理解しやすい

    • 記事の解決策は必要以上に自由度が高いようで落ち着かなかったが、ランタイムパラメータを1つに減らすエレガントな方法に見える
    • includeIf大文字小文字を区別し、優先順位は最後の設定が勝つ
      正しく動作しているか確認するには、git remote get-url origingit config --get user.email を実行すればよい
    • この方法は、リモートリポジトリ URL が特定の形式だと期待するスクリプトを壊す可能性があった
  • より良い方法は、HOME.gitconfig にアイデンティティ別のエイリアスを置き、リポジトリの初期化やクローン直後に git config-company または git config-personal を実行することだと思う
    user.useConfigOnly = true を有効にし、エイリアスでローカルリポジトリの user.emailuser.namecore.sshCommand をそれぞれ個人用/会社用 SSH キーに設定すればよい

    • 最初から正しい SSH 設定なしで初回クローンをどう行うかが問題になる
      記事の方法は、組織からクローンすればそのまま動く点が利点に見える
  • 以前あるスタートアップに、毎日おとぎ話のような適当な名前にアイデンティティを変える人がいた
    月曜日のコミットは Mr. Bunnymann、火曜日のコミットは Doctor Funtime といった具合で、バージョン管理フォレンジックをする時に非常に不便だった
    好意的に見れば、誰でもアイデンティティ設定に任意の値を入れられるので、その値をあまり信用しすぎてはいけないと思い出させようとしていたのかもしれない

    • 非難しない文化であれば、バージョン管理フォレンジックでは誰がやったかよりも、いつ、どの変更の周辺で起きたかの方が重要だったはず
      それでも詳細を尋ねたり、スタイルや専門性を推測したりするには、誰がやったかを知ることが役に立つ
      コミットに GPG 署名を要求し、許可された GPG アイデンティティを登録すれば、author/committer メタデータの代わりに署名で実際の作者を識別できる
      もちろん「簡単に」と GPG 署名は、いつも相性がよいわけではない
    • 従業員が書いた文書や署名を信頼するのと同じくらい信頼すればよい
      従業員が自分のコミットを正しく識別できないと信じられないなら、解雇すべきだと思う
    • 好意的に見れば、同じ署名キーを使っていたのかが気になる
    • そんな悪ふざけで給料をもらっていたというのが驚きだ
    • Git には author と committer を分ける組み込みサポートがあり、おそらく author 属性だけを変えていたのだと思う
  • ~/.ssh/config を触る必要はなく、~/.gitconfig や記事のように ~/.config/git/personalcore.sshCommand = /usr/bin/ssh -o IdentitiesOnly=yes -i ~/.ssh/IdentityFile2 -a を入れればよい
    こうすれば insteadOf なしでもサブモジュールが楽になる

    • SSH アイデンティティが複数ある場合はどうするのか、という問題は残る
  • 以前からディレクトリベースの includeIf を使ってきたが(https://www.bobek.cz/til/git-identities/)、hasconfig:remote は本当にすっきりしている
    リポジトリをクローンする時にも動作する

  • includeIf はかなり良い
    今は SSH の複雑さを ~/.ssh に置き、顧客/プロジェクト/アイデンティティごとに include を1つずつ置いている
    GitHub のように固有のホスト名がないものには customer-github のようなホストエイリアスを付け、HostName github.comIdentityFile ~/.ssh/customer_rsaUser git のように設定する
    あとは git clone でそのエイリアスを使うだけで終わり

  • 同じ問題があり、これで解決策ができたことになる
    NixOS と home-manager を Linux と Mac で使うと、この設定は簡単になる
    programs.git.includescondition = "hasconfig:remote.*.url:git@github.com:/**"user.email 設定を入れればよい
    参考: https://nix-community.github.io/home-manager/options.xhtml#opt-programs.git.includes

    • 直接 .gitconfig に書くより簡単には見えない
      記事と同じ条件と設定なのに、そこにビルド/テンプレート段階と、独特な文法の新しいプログラミング言語の学習まで追加される
  • すでに includeIf: "gitdir" で仕事用と個人用の設定を分けていたが、hasconfig:remote は完全にゲームチェンジャーだ

    • この宝物が3年間ドラフトとして隠れていたとは信じられない
  • コンサルタントには、仕事用には常に別マシンを使うか、少なくとも別の OS ユーザーを使うよう強く勧めている
    個人用マシンを仕事に使うと、大きな面倒に巻き込まれるリスクがある

    • 「個人用マシンを仕事に使うこと」は範囲が非常に広い
      リモートファーストの会社でノートPCを自分で用意し、2〜3年ごとに新しい機器の購入費を受け取っていたが、それでも個人ノートPCだった場合もあるし、臨時契約者の場合もある
      どの状況でなぜ問題になるのか、もっと具体的に説明すべきだ
      リスクは実際にあるが、列挙できないなら教育ではなく FUD を広めるのに近くなる
  • プロジェクトごとに Git アイデンティティを簡単に切り替えるために作ったツール: https://github.com/cquintana92/git-switch-user
    アイデンティティを設定した後、$ git su Personal または $ git su Work を実行すると、メール、名前、SSH キー、任意で PGP キーまでリポジトリの .git/config に設定される
    かなり時間を節約してくれた

    • SSH 経由の Git アクセス用の GitHub アイデンティティ管理ツールもある: https://github.com/dolmen/github-keygen
      12年前のツールだが、今も活発にメンテナンスされている