はじめに
RubyのコミッターでもありRailsなどの多くのOSSで活躍されているMarc-André Lafortune さんのブログに面白い記事があったので筆を取りました.
(許可は取りましたヨ)
*注釈 [...] で記された文章は原文には存在しない私の注釈であるので留意されたいです.
翻訳に至らない所があれば編集リクエスト待ってます.
要約
-
PR,feature単位でcommitをまとめるかどうかでRailsのプロジェクト上などで揉めた.
-
それぞれのcommitは独立してるいるはずだからまとめる必要はない
-
仮にどうしてもまとめたいなら自分でやるべきだし人にその考え方を押し付けるな
(まあ実際は皆いい人だから理解してくれるけど)
この方は徹底してcommitを最小の変更単位で分けて、
それぞれが独立してテストを通るように心がけている姿が印象に残りました.
(しないといけないと分かっていても僕は大きくなってしまいます... :(
以下翻訳
概要
私のpull requestに対して多くのコメントを頂ける事を大変感謝する一方で、中には少し理解に苦しむものもある.
私のコミットに対して(git merge --squash
などで)まとめろと言わないで欲しい.
*注釈 [上記のRailsプロジェクトのやり取りの中で「マージするからコミットをまとめてもらえる?」というやり取りがある. まとめるメリットはfeature単位、pull-request単位でコミットを1つにした方がそのfeatureやpull-requestに関する backport/revertが容易になる所にある.]
各プロジェクトのコミッターらの素晴らしい仕事に対して失礼ながら、私はコミットをまとめたいとは思わない. だから私にまとめろ言わないで欲しい.
例えば5つのコミットからなるpull requestがあったとして、もし私が何もミスをしてなければ、この5つのコミットはそれぞれ独立しているはずで、それらをわざわざまとめるべきでないと思っている.
もしどうしてもまとめたいならば各プロジェクトのコミッターは自分でやるべきで、
誰かがまとめるのを待ったり、はたまたrejectするべきでない.
私の主張は気が狂っているだとかエゴだとか言われるかもしれない、
が私は私のコミットをまとめたくない.
まあしかし幸いな事に多くのコミッターは私がこの提案を穏やかにしているためか、
攻撃的な態度を取る事なく受け入れてくれる.
私のコミットをまとめないで欲しい理由
私が思うに多くのcontributor達が歴史的な理由もあってgit
やgit rebase -i
をよく思わない事が主な理由で、彼らがコミットをそれぞれ独立させるのではなく、思いつくままにコミットを作ってしまう事がいけないのではないかと思っている.
例えばこんな感じ
- 素晴らしいfeatureを思いつき、手をつける
- しまったtypoしてた直さないと
- しまったバグを直さないと
- featureを仕上げる
この様なcontributor達がもし、そのままのcommitをpull-requestに出して、それが受け入れられない(つまりマージされない)という事は当然の報いだとは思うが、
多くのcontributorはgit rebase -i
とgit commit -p
を用いて修正をしている訳で、
この様なcommitは受け入れられるべきだと思う.
ほかの理由としてはここでも述べたが
もしコミットをまとめてしまうとpull-requestの一部に対するbackport/revertはむしろ複雑になってしまう.
もっと言えば、pull-request全体に対するbackport/revertもgit revert
とgit cherry-pick
を「コミットの範囲を指定」とするか「マージ済みのコミット」とすればそんなに大変ではないはずだ.
そもそもbackport/revertはそんなに頻繁に起こるものでもない(全体の2%以下)
どんな時にコミッターはコミットをまとめろと言うべきでないか
もしそれぞれのコミットが独立しているとしたら(つまりそれぞれのコミット、どの部分で切ってもテストが通る状態)まとめる必要はないし、まとめるなとさえ言うかもしれない.
私のコミットは往々にしてそれぞれ最小の変更でそれぞれがテストを通るような構成になっている.
中にはトリビアな変更が多く含んでいるなど例外もあるが(スペースの削除、多くのタイポの修正、変数名の変更など)まあそれでもdocのtypoの修正と変数名の変更を一緒にコミットしようとは思わない.
私はリファクタリングを行う時は大抵、小さな独立したコミットにする事を心がけている.
そちらの方が理解もしやすくマージなどの判断も容易いと思うからだ.
良い例がここにある.
これは一つのbugを修正するためのpull-requestだが私は15つのコミットに分けた.
それぞのリファクタ1つ1つはしかるべく順序で並んでおり、最後の1つだけがbugの修正それ自体なのだ.
こちらの方がコミットを1つにまとめられてdiffに多くの変更が一度に出てくるよりは、それぞれの変更に間違いがないか確認するのが容易である. これをまとめろというのは理解にくるしむ.
私は別に全ての人にこの様にコミット1つ1つに気を使って構成せよと言ってるのではない.
1つ1つ丁寧に分けられたコミットをそのままにしておけと言ってるだけだ.
もしこの考え方が理解できずあなたはコミットをまとめると主張しても、少なくとも他人がこの様な考え方を持っていたらの受け入れるように努力はすべきである.