5 ポイント 投稿者 GN⁺ 2024-02-14 | 1件のコメント | WhatsAppで共有
  • Gitを長く使ってきたユーザーでも見落としがちなあまり知られていない機能が多く、高度なコマンドライン知識が広く共有されているという前提は揺らいでいる
  • SVNやCVSから移行してきた世代とは異なり、Gitだけを使ってきた開発者は一部の高度な使い方を学ぶ機会が少なかった
  • Gitは時間とともに小さいながら有用な機能を継続的に追加してきており、こうした変化は特定の状況で実用的な価値を持ち得る
  • 中級〜上級ユーザー向けに、古いが有用な機能、最近追加された機能、大規模リポジトリ・モノレポの話題を3本の短いシリーズに分けて扱う
  • 慣れたGitの使い方だけでは見えてこない機能を改めて見直すことで、日常的なリポジトリ作業をより効率的に扱える

Gitを改めて見直す理由

  • 最近、GitとGitButlerに関する発表を行う中で、多くの開発者がGitについて知らない部分が多いことを確認した
  • 以前は高度なGitに関する発表をしていたが、ここ10年ほどは、人々は高度なコマンドライン機能をすでに知っているものだと考えていた
  • Gitだけを使ってきた開発者世代は、SVNやCVSのようなツールからGitへ移行したり、以前の概念を学び直したりする機会がなかった
  • Gitも時間とともに新しい機能を取り入れてきており、その多くは微妙な変更や特定用途向けの変化だが、実際の作業に役立つことがある
  • FOSDEM 2024での発表 little known Git stuff をもとに、ブログシリーズを構成した

3本に分かれるGitヒントシリーズ

  • 対象は中級〜上級のGitユーザーで、Gitを長く使ってきたとしても見落としている可能性がある機能を扱う
  • 1本の記事にすべて詰め込むのではなく、いくつかのテーマごとに分けた短い記事3本で構成する
  • 含まれるテーマ:
  • 最初の記事は Oldies but Goodies へ続く

1件のコメント

 
GN⁺ 2024-02-14
Hacker Newsの意見
  • 筆者として、こうした内容のかなりの部分はかなり最近になって学んだものだと認めている。大規模リポジトリ関連の機能は、この数年でMicrosoftとGitHubがGitコアに少しずつ入れてきたものなので、彼らのやったことを一か所に整理した資料を見つけにくいという点がある
    Mercurial側の人たちとも面白い会話をしており、最近Hg内部の一部をRustで書くことで驚くほどの速度改善が得られているという
    Pro Git第3版も考えているので、Gitを苦労して学ぶ中で知ったことや、知りたい内容があれば教えてほしいとのこと
    • すでに知っているかもしれないが、difftasticをGitのdiffの代わりに使うとよい: https://difftastic.wilfred.me.uk/
      よく使うgitconfigのエイリアスとしてfzagonerootを使っている。git fzaは変更済み/新規ファイルをfzfウィンドウに表示し、選択したファイルをgit addに渡す: https://github.com/junegunn/fzf
      git goneはリモートに存在しないローカルブランチを削除し、git rootはリポジトリのルートを出力するので、深いディレクトリからルートに戻るのに便利。最近はzoxideを使っているので、あまり使わなくなった: https://github.com/ajeetdsouza/zoxide
    • 空白差分に関する部分には、ignore-revs-fileも入れるとよさそう。リポジトリにignore-revsファイルをコミットしておき、大規模な再フォーマットを行った人が該当SHAを追加することで、git blameが壊れないようにする
      https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revltrevgt
    • Gitで苦労して学んだことの一つは、マージ、チェリーピック、リベースのような操作がスナップショットではなく、差分とパッチ、より正確には3-way mergeとして動作するという点。Pro GitはGitのスナップショット保存モデルをうまく強調しているが、このモデルだけで考えると、特にリベースで混乱しやすい
      例えばリベース中にコミットを1つ削除しただけなのに、なぜその後のすべてのコミットが変わるのか理解できなかった。結局、保存はスナップショットベースだが操作は差分ベースだと気づいて初めてリベースを理解できたので、教えるときもこの点をもっと強調すると役に立つ
  • Gitの曲芸を覚えたいのではなく、できるだけ単純に使いたい。コードをプッシュしてGitは終わらせ、そのまま仕事を続けたいだけだ
    Gitが好きな人たちは尊重するが、自分にとっては単に使わなければならない道具でしかない
    • Gitの複雑さの一部は、もともとGitが**低レベルの配管(plumbing)**として設計されたことに由来する。Gitのデータモデルの上に、より親切なユーザー向けの表面(porcelain)が載ることが期待されていたので、単純で一貫したUIを得るには今でもその方向がよいかもしれない。JujutsuやGot(game of trees)がその例になり得る
    • その気持ちは分かるが、Gitはそこまで難しくはない。基本的なcheckout/commit/pushを超えて、特に履歴の書き換えのようないくつかを知っておくと、コミット履歴の品質が大きく向上し、プロジェクトの他のエンジニアが流れを理解しやすくなる
      Gitは業界で長く残る定数に近いものに見えるし、日々の開発で最も頻繁に触るツールの一つなので、少し調べてみる価値はある
    • 問題そのものに内在する細部もあれば、そうでないものもある。内在する難しさを過小評価する傾向があると思う
      だからGitに複雑性がある程度あるのは構わないと思う
    • プログラミングを学びたくなく、コンピュータをできるだけ単純に使いたいと言っているのに似て聞こえる。やることを伝えて終わらせたい、という感じだ
    • Gitのインターフェースは漏れのある抽象化のように感じる。Gitの曲芸を覚えたいわけではなかったが、結局望んでいた以上に多くのことを知ることになった
  • core.fsmonitorについて新しく学んだ。大規模モノレポの観点では、git cloneにレジューム機能があってほしい
    2000年代に低帯域の接続でカーネルリポジトリをクローンしようとして同じ問題に遭い、メーリングリストで助けを求めた後、誰かが個人サイトに圧縮tarでリポジトリ全体を置いてくれてようやく取得できた
    今でも会社のVPNが一瞬切れると、大きなリポジトリのクローンで時々同じ問題が起きる。Windowsリポジトリ300GBを95%まで取得したところでWi-Fiが一瞬切れるところを想像すればよい
    現代の開発スタックで帯域を大量に使う二大ツールであるGitとDockerが、ダウンロードのレジュームをきちんとサポートしていないのは奇妙だ
    • 求めているものはgit bundleに近そう。ただし、そもそも誰かがバンドルを作らなければならないという条件がある
      https://git-scm.com/docs/git-bundle
    • shallow cloneをしてから何度も拡張する形なら可能そうではある。それでもfetch/pushプロトコルは基本的に、より小さなリポジトリや非常に良好なインターネット接続とサーバーを期待しているほうだ
  • 非常に興味深い。複数の人がそれぞれ異なるリリース、機能、ホットフィックスに貢献し、リリースにタグを付け、過去に戻ってバグを探す問題を、より簡単なインターフェースで誰が解けるのか見てみたい
    システムの複雑さを隠す低レベル言語が欲しいと言うのに似ていて、両者は実質的に相互排他的だ。Gitは満足できるもので、学ぶのもそれほど難しくないので、一部は単にGitを学ぶ必要がある
    • だからGitKrakenを強く勧めるようになった。有料製品なので慎重になるが、いろいろなツールを試した中で、GitKrakenほど強力さを引き出してくれるものはなかった
      ターミナルで多くの開発者が感じるブラックボックス感を取り払い、グラフを前面に出し、リベース作業を視覚的に自然に見せてくれるので、Gitが楽しくなる
      CLIの熟練度には今でも価値があるが、10年目の開発者たちが基本的な問題で迷ったり、「本物のエンジニアならGit CLIだけを使うべきだ」という空気のせいでプロジェクト履歴を台無しにしたりするのを見ると、もどかしい
      最近はCLIを使うとしても、一日中別のウィンドウでグラフは見ておくようにと言っている。VS Code、JetBrains、さらにはCLIでも無料で可能だ

チームメンバーがPRをマージしたらすぐ確認して自分のブランチをリベースするので、ブランチが常にmainベースの最新状態になり、マージ地獄やひどい「fix conflicts」コミットを残さずに済む

  • 昨日作成されてから変更が最も多かった上位10個のファイルを探していて、https://github.com/tj/git-extras/blob/main/Commands.mdを見つけた
    使えそうなGit追加コマンドがたくさんある

  • GitKrakenのような現代的なUIクライアントは十分使えて役に立つのに、なぜほとんどの開発者があえてGit CLIにこだわるのか、よく理解できない: https://www.gitkraken.com/

    • CLIの知識はスクリプト作成につながり、スクリプトで学んだGitの知識は日常利用へとまた戻ってくる。サーバーとして使っているRaspberry PiにSSHで入ったとき、CLIを使う必要があるという理由だけで無力になりたくない
      GUIに全面的に反対しているわけではないが、今はCLIのほうが効率的で、次の条件を満たすGUIを探すことに時間を使いたくない
      見た目が良く、古いWebブラウザを埋め込んだようなものではないネイティブアプリで、テレメトリがないかデフォルトでオフになっており、完全なオープンソースで、5年後にも消えていないと期待できるものであること
      さらに、より混乱させるものであってはならない。以前の会社でVisual Studioを使わなければならなかったが、実際には「競合解決済みとしてマーク」という意味のボタンに、不吉にも「Accept merge」と書かれていた
      すでに特定の単語が特定の意味だと期待している人を混乱させてはいけないし、「Commit changes」ボタンが親切のつもりでリモートへのpushまで行うような挙動も信用しにくい
    • CLIも十分使える。エディタのプラグインも使うが、すでにコマンドラインにいるならそこで処理する
      1つコミットするために別のプログラムへ切り替えなければならないと、こまめにコミットしようという意欲が下がる
    • ごく特定の問題がない限り、Gitでやることは最小限にしている。自分の場合は実質的にpushpullcheckout程度なので、GUIを使うのは大げさに感じる
    • すっきり見えるが、グラフィカルインターフェースはあまりにも簡単に気が散る。結局は個人の好みの問題に見えるし、CLIは速いが学習曲線が大きい
      CLIでGitを使うときも、大半は特別なことではなくいくつかのコマンドだけで、たまにしか使わないTipsやテクニックはテキストファイルに書き留めている
  • -committerdateは知っていたが、デフォルトのソートに設定できることは知らず、とても便利。いくつかメモがある
    git columnsは画面に収まらずスクロールが必要になるとかなり分かりにくいので、番号があると良さそう
    git maintenanceは良さそうだが、リベースをたくさんするので心配。loose objectをgcより早く失うのか気になる。gcがオフになっているのは分かるが、明確ではない
    git blame関連で、あまり知られていないが便利なスクリプトとしてhttps://github.com/gnddev/git-blameallがある。あまりにも知られていなかったので、自分でPython 3に移植する必要があり、私はPython開発者ですらない

    • スケジュールされたメンテナンスではgcは無効化される。maintenance runを明示的に実行するときは、タスクとして有効化される
      loose objectをgcより早く回収することはない。結局は単にgcを実行しているだけだから
    • 逆順ソートが可能なのか気になる。ブランチが画面外へ押し出される問題の簡単な解決策は、最新ブランチを最後に置くことのように見える。自分はユーザースクリプトでそうしている
    • 早く失うことはない。リモートからデータをより頻繁に取得し、データを再パックするだけ。GCがオフならデータは削除されない
      git-blameallは良さそうなので一度使ってみたい
  • 複数の環境で動くエイリアスをいくつか用意して、Gitの流れを大幅に単純化した
    git syncedは現在のブランチを、upstreamがあればそこに、なければoriginに合わせてリベースで同期する。masterまたはmainを使い、mainを優先する
    git pubは変更をリモートoriginに公開し、lease付きの強制pushを使う
    git prはGitHubで適切なPR URLを開き、GHクライアントは不要。upstreamが定義されていればそちらへPRを送る
    git hubはリポジトリのGitHubページを開く
    https://softwaredoug.com/blog/2022/11/09/idiot-proof-git-aliases.html

    • 区切り文字として使っている変な毛の生えた矢印を、なぜ選んだのか気になる
  • 分かっているふりをやめて、視覚的なGitツールを使っている。SmartGitやIntelliJに入っているツールのようなものだ。Gitの「コマンドライン・ヒーロー」は、見せびらかしに近いと思う
    ユーザー向けのコマンド層は、いら立つほど分かりにくいことがある。たとえばYoursTheirsは、文脈によって正反対の意味になり得る
    ユーザーインターフェース全体に共通したスタイルやテーマがないため、人をおかしくさせないためには新しい視覚的なレイヤーが必要だ

    • 自分も同じ。常に差分を見られて、何が起きるのかを一目で視覚的に確認できるのが良い。追加のコマンドをいくつも実行する必要もない
      アプリとGit全般については、仕事に必要な分だけ知っていて、まれにもっと必要になれば調べればよい。何年も使っていて、そういうことは一、二回だけだった
    • 日常作業では常に視覚的なGitツール、特にTortoise Gitを使っている
      他人や自分のミスを直す複雑な作業でも、まず視覚的ツールで履歴とコミット、reflog、差分を見て、何がこじれているのか、救えるものがあるのかを把握する
      戻るべきコミットが1つだけならreset --hardを使い、複数のコミットから何かを統合する必要があるなら、たいていコマンドラインを使う
  • 両者は相互排他的ではありません。差分や競合のようなものは視覚的なツールだけを使っていますが、コミットオブジェクト、reflog、リベースが裏側で行っていること、インタラクティブリベース、hard/soft reset などを学ぶことで得たものは多くありました