1年目から身につけたい! チーム開発 6つの心得

第5章 情報価値の高いコミットをしよう―コードだけではわからない意図を伝える技術

この記事を読むのに必要な時間:およそ 9.5 分

間違えたコミットはrevertで取り消そう

開発を進めていると,メソッドを間違ったクラスに実装してしまったり,まだコミットするつもりではなかった作業中のファイルをコミットしてしまったりといった間違えたコミットが発生することがあります。また,試行錯誤しながらの開発では,試しに実装してみたものの,結果が芳しくなかったのでもとに戻したい,ということもよくあります。

Gitでは,以前のコミットを取り消す内容のコミットをgit revertで生成できます。たとえば直前に行ったコミットは,git revert HEAD^注10で取り消せます。

特定のコミットを取り消す場合は,git revert d3eadd6b231275dfb7bf0b11d9fc1d3b6321c3d1のようにコミットIDを指定します。コミットIDはgit logなどであらかじめ確認しておきます。

git revertを実行すると,通常のコミットと同様に,エディタが起動してコミットメッセージを編集できる状態になります。通常のコミットと異なるのは,どのコミットを取り消すコミットであるのかを示す図6のようなメッセージがあらかじめ入力された状態になっていることです。

図6 変更を取り消すコミットの既定のメッセージ

Revert "Add a feature A"

This reverts commit d3eadd6b231275dfb7bf0b11d9fc1d3b6321c3d1.

このままコミットしてしまうこともできますが,単に「~のコミットをrevertする」というメッセージでは,ほかの開発者が読んだとき,なぜそれが間違いであったのかを知ることができません。図7のように,変更を取り消す理由をメッセージに加えておきましょう。

図7 変更を取り消す理由を追加したコミットメッセージ

Revert "Add a feature A"

This reverts commit d3eadd6b231275dfb7bf0b11d9fc1d3b6321c3d1.

Because it conflicts with feature B.

コミットに成功したら,最後に,共有リポジトリに変更を反映するためにgit push originを実行します。これで,コミットの取り消しは完了です。

revert「指定されたコミットで行われた変更をまたもとに戻すコミット」を自動的に行う操作です。ですので,コミットログには「間違えたコミット」「それを取り消したコミット」の両方が記録されることになります。

注10)
HEAD^は1つ前のコミットを指します。なお,HEAD~NでN個前のコミットを指すことができます。

良いコミットをすればコミットログを活用できる

バージョン管理システムにはさまざまな機能がありますが,それらを活用するためには良いコミットを行う必要があります。どんなにコードそのものがきれいでも,コミットのしかたが良くないと,バージョン管理システムの真価は引き出せません。

コミットログは見返すためにある

適切にコミットメッセージが書かれていると,新バージョンをリリースする際の「前のバージョンからの変更点の一覧」を作成する作業が簡単になります。

バージョン番号を付与して新しいリリース版を提供するときには,前のバージョンから何がどう変わったのかを説明する必要があります。適切なコミットメッセージによって情報価値の高いコミットログになっていれば,コミットログからコミットメッセージを収集してくるだけで,それがそのまま「新しいバージョンでの変更点の網羅的な一覧」となります。

行単位でのコミットログで原因を調べる

行単位でのコミットログもまた,さまざまな場面で役立ちます。

たとえば,ある行が不具合の原因であるとわかったとき,そのコードを削除してもよいかどうかはどうすれば判断できるでしょうか? 一見すると奇異なコードでも,実はとても重要なコードで,それを削除するとほかにも大きな影響を与えてしまう,ということはよくあります。そのような場合,毎回すべての影響範囲を調べるわけにもいきません。

コミットメッセージが適切に書かれていれば,この場合,行ごとのコミットログが手がかりになります。Gitのリポジトリであれば,git blamegit showというコマンドが役に立ちます。blameはあるリビジョンのコードについて,行ごとにそれがどのコミットに由来しているのかを表示する機能です図8注11)⁠

図8 git blame

図8 git blame

これを使用して障害の原因となっている行が導入されたコミットを探し出し,git showでそのコミットメッセージや差分を読むことで,⁠一見すると奇異なコード」「どういう理由で導入されたのか」を知ることができます。調査の範囲を絞り込むための大きなヒントとなるでしょう。

しかし,情報価値の低いコミットメッセージや,複数の変更が混ざった大規模なコミットが多いと,行ごとの変更履歴は活用しにくくなってしまいます図9)⁠

図9 コミットログの情報価値が高いと,さまざまなことを

図9 コミットログの情報価値が高いと,さまざまなことを

注11)
コーディングスタイルを揃えるためのコミットが多い場合は,-wオプションを指定してgit blame -w path/to/fileとすると,空白文字のみのコミットを除外できます。

放っておくと実装が肥大化してしまうように,コミットも放っておくと肥大化してしまいがちだね。⁠コミットの単位でコードを管理できる」というバージョン管理システムの利点を有効活用するには,良いコミットが欠かせないんだ。良いコミットを重ねてこそ,リポジトリは利用価値の高い宝の山になるんだよ

僕,コミットログって今まで見たことなかったです。もっと活用していかないともったいないですね……!

COLUMN 間違いを取り消すためにgit push -fしてはいけない

Gitでは,⁠コミットを取り消すコミットをする」以外に,⁠コミット自体をなかったことにする」こともできます。そうしてコミット自体をなかったことにしたうえで,操作を強制的に行う-fオプションを添えてgit push -fとコマンドを実行すると,ローカルリポジトリの内容をリモートリポジトリに強制的に反映して,⁠間違えたコミット」の痕跡を完全に消してしまうことができます。

しかし,原則としてこの操作は複数人で作業している共有リポジトリに対して使ってはいけません。リポジトリを破壊してしまう恐れがあるからです。

通常,git pushはリモートリポジトリ側に新しい変更があった場合,先にそれらをpullしてから再度pushしなおすように警告して,処理を中断します。しかし,git push -fは一切の確認なしに変更を反映します。もし仮にリモートリポジトリにほかの人が何か変更をコミットしていても,それらはすべて失われてしまうことになります。

このようなトラブルを避けるためにも,コミットの取り消しは必ずgit revertで行うようにしましょう。

著者プロフィール

足永拓郎(あしえたくろう)

株式会社クリアコード所属。デスクトップや組み込みソフトウェアの自由を求めて活動中。


結城洋志(ゆうきひろし)

株式会社クリアコード所属。Firefox黎明期からアドオン開発を手がけ,業務上もMozilla製品の技術サポートを担当。代表作は「ツリー型タブ」「テキストリンクなど。また,日経Linux誌にて「シス管系女子」を連載中。


林健太郎(はやしけんたろう)

株式会社クリアコード。趣味であれこれと,Sylpheedのプラグインを開発したり,Debianのパッケージをいくつかメンテナンスしている。

Twitter:@kenhys

コメント

コメントの記入