Gitのヒントとテクニック
(blog.gitbutler.com)- 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: 古いが今なお有用なGit機能
- Some Subtle New Things: 最近Gitに追加された微妙な変更
- Really Large Repositories and Monorepos: 非常に大きなリポジトリとモノレポに関する内容
- 最初の記事は Oldies but Goodies へ続く
1件のコメント
Hacker Newsの意見
Mercurial側の人たちとも面白い会話をしており、最近Hg内部の一部をRustで書くことで驚くほどの速度改善が得られているという
Pro Git第3版も考えているので、Gitを苦労して学ぶ中で知ったことや、知りたい内容があれば教えてほしいとのこと
difftasticをGitのdiffの代わりに使うとよい: https://difftastic.wilfred.me.uk/よく使う
gitconfigのエイリアスとしてfza、gone、rootを使っている。git fzaは変更済み/新規ファイルをfzfウィンドウに表示し、選択したファイルをgit addに渡す: https://github.com/junegunn/fzfgit goneはリモートに存在しないローカルブランチを削除し、git rootはリポジトリのルートを出力するので、深いディレクトリからルートに戻るのに便利。最近はzoxideを使っているので、あまり使わなくなった: https://github.com/ajeetdsouza/zoxidegit blameが壊れないようにするhttps://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revltrevgt
例えばリベース中にコミットを1つ削除しただけなのに、なぜその後のすべてのコミットが変わるのか理解できなかった。結局、保存はスナップショットベースだが操作は差分ベースだと気づいて初めてリベースを理解できたので、教えるときもこの点をもっと強調すると役に立つ
Gitが好きな人たちは尊重するが、自分にとっては単に使わなければならない道具でしかない
checkout/commit/pushを超えて、特に履歴の書き換えのようないくつかを知っておくと、コミット履歴の品質が大きく向上し、プロジェクトの他のエンジニアが流れを理解しやすくなるGitは業界で長く残る定数に近いものに見えるし、日々の開発で最も頻繁に触るツールの一つなので、少し調べてみる価値はある
だからGitに複雑性がある程度あるのは構わないと思う
core.fsmonitorについて新しく学んだ。大規模モノレポの観点では、git cloneにレジューム機能があってほしい2000年代に低帯域の接続でカーネルリポジトリをクローンしようとして同じ問題に遭い、メーリングリストで助けを求めた後、誰かが個人サイトに圧縮tarでリポジトリ全体を置いてくれてようやく取得できた
今でも会社のVPNが一瞬切れると、大きなリポジトリのクローンで時々同じ問題が起きる。Windowsリポジトリ300GBを95%まで取得したところでWi-Fiが一瞬切れるところを想像すればよい
現代の開発スタックで帯域を大量に使う二大ツールであるGitとDockerが、ダウンロードのレジュームをきちんとサポートしていないのは奇妙だ
https://git-scm.com/docs/git-bundle
システムの複雑さを隠す低レベル言語が欲しいと言うのに似ていて、両者は実質的に相互排他的だ。Gitは満足できるもので、学ぶのもそれほど難しくないので、一部は単にGitを学ぶ必要がある
ターミナルで多くの開発者が感じるブラックボックス感を取り払い、グラフを前面に出し、リベース作業を視覚的に自然に見せてくれるので、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追加コマンドがたくさんある
git-extrasは良い。ほかに良いツールとしてgit absorbもある: https://github.com/tummychow/git-absorbGitKrakenのような現代的なUIクライアントは十分使えて役に立つのに、なぜほとんどの開発者があえてGit CLIにこだわるのか、よく理解できない: https://www.gitkraken.com/
GUIに全面的に反対しているわけではないが、今はCLIのほうが効率的で、次の条件を満たすGUIを探すことに時間を使いたくない
見た目が良く、古いWebブラウザを埋め込んだようなものではないネイティブアプリで、テレメトリがないかデフォルトでオフになっており、完全なオープンソースで、5年後にも消えていないと期待できるものであること
さらに、より混乱させるものであってはならない。以前の会社でVisual Studioを使わなければならなかったが、実際には「競合解決済みとしてマーク」という意味のボタンに、不吉にも「Accept merge」と書かれていた
すでに特定の単語が特定の意味だと期待している人を混乱させてはいけないし、「Commit changes」ボタンが親切のつもりでリモートへのpushまで行うような挙動も信用しにくい
1つコミットするために別のプログラムへ切り替えなければならないと、こまめにコミットしようという意欲が下がる
push、pull、checkout程度なので、GUIを使うのは大げさに感じる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を実行しているだけだから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の「コマンドライン・ヒーロー」は、見せびらかしに近いと思う
ユーザー向けのコマンド層は、いら立つほど分かりにくいことがある。たとえば
YoursとTheirsは、文脈によって正反対の意味になり得るユーザーインターフェース全体に共通したスタイルやテーマがないため、人をおかしくさせないためには新しい視覚的なレイヤーが必要だ
アプリとGit全般については、仕事に必要な分だけ知っていて、まれにもっと必要になれば調べればよい。何年も使っていて、そういうことは一、二回だけだった
他人や自分のミスを直す複雑な作業でも、まず視覚的ツールで履歴とコミット、reflog、差分を見て、何がこじれているのか、救えるものがあるのかを把握する
戻るべきコミットが1つだけなら
reset --hardを使い、複数のコミットから何かを統合する必要があるなら、たいていコマンドラインを使う両者は相互排他的ではありません。差分や競合のようなものは視覚的なツールだけを使っていますが、コミットオブジェクト、reflog、リベースが裏側で行っていること、インタラクティブリベース、hard/soft reset などを学ぶことで得たものは多くありました