- GitHub式のPRレビューでは、元の変更の上に修正コミットを積み増ししやすく、レビュー過程と最終的なコード履歴が混ざってしまう問題がある
- 良いパッチシリーズは、リファクタリング、新しいAPIの追加、既存利用者の移行のように、論理的に分離されたコミットを順番に読めるべきである
"fix review" や "minor" のようなコミットが積み重なると、変更意図がぼやけ、git blame や git bisect で問題の原因を探すコストが大きくなる
- interdiff レビューでは、パッチシリーズの新しいバージョンを発行し、
git range-diff main..v1 main..v2 でコミットごとの変更差分を比較する
- レビュアーは500行全体を読み直さずに50行の増分だけを確認でき、作者は
"address review" のようなノイズコミットなしで最終コミット構成を維持できる
コードレビューツールと出発点
- Gerrit Code Review は Git リポジトリと連携して動作するオープンソースのコードレビューツールで、パッチを投稿し、他の人がコードをレビューしてコメントを残す流れを支援する
- コードレビューの方式は、Gerrit、GitHub、Phabricator だけでなく、バグトラッカーに
.patch ファイルを上げる方式、git send-email、同僚との長い議論の末に実装へ導く方式までさまざまである
- Go プログラミング言語は Gerrit を使っており、KDE と LLVM は Phabricator を使っていた。また Jujutsu は Gerrit の利用を検討したことがある
- Linux カーネルはメールベースのワークフローを独特のやり方で使っており、多くのプロジェクトは使いやすく導入コストの低い GitHub を選ぶ
- 核心的な問題は、ツールごとに同じレビューのモデルを提供しているわけではなく、GitHub の標準的な体験が常に十分とは限らない点にある
良いパッチシリーズの条件
- 理想的なパッチシリーズは、ひとつの大きな変更を論理的な段階に分けて提出する形である
- まず偶然見つけたコード整理を行う
- 次に新しい API を追加する
- 最後に既存 API 利用者を新しい API へ移行する
- 各パッチは独立した理由を持つべきであり、順番に適用したときにコードが段階的に進化していく様子が見えるべきである
- この構造は、作者やレビュアーだけでなく、後で
blame や bisect によって変更理由を追わなければならないメンテナにも有利である
- 実際のパッチサイズは状況によって変わる
- リファクタリングがないこともある
- 100行のこともある
- 中核APIの変更のように、すべての呼び出し箇所を修正する必要があるなら500行になることもある
GitHub式「diff soup」が生む混合履歴
- GitHub は、レビューコメントを反映するときに、元のコミットの上へ新しいコミットを追加する流れを明示的・暗黙的に促している
- 例では、元の3コミットの後ろに、Alice と Bob のレビュー反映、テスト追加、
"minor" 実装変更コミットが順に積み重なる
- コミットグラフには親子関係しか残らないため、レビュー修正コミットが元のどのコミットのどの問題を直したのかは見えない
- ひとつの
"fix review" コミットが複数の元コミットを同時に触ると、概念モデルはさらに複雑になる
- ひとつの修正コミットが厳密にひとつの指摘だけを反映するようにもできるが、その分 fixup コミットの数は増える
- このように、大きな変更のまとまりとレビュー修正がひとつの器に混ざった状態が「diff soup」である
git blame と git bisect のシグナルがぼやける
git blame は行単位で動作するため、レビュー反映コミットが既存行のごく一部だけを変えた場合でも、その行の出所が "fix alice review" のようなコミットとして見えることがある
- 実際の変更理由を見つけるには、元のコミットとレビュー修正コミットを追い直すコミット考古学が必要になる
git bisect でも、"minor" コミットが本当の原因なのか、新しい API が最初に追加された時点からあったバグが後になって表面化しただけなのかが不明瞭になりうる
- 新しい API が大きな性能向上をもたらすなら、元に戻すのが望ましくない、あるいは不可能な場合もある
- 回帰が数週間後に現れた場合、P1 会議のような緊急状況で、
"minor" というコミットメッセージだけを見て追加調査しなければならないコストが発生する
- レビューが2回往復しただけの例でも履歴は複雑になり、オープンソースプロジェクトのように何度もレビューが繰り返される場合は問題がさらに大きくなる
GitHub UX がこの流れを強化する仕組み
- GitHub で増分レビューを行うには、新しいコミットを上に積む方式が事実上もっとも簡単である
- 新しい API の500行を読み直すより、
+/- 10 行の "fix alice review" パッチを見るほうがレビュアーの負担は小さい
- PR の diff タブは、デフォルトではすべてのコミットをひとつの diff にまとめて表示する
- これは
git diff master..foo-branch を見るのに近い
- しかし、これは人が変更を書き、読み取るやり方とはあまり合っていない
- GitHub の UX は名前付きブランチモデルに強く最適化されており、ブランチ以外の単位同士の差分を見にくくしている
- force push 後、PR の「Force Push」行にある「Compare」ボタンで diff を見ることはできる
- ただし表示されるのは、以前のブランチ head と現在のブランチ head の全体 diffだけである
- より細かい比較をしたければ、コミット ID を自分で探して URL に入れる必要がある
interdiff レビューと git range-diff
- interdiff レビューでは、元の3コミットの上に修正コミットを追加するのではなく、同じ3コミットから成る新しいバージョンを発行する
- たとえば
v1 パッチシリーズで Bob のコメントを反映する必要があるなら、1つ目のコミットと3つ目のコミットを修正して v2 シリーズを作る
- その後、Alice のコメント、テスト追加、
"minor" 変更まで同じやり方で反映しても、最終結果は依然として3コミットのままである
v1 のコミット A、B、C が v2 の X、Y、Z へ進化したなら、git range-diff は各位置のコミット同士の差分を表示する
git range-diff \
main..v1 \
main..v2
- このコマンドは、
v1 ブランチの3コミットと v2 ブランチの3コミットの間にあるペアごとの差分を表示する
- 1つ目のコミットは
diff(A, X)
- 2つ目のコミットは
diff(B, Y)
- 3つ目のコミットは
diff(C, Z)
interdiff 方式の実務上の効果
- GitHub が通常
diff(main, C) や diff(main, Z) のようなブランチ全体の diff を見せるのに対し、interdiff はコミットバージョン間の差分を見せる
- レビュアーは、すでに見た500行の API 変更を読み直すのではなく、修正された50行だけを確認できる
- 作者は
"address review" のようなノイズコミットを履歴に30個も積み上げずに済む
git blame は、より少ないノイズで元の変更コミットへ行を結び付けられる可能性が高くなる
git bisect は、回帰を新しい API コミットのような、より意味のある単位として指し示せる可能性が高くなる
- 結果として、基本的な診断ツールの信号対雑音比が改善する
マージ戦略と rebase に関するメモ
- パッチのマージ戦略に関する説明は TODO のまま残されている
git rebase は、公開ブランチの上に他の人がコミットを積み上げることが期待される場合でなければ問題ない、という立場である
- interdiff レビューシステムは、より小さく、より早くマージ可能なパッチを促進する
- 5コミットすべての準備が整うまで待つ必要はない
- 前の3つが問題なく、後ろの2つにさらに作業が必要なら、3つだけをマージできる
- 目標は、人々が長期ブランチではなく main ブランチを基準に作業するようにし、複数のリモートブランチが互いに絡み合ってマージされる状況を減らすことである
- Linux カーネルのように、公開ブランチを他のリポジトリとマージしたり、別のブランチの上にあるものとして明示的に公開したりするプロジェクトもある
- Linux 開発者は、パッチシリーズを作って磨き上げる際に
git rebase を使える
- ただし公開ブランチを作成した後は、誰かのツリーにマージされる可能性があるため、force push はせず、新しいコミットを含む新しいブランチを作る
1件のコメント
Hacker Newsの意見
GitHubではだいたいこういう流れを使っているが、欠点は自分のやることが増えることと、共同作業者にとって直感的ではないことだ
それでも、レビュアーが自分のフィードバックだけが反映された差分を見られて、
git blameやgit bisectを壊さないという利点はそのままあるレビューのフィードバックを反映するときは
git commit --fixupでコミットし、pushしたあとレビューコメントへの返信にfixupコミットハッシュを残すPRが承認されてマージ直前になったら
git rebase --interactive origin/main --autosquashを実行してfixupコミットを元のコミットにまとめ、最後にgit push --force-with-leaseしてからマージするレビューが終わる前のforce pushには注意が必要だ。そうするとレビュアーが前回のレビュー以降に追加された内容を見られなくなる
ターミナルの自動補完にかなり頼っていて、
git reくらいまで打てば長いコマンドまで行けるが、やや無骨なので、この流れを支援して推奨してくれるツールがあるといい。とはいえGitHubに縛られているなら、これでも十分悪くないただし、gitの高度な機能をあえて学ぶような、規律あるエンジニアリングチームで実際に使われることが多い
~/.gitconfigに以下の設定を入れればいい[rebase] autosquash = trueそうすると以後は
git rebase -i origin/mainだけでfixup/squashコミットが自動的に並べ替えられる。小さな設定だが、作業フローは大きく良くなった複数ブランチが載ったコミットシリーズをrebaseするときに
--update-refsが必要になるのと似た領域だ。人間がグラフ関係を追跡してコミットを手で入れ、ブランチを動かさなければならないのはなぜなのかと思う。コンピュータはグラフの扱いが得意なのだから任せればいいgit absorbもあるが、Saplingの実装ほど堅牢ではない[1]本当の問題はインタラクティブrebaseかどうかではなく、たいていはレビュー ツール自体のユーザー体験と、それが生み出す循環構造にある。たとえばfixupコミットでは、GitHubが基準点同士の差分を表示する問題を解決できず、基準点が大きいとレビューを完全に台無しにしうる。たとえば新しいコミット10個の上にrebaseした場合がそうだ
Git自体のUXにも不満はあるが、原文は主にGitHubへの不満に近い
[1] 2つの基盤アルゴリズムの違いを示す例は、このGitHub issueにある: https://github.com/martinvonz/jj/issues/170
このやり方が理想的だという点には100%同意する。GitHubのやり方は本当にひどく、あれを当たり前のものとして受け入れる人が増えすぎたのは悲劇だ
昔はPhabricatorでこうやっていて、すべてのレビューを一度に更新するコマンドラインマクロのおかげで、ある程度は手動で可能だった。それでも明示的なUIがあればなお良い
そう、そのとおり。頭の中で本来のコードレビューのスタイルとして思い描いていたのはまさにこれであって、GitHubのやり方ではない。名前が付いていると知れてうれしい
さらに、レビューシステムが、準備のできたパッチをレビューから「外へ」押し出せるといい。大きな機能を作業している途中で作った小さなバグ修正は、小さく独立したパッチであるべきで、レビュアーとも素早く合意できる可能性が高い
そうなれば、そのパッチを全体のシリーズから切り出してmainにcherry-pickし、レビューを新しいHEADの上にrebaseしたい。あるいは最新のパッチシリーズをmainの上にrebaseしつつ、合意済みのパッチを先頭に並べ替えてから、mainをそのパッチへfast-forwardしてもよい
要するに、レビュー対象を「まだ議論中の部分」に絞りつつ、バグ修正は準備できしだいマージされるようにしようということだ
反論としては「単に別のレビュー/PRとして作ればいい」となるだろうが、そうするとパッチセットAがパッチセットBに依存し、Bがマージされたあとはmainに依存する、といった複雑さが生じる
ここではAttention Setのような賢いUXのアイデアも一役買っている。基本的には「次の行動を取るべき人は誰か?」を示すもので、ターン制ゲームのように動く。自分が今しがたレビューしたなら、そのパッチのattention setにはもう自分は入っておらず、作者が入っている
だからGerritのUIでは、その項目は自分のキューの下のほうへ移動する。キューの一番上には、自分がattention setに入っている項目が来る。自然と仕事がそういうふうにまとまる
GitHub UXのほかの細かな苛立たしい問題までは触れていないが、pull requestの一覧ですら代替手段より劣っている。どの項目がどんな状態なのかわからず、結局は全部読まなければならない
一番下のxならそのまま送信して、残りは引き続き進められる
コードレビューへの新しいアプローチを見るのは、いつだって興味深い。GitHubにも利点はあるが、完璧にはほど遠い
提示されたシナリオなら、3つのパッチを相互依存する別々の pull request に分けることを考えられる。GitHub は標準では対応していないが、適切なコードレビュー ツールなら、pull request を小さく保ちながら依存関係を管理できるべきだ。たとえば、パッチ 3 をパッチ 2 に、パッチ 2 をパッチ 1 に依存させられる
ツールが提供する依存関係追跡のおかげで、必要ならそれらをまとめてデプロイされるよう保証できる
各パッチを個別にレビューすれば、フィードバックはより明確になり、対応もしやすくなる。pull request の中でコミットを squash して、個々の変更を正確に反映したきれいなコミット履歴も作れる。さらに、適切なツールなら AI で pull request とレビューを要約し、手作業なしで正確なコミットメッセージを書くことも簡略化できる
良いコードレビュー ツールは、rebase、merge、force push のような git 操作に振り回されるべきではない。裏でどんな複雑な git 操作が起きようと、レビュアーは前回レビュー以降の変更だけを見られるべきだ。そうすれば大きな diff を再レビューせずに新しい内容へ集中でき、レビュー履歴はコミット履歴と切り離されてきれいに保たれる
このように pull request を分けて相互依存を追跡するやり方で、要件を満たせるのか気になる
文字通り git が対応するよう設計されたワークフローであり、GitHub が pull request を備えて以来ずっと提起されてきた古い批判の核心だ
このアイデアが カレンダーを確認したところ 15年以上ものあいだ「メーリングリストの化石たち」のやり方としてこき下ろされ、今になってようやく流行の開発文化圏に入ってきたのはなぜなのか不思議だ
多くのソフトウェア開発者が、最もよく使うツールの1つをきちんと学ぶことを長らく拒んできたので、わざわざ悪いワークフローを選んでいるのだと思っていた。だから会社を git に移行するとき、そういうツールとフローを選んで作った。まあ、IBM を買ったからといって解雇されるわけではないし
外部コントリビューターがリポジトリの fork を使う場合、3つの PR はそれぞれ A、A+B、A+B+C を段階的に含むことになる。すると最後の2つの PR では、すでに別の PR でレビューしたコードまで diff として再び見る必要があり、レビューが難しくなる
各コミットは独立してレビューできる。コミット間の依存関係も追跡できる。AI が組み込まれていないのも良い点だ。PR と違って、コミット間の interdiff も見られる
コミットは Git の基本素材だ。素直にコミットを使えばいい
GitContext が、fixup、rebase、並べ替えのような操作を経たコミットをどう追跡するのか気になる
この記事を書いた本人です。何でも聞いてください
ついでに、ルール違反かどうかは分からないが、最近新しい仕事が必要になった。開発ツールや難しい問題に取り組むのが好きだ。この記事が気に入ったり、開発チームの生産性を高めたかったり、私のすばらしくて時々妥協的な趣味を体験して楽しみたかったりするなら、プロフィールにメールアドレスがある
真面目な話、履歴書は印象的だ。うまく、そして早く落ち着き先が見つかることを願っている。ごく最近の転職活動の経験からすると、今の採用市場は致命的なまでに病んでいる。よりシニアで経験が多いほど、狂った面接・HR 慣行や説明のない不採用で心がさらに削られる
友人が下のリンクを送ってくれた
https://danluu.com/hiring-lemons/
https://danluu.com/programmer-moneyball/
https://danluu.com/algorithms-interviews/
幸運を祈る
まだ触れられていない点が1つある。diff soup のせいで、人々が fixup コミットの「ノイズ」を消すために squash merge 戦略を好むようになるかもしれないということだ。すると最初の良い原子的な 3 コミットまで一緒に捨てられてしまう
interdiff レビュー スタイルなら、最初の 3 コミットは残り、それぞれを個別に取り込むか squash するかは、そのコミット自体と実際の原子性に完全に基づいて決められる
GitHub の苦痛を和らげようとする外部サービスもあり、stacked diff のサポートを提供しているが、かなり高価に見える。特に self-hosted Gerrit と比べるとそうだ。こうしたツールも検討したのか気になる
以前、MR シリーズのパターンをかなり簡単に組めた記憶がある。3 つの MR をマージすると、各 MR ごとに単一の squash コミットを持つ 3 つの merge commit ができた。MR のコミット履歴とは無関係だった
トレードオフは、レビュー中に前方のシリーズ ブランチが変わると、後方のシリーズ ブランチに再度 merge しなければならない点だ
それでもレビュー中は、コミット履歴を人々が好きなように扱える。どうせ squash されるのだから問題ない
ただ、やっていたのはかなり前で、最近は GitHub に縛られているので、美化された記憶になっているのかもしれない
Review Board [https://www.reviewboard.org] では、2006年の時点ですでに interdiff が作られていた。実際、その用語は自分が作ったか、独自にたどり着いたものかもしれない
今でも製品とコードレビューのプロセスでいちばん気に入っている部分であり、人々が GitHub のようなものへ移るときに最も恋しがる機能の一つだとよく聞く
fix-it コミットは、まともな代替手段だと感じたことがない
第一に、上位の変更がコミット列にどう反映されたのかを示してくれない
第二に、一時的であってもコミットグラフを乱し、レビューを難しくする。レビューを追い続けていた人は fix-it コミットが修正するコードをすでに読んでいるかもしれないが、新しく入ってきた人は、そのコードが何をしようとしているのかや構造がどうなっているのかについて、悪い第一印象から始めることになりかねない
第三に、誰もが Git や複数コミットを扱える構成管理システムを使っているわけではない。ゲーム開発では Perforce を、チップメーカーでは Keysight SOS のような特殊な構成管理システムを使うことも多い。そうした環境では fix-it コミット自体が選択肢にならない
きちんとした interdiff 対応のコードレビューシステムであれば、あるレビュアーは最初に公開されたレビューリクエストから全更新を追って変わった部分だけを見られ、別のレビュアーは最新の全体変更にそのまま入り、fix-it の連なりを気にしなくてよい。そしてこれは構成管理システムに依存せず実現できる
きちんと作れば、複数コミットから成る変更とも共存できる
たとえば、小さなプロジェクトをレビューしやすくするために API ハンドラー、フロントエンド UI、ドキュメントの複数コミットに分け、それらのコミットが密接に関連しているので一つのレビューリクエストとして出すのが適切だと判断することがある。相互の関連が薄いなら、依存チェーンとして複数のレビューリクエストにするほうが理想的だろう
レビューフィードバックに応じて、それらのコミットの一つまたは全部に対して一連の変更を加えることもできる。人々が更新をレビューするとき、fix-it コミットとその変更を対応する元の変更へ頭の中でマッピングするのではなく、各部分がどう進化したかを見られるほうがよい
だから interdiff は本当に素晴らしい。小さなコミットが多い場合でも大きなコミットでも、単一コミットのレビューリクエストでも複数コミットでも、もっと多くの人が使うべきだ
2013年ごろ、Glasgow Haskell Compiler は、冗談のように言われた「バグレポーターで .patch ファイルを読む」方式から Phabricator の利用へ移行した。理由はいくつかあったが、当時は stacked diff が理由ではなかった。GitHub はレビュー機能があまりに貧弱で、side-by-side diff すらなかったからだ。その理由だけでも完全に対象外で、ほかにも理由があった
しかし、コードレビュー用ツールへチームを移したのはそれが初めてではなかった。2009年の最初の職場は Houston の一室に集まったとても小さく結束の強いエンジニアチームで、他の人に自分のコードをレビューしてもらい、彼らが書いたものを読むことでコードベースをより深く理解できるはずだと思っていた
そこで入社後の最初の数か月、マネージャーに頼み込んで ReviewBoard を導入してもらい、みんな本当に気に入っていた
つまり RB には感謝しているということだ。今でも時々よい思い出として浮かぶ。そのおかげでコードレビューはほとんど初日から自分のキャリアの非常に大きな部分になり、今でももっとできると思っている
全体として、コードレビュー優先で rebase 中心の Gerrit のようなシステムのほうが、コードをずっとレビューしやすいと感じていた
最もよい点の一つは、複数パッチを積み上げる機能を標準でサポートしているため、人々がより小さくレビューしやすいパッチを作るようになることだ
GitHub のコードレビューは、質の悪い後付け機能のように感じられる。フォーラムスレッドのように見える無駄の多い UI や、rebase をまたいで追跡できない点などがそうだ
こうした「大きな絵」でありながら技術的でもある議論は、あまりにも頻繁にイシュートラッカーで行われてしまう。だが、どこに置くべきなのかもわからない。このスタックはあまりに一時的で、次の push で完全に変わってしまうかもしれない
こうした戦略を主張するのは何度か聞いたことがあるが、納得はしていない。自分が関わるほとんどのプロジェクトでは、feature branch は単一コミットに squash してマージし、ブランチ履歴は消している
筆者が説明したケースなら、リファクタリング、新しい API、更新をそのまま 3 つのコミットにするだろう
自分にとって確実に良い実践だったのは、長生きするブランチを避けることだ。こうした多段階コミットのシナリオは、たいていそこから生まれる。誰かが機能を数日、ひどいと数週間作業してから、一気に投げ込みたがるような状況のことだ
自分は毎日、あるいは1日に何度も main に移すほうをずっと好む。そのための方法の一つは機能フラグを使って、作業途中のコミットでも問題なく取り込めるようにすることだ。システムがきちんと構成されていれば、開発・ステージング環境で有効にしてテストできる利点もある。blue/green デプロイにも一歩近づく
大きなコミットをもっと簡単にレビューする方法は望んでいない。チームに、小さな変更を早く、頻繁にコミットするよう強制したい。全員が同意しないことは理解している
その理由の一つは、GitHub の PR と違って、スタックの一部だけを取り込めるからだ。記事の例でいえば、「小さなリファクタリング」diff の準備ができていれば、「新しい API」と「API 利用者のマイグレーション」diff を一緒に取り込まなくても先に入れられる
ブランチではなく コミット中心 にすると、長生きするブランチよりも各コミット全体が小さくなる効果がある
そうすると
git blameとgit bisectが事実上役に立たなくなるリグレッションがあれば、
git bisectは単一のパッチまで絞り込める。だから特定機能については、8000 行のパッチ 1 つよりも、160 行のパッチ 50 個が git の履歴にあるほうがよいあるコード行が怪しく見えたら、
git blameや連続したgit blameコマンドで、8000 行のコミットではなく、詳しいコミットメッセージの付いた 160 行のコミットにたどり着いてほしい元のコミット順も保持されるべきだ。数年後に個々のコミットメッセージを順番に読むだけでも、元の設計を理解する助けになることがある。もちろん元のパッチセットは依存関係の順に構成され、各段階でコンパイルできるなど、機能実装とは別の開発段階が必要になる。コードは論理的な段階で提示されるべきだ
興味深い。職場では、筆者がコミットを書くやり方で PR を作り、最後には実際に squash-and-merge している
ただ、このやり方だと前の PR を変えるたびに後ろの PR を rebase しなければならない。かなり面倒だし、「force-push 禁止」のルールにも引っかかるし、エンジニアが習得するのにも時間がかかり、GitHub UI 上の既存のコードレビューコメントを壊しがちだ。それでも 2、3 個の PR くらいなら何とか機能する
自分たちのフローでは、コミットは作業単位というより保存ポイントに近い
stash もよく使うし、Emacs の undo-tree-mode もよく使う。するとソースコード履歴を追う方法が 4 つになるが、重複しているようでいて実際にはうまく回っている
Git でこれを扱う 使い勝手 はかなり悪い。Phabricator のほうがまだ良かったが、それでも不必要に難しかった。もしかすると新しい構成管理ツールなら、コミットやブランチより高いレベルの概念を第一級でサポートできるのかもしれないし、そうすると逆にもっと使いにくくなるのかもしれない
Git より良いツールがあればいいか? もちろん、自分も欠点が少なくてもっとユーザーフレンドリーなツールが欲しい。だが当面の対処として、コミットをコミットとして扱ってみてはどうだろう。わざわざ自分で難しくしなくてもいい
GitHub が人々に PR 色の眼鏡をかけさせた責任がどれほど大きいのか気になる
jj,sapling,mercurialを見てみるとよいブログ記事は良かったし、コードレビューがどうあるべきかを実際に考えている人たちがいるのを見られてうれしい
それぞれ長所と短所のある 4 つのコードレビューシステムを多く使ってきた: Critique(Google 社内)、Gerrit(Google でも使ったが外部版と同じ)、GitHub、そして自分が作った CodeApprove だ
Critique は圧倒的に最高だったが、それが可能だったのは Google の monorepo と独自の構成管理システム、カスタム lint/test ツールに完全に最適化されていたからだ。CodeApprove はその長所をできるだけ GitHub に持ち込むよう設計したが、実際にそこまで近づくのは難しい
Gerrit はレビュアー体験の面では 2 番目に良かったが、作者の立場ではずっと嫌いだった。正しいやり方より間違えるやり方のほうが多いように見えたし、UI も特別美しくはない
GitHub は作者には非常に親しみやすく、自分たちが考える通りに動く。コードを書き、フィードバックを受け、さらにコードを書くという流れだ。PR の最後で squash and merge すれば、筆者が言う履歴の問題はない
しかしレビュアーやチームにはあまり親切ではない。増分 diff が強調されず、diff と会話が別タブにあり、force push と rebase が履歴を壊す。コメントは "outdated" として消え、diff 画面の外にあるファイルにはコメントできず、大きなファイルはデフォルトで隠されるなど、問題が多い。GitHub がこれをあまり気にしていないのは明らかで、もしかすると自分の知らない何かを知っているのかもしれない
結局いちばんもどかしいのは、多くのチームが構成管理プラットフォーム内蔵のコードレビューツールをそのまま受け入れていることだ。ノートPCに標準搭載された IDE をそのまま使うようなものだ。今はもっと良い選択肢がたくさんある。CodeApprove のほかに自分が気に入っているのは GitContext、Reviewable、Graphite で、そのほかにも優れた選択肢を 6 つは挙げられる。デフォルトを受け入れるべきではない
レビュアーやメンテナーは、コントリビューターよりずっと希少だ。ワークフローと UI は レビュー処理量 を最適化すべきだと思う
挙げられていた他の 3 つのツールは使ったことがないので、自分の主張は一般論だ