gitの良さがいまだに分からない
ここ2年ぐらいで俺が働いた現場はみんなgitを採用している。就職エージェントと面談するときもgit経験の有無をよく訊かれるし、今ではVSSやCVSどころか、SVNですら時代遅れになってきて、SVNを使っている現場は「レベルが低い」「保守的・旧態依然」という雰囲気すら感じる。
俺としては4-5年前からgit(GitHub)を使っているし、gitを使うこと自体に抵抗はない。一通りの基本操作はできるし、人並みにはできると言っても差し支えはない。
…が、正直gitの良さがあまり見えてこない。
もし俺が中規模以上のプロジェクトのリリースを本格的に管理する側であれば全然違った感想を持ったかもしれない。でも一人の開発者として、せいぜい10人程度のプロジェクトで利用する限り、「gitで良かった」という状況があまり思い当たらない。
ではgitの何が気に食わないのか書いていきたい。
git
イシューごとにブランチを切り、ローカルでコミットして、リモートブランチにpush
して、GitHub・GitLab・Bitbucket経由でマージリクエスト。コードレビューの後にマージ。
SVN
リモートのtrunkに個々人が直接コミット。コードレビューはあまりない。ブランチを切ることもない。
このような違いが出る背景には次のものがある。
- gitを採用する現場は、猫も杓子もgit-flowというプラクティスに従う傾向がある
- gitを採用する現場は、コードの品質もある程度管理する傾向がある
- SVNは集中型でありブランチ機能などが非常に使いにくい
- SVNを採用する現場はコードの品質よりも「リリースに含めるならさっさとコミット」と考える傾向がある
①gitは馬鹿には難しい
もっと丁寧な言葉で言うと「gitは学習コストが高い」となる。
このブログを読んだ奴から「gitの良さを理解できないのはお前が馬鹿だから」という意見が出てもそれは分かる。卑屈ではなくて、それは素直に事実だと思う。でもこの業界には、俺より頭の悪い人、俺以上にgitを理解しておらず、理解しようともしない人がザラにいるのだ。
プロジェクトのメンバーで「gitの経験は有ります!」と豪語していた奴から翌日「Permission denied (publickey).fatal: The remote end hung up unexpectedly
と出ます。教えてください。。。」というメールが来るなど、導入障壁からして低くないようであるが、そもそも「分散リポジトリ」という仕組み自体が完璧には受け入れられていないように思う。
ある日、同僚が社内チャットで突然こんなメッセージを残した(原文ママ)。
この同僚は技術力もないのに仕事を抱え込んではイライラを表に出していて、できるだけ関わりたくなかったが、当時奴が作業しているリポジトリにマージリクエストを出していたのはメンバーで俺だけだったので、嫌々ながらも話しかけることにした。
馬鹿からは返事が来なかった。よってその場は、謎のまま終わった。
しかし、その後、全員が集まるミーティングの場で彼は俺に対して直接要求してきた。
なんとこの馬鹿は、俺のブランチから出して放置されてるマージリクエストが、奴のブランチから出したマージリクエストとコンフリクトしているため、俺の方を取り下げろと言っているのだ。あり得ないほど幼稚な勘違いにクラクラした。
そもそも自分の無知蒙昧からの勘違いで社内チャットで乱暴な台詞を吐いた挙句、説明を求めても無視するとはなんて奴だとは思ったが、俺は奴に比べたら大人なので、その場でやんわりと丁寧に説明し、解決方法も提案したところ「あ、そうなの?」とは言っていた。
この馬鹿は謝罪もしなかったが、それは別に必要ではなく次からは少しだけgitの仕様を理解してくれさえすれば良かった。しかし、残念なことにその後も全く成長せず自分の思い通りにいかないと直ぐ人になすりつけてきた。
例えば、彼は自分のコミットがコンフリクトしたまま無理やり俺と共用しているリモートブランチにpush
した挙句、少し経ってから俺に言ってきた。
どうやらコミットログの読み方すらも分からないらしい。
再び丁寧に「123abc
で入ってるから、そちらのコミットで入ったんですよ」と教えてあげたが、知能に問題があるのかそれともプライドが高いのか、その後反応がなくなった。仕方ないので俺がわざわざ解消してやった。
彼は齢にして30代中盤らしくあまり技術的なセンスは感じなかったし精神的には無論子供だったが、エンジニアとしてある程度の経験と実績があるようで、その職場でも俺よりも勤務経験は長くて、俺よりも全然信頼されて大きなタスクを任せられていた。単価は月100万程度は有ったんだろう。このレベルの中堅技術者であってもgitは難しいのだ。
正直、俺のgitに対する悪印象の40%ぐらいはこの馬鹿のせいだと思う。
②コードレビューが常に必要になる
gitを採用する職場は猫も杓子もgit-flowに倣うので必然的にコードレビューを採用する。反面、SVNではそれほど多くはない。
コードレビュー自体を否定する訳ではない。その目的は「成果物の品質を担保する」「プロジェクト内でコードベースを共有する」などが挙げられる。
しかし、コードレビューのとにかく時間が掛かるという負の側面は本当に深刻な問題だ。実際、1つのマージリクエストのマージに数週間掛かるのはザラだし、下手すれば数ヶ月とか永久にマージされないという事も普通にあり得る。どうしても必要であれば催促すれば話は別だが、しかし常識的に全てのマージリクエストに催促できるはずもない。
どうしてレビューに時間が掛かるのか。概して他人が書いたコードを読むのは苦痛なのだ。また「マージは正社員のみが行える」と定めている現場も意外に多い。これ自体は形式的にも正社員にプロジェクトの責任を負わせたいという矜持溢れたポリシーだが、全ての正社員がコードを読める訳ではない。よってマージは遅れる。
はっきり言うとしっかりとした人間を採用していればコードレビューは大体が不要とすら思っている。エンジニアに信頼が有れば、コードレビューなんか「斜め読み」程度に留めて、よほど一目瞭然の間違いが無い限りは、さっさとマージした方がいい。最終的な動作の担保はテストフェーズなどで確保できるからだ。
にも関わらずコードレビューが有用(必要)となるのは、下記の1)、2)、3)のような状態である。
1) プロジェクトメンバーの中にとんでもないゴミがいて、誰かが監視しない限りクソコードをコミットされ放題になる。
2) プロジェクトメンバーが少数精鋭でレベルが高く、自分の担当外の分野に対しても積極的に踏み込んでお互いを高め合っていける。
3) 以下の全てとは言わずとも大半を満たす人がプロジェクト内に存在する。
- レビューに時間を割ける
- 「その実装が要件を満たしてるかどうか」を判定できるだけの仕様に対する理解が有る
- マージリクエストから(数日以内とは言わずとも)記憶が新しいうちにレビューを行える
- 言語やフレームワークに対して他人に指導できるぐらいの知識とセンスが有る
- その実装が短期的ではなく中・長期的にプロジェクトにどう影響を与えるかも予見できる
- カリスマと説得力、コミュニケーションに優れており、年齢やプライドだけは高いエンジニアに対しても柔軟に指摘を受け入れさせられる
1) については、恐らくコードレビューの有用性が叫ばれるケースは大半がこれを想定している。しかし、とどのつまり、これは採用プロセスでの過ちをコードレビュー導入で修正しているに過ぎない。OSSでない限り、プロジェクトのコントリビューターはそもそも限定できるのだ。また、仮に採用してしまっても、そのゴミの「解雇」という選択肢も有る。
2) は理想であるが、現実的にはそんな職場はあまりない。そもそも日本のIT業界において「良いコードを書こう」という文化自体が浸透しておらず、優秀なエンジニアというのは相対的に絶対的にも少ないのだ。Python、Scala、Goと言った人口も少ないが優秀な人間が集まっている言語ならともかく、C#やRuby、Objective-C、Java、PHPなどは玉石混交だから優秀な人を採用するには金を積む必要がある。
3) も極めて難しい。GitHubの有名OSSのリポジトリを見れば、多くのリポジトリ管理者達が、実は企業から雇われてマージリクエストをチェックしている事が分かる。彼らはそれで金を貰ってるのだ(しかも高給)。そんな彼らでも数週間、数ヶ月、数年(!!)単位で放置してしまうのだ。日本のSIerの社内SEが複数プロジェクトを掛け持ちしつつ、片手間にできる作業ではない。
コードレビュー導入は終局的には「コードはできるだけ書かない」という境地に至る。パラドックスにも思えるが、コードレビューを導入するとむしろコードの質が下がる事になる。ちょっとしたリファクタリングや機能の改善などがその典型例で、どうせコードを書いても放置されてしまうし、社員に催促するのも億劫だし…という事になるので、気軽に直せなくなる。
③利用者の負担が大きい
gitは本当に強力だ。たとえばSVNとは違ってコミットを履歴を汚さずに修正し放題だし、無かったことにもできるし、複数ブランチを切り分けて美しい開発フローを保てる。これは素直にgitの長所だ。何でもmasterに好き放題にコミットされていたSVNのログはどうしても「みす。。。。」「取り消し。。。」とかいうクソコミットで汚染されているのだから。
でもその分ユーザーの負担も大きい。ローカルリポジトリというワンクッションがあるゆえに、リモートのログは特に潔癖症のように扱われる。bitsect
の邪魔になるとかの理由もあり、リモートにマージしてもらうときは複数コミットはできるだけsquash
しろとか、グラフで美しいツリーを作るために適切にrebase
してくれとか「こだわり」を要請される事も多い。
しかし、言うようにgitを用いた開発ではマージリクエストの数週間放置はザラだ。だから一つのチケットAのマージリクエストを出して、別のチケットB、C、Dに取りかかろうとも、そのB、C、DがAを前提にしていることは珍しくもない。でもAからBを切ったら「ツリーが崩れる」と言われるし、Aでコードレビューを反映させてsquash
してpush -f
したら、B,C,Dも改めて修正しないといけない。
もちろん綺麗なツリーやコミットログを目指すのは結構だが、ここまで負担が大きいんじゃ無理に目指す必要なんてあるんだろうか。
④ローカルコミットやブランチ切替えにさほどメリットがない。
gitは分散リポジトリ制で、ローカルに自分のリポジトリがまず存在する。一つしかリポジトリのないSVNだと最後の最後まで行えなかったコミットが気軽にできること、また複数ブランチを一つのリポジトリで併行して開発出来ることはgitの大きな特徴でありメリットでもある、…と思っていたが、実はこれそこまで有り難い機能とも思えない。
まずローカルでコミットできても結局間違ってrm -rf
すれば電子の海にデータは消える。ローカルコミットはゲームのデータの途中セーブとは異なる性質のものだ。ある程度開発が進んでそろそろマージリクエストを作る直前までコミットできなくても問題はない。もちろん巨大なチケットに関しては、全ての変更を1つのコミットを含めるのではなく、複数のコミットに分割するというのも手だが、全ての変更を綺麗に適切にコミット単位に分割するというのは、それはそれで負担が大きいのだ。
また、同一リポジトリ内で、別のブランチに切り替える場合も大抵はコンフリクトするため、stash
したりと色々と面倒なことになる。もし本当に複数ブランチ(≒チケット)を同時に進めたいのであれば、物理的にリポジトリをもう一個clone
してきて「ディレクトリ:ブランチ=1:1」で開発した方が全然やりやすいと思う。そして、それなら普通にSVNでも可能だ。
⑤コマンドや操作があまり直感的ではない。
まあこのコマンド体系を考えた人間が誰なのかと思えば、我々は唯一神のご意向に従うしかないのだが、個人的にはgitのコマンドや操作方法に関しては数年使っても全然しっくりこない。例えば、ファイルの削除がgit rm foo.txt
なのに、ブランチ削除はgit branch -d hoge/fuga
とか。git rm -b hoge/fuga
じゃ駄目なのだろうかね。
gitを数年使っているし、ヘルプメッセージもヘルプもそれなりに充実しているのだが、結局いまだに何か分からない事があればググってしまう癖がある。
⑥git-completionとgit-promptはいい加減デフォルトにしろ
これは批判点というより要望なのだが、この2つがないとgitを使う気が正直起きない。どのディストリビューションでも環境構築をするときこれを自分で導入しているのだが、そろそろ標準でパッケージに含めておいて欲しい。
というわけで、gitはあまり好きではない。しかし、かといって今時SVNを採用している現場なんて色々とアレなところが多いだろうから、そこでも不愉快な思いをすることが多いだろう。そこにジレンマがある。