なぜVCS(Version Control System)を使うのかを考える

# はじめに
gitこわいみなさんこんにちは！

チーム内ではgitおじさんとして日々活動しています。意外と(?)git苦手なひと多いですよね。最低限の操作はできても、何のために、どのように使うのが適切かを意識しているひとは少ないと思います。

本記事は自分のチームに向けて、なぜgitを使うのか、どんな使い方が適切かを理解してもらうために書きます。

# なぜVCS(Version Control System)を使うのか
なぜ使うのでしょうか。まずはここから考えていきます。

ちょうど最近読んだ[ベタープログラマ](https://www.oreilly.co.jp/books/9784873118208/)に``効果的なバージョンコントロール(p179)``という章があります。そこを見て考えてみましょう。

## 使いなさい、さもなければ失われる(p180)
>開発者にとってバージョンコントロールは、食事したり呼吸したりするようなものです。(p179)

本書ではここまで言い切っています。

>バージョンコントロールを使ってください、使わないという選択はありませんし、あればよいというツールでもありません。開発の基盤です。それなしでは、成果物は危険にさらされます

この点に疑問を持つひとは少ないでしょう。VCSの必要性は**なんとなく**理解しているはず。

では、VCSを使うと何が嬉しいのでしょうか？（〜するとうれしいの？はエンジニア特有の問いみたいですね。)

### 開発者の共同作業のハブ
> 開発者達の共同作業を助け、その中心となるハブを提供します。(p179)

ソフトウェア開発を1人ですることはほとんどありえません。具体的にはブランチという概念によって開発者達の作業を分散し、並行して動かすことができます。

### ソフトウェア考古学を可能にする
> 特定の機能を実現した変更を知るためにファイル内の変更を調査するという、ソフトウェア考古学を可能にしています。個々のファイルを誰がどのような理由で変更したかを記録しています。(p179)

**ソフトウェア考古学**という言葉が本書ではよく出てきます。言葉通りなのですが、どのように変化してきたかを後から辿ることの喩えです。

ソフトウェアは変化し続けます。関わるひとも変わり続けます、VCSなしにどうやってその変化を追うことができるでしょうか。

後述しますが、変化を追うためには、gitを適切に使わなければいけません。

### 開発者へセーフティネットの提供
> 開発者にセーフティネットを提供します。実験したり、変更を試したり、そして、動作しなかった場合に変更を戻したりできます。(p179)

これは逆に言えば、ソフトウェアは本質的に安全ではないことを言っています。たった１行、いや、たった１文字違うだけでうまく動かないかもしれない。僕はソフトウェア開発の最大の的は**不安**だと思っています。その不安をVCSは取り除いてくれます。

> ソフトウェアは本質的に安全ではありません。ディスク上のソースコードはデジタルの煙のようなものです。すべてを消し去ることが簡単にできます。私は、誤って決してしまったり元に戻すチェックポイントがないまま間違いを犯したことは数え切れないほどあります。バージョンコントロールは、そのようなことを防いでくれます。きちんとした軽量なVCSは、小さくて頻繁なチェックインを推奨しており、あなたの愚かな行為に対する重要なセーフティネットを提供します。(p180)

私がgitを好きになったのは、変更の不安を、**いつでも戻せる**という安心に変えてくれる点に他なりません。

cpコマンドでバックアップを取る、確かにそうすればいいかもしれません。でもその操作は間違えるかもしれないし、忘れるかもしれない。``git checkout``コマンド一発で安全な状態に戻せることがどれだけ私を安心させたかわかりません。

ベタープログラマに頼りきりですが、VCSを使う理由は単純なソースコードのバックアップ以上のものがあると思います。私たちはVCSなしにソフトウェア開発はできないでしょう。

## PR(PullRequest)/MR(MergeRequest)とcommitの粒度を考える
さて、VCSを使うことは大前提として、VCSをどう使うか、つまりcommitや、github/gitlabの機能であるPR/MRの粒度について考えてみたい。

なお、いずれもこれが答えというものはないので悪しからず。

## PR(MR)の粒度
リポジトリ(チーム)の方針に従うが、おそらく機能単位になるでしょう。issueが切られる単位。必ずしも外部仕様の1機能の変更に限らず、別にリファクタリングというPRがあっても良いと思います。

ある関心のある変更のひと塊であり、チーム内でポリシーを決めておくといいですね。リリースの最小単位と考えてもいい。

## commitの粒度
PR(MR)よりは少し範囲が小さくなります。ベタープログラマに言わせると``アトミックなコミット``です。

> アトミックな(これ以上分けられない最小の)コミットを行ってください。そうすれば、理解するのも、正しいかを調べるのも容易です。これは、小さく頻繁にチェックインするという戦略です。(p185)

これをよく私は**論理的に意味のある塊**でコミットして、と言っています。補足するならば、**論理的に意味のある、単一種類の変更**でしょうか。

もっとゆるく言い換える**変更に気をつかってください**になります。

### @jnchito さんの記事
qiitaのcontribution数が怪物級の伊藤さんがすでにこの問いについて考えてくれています。見てみましょう。

[【初心者向け】「コミットの粒度がわからない問題」の模範解答を考えてみた](https://qiita.com/jnchito/items/40e0c7d32fde352607be)

動画も見ましたが、なるほどなーと思ったのは``正常に動く単位にする``という点ですね。

これは``コミットはドラクエのセーブと同じ``と相反するかもしれません。

自分のlocalの作業用ブランチは1日の終わりにセーブでいいと思います、これ自体は間違いではありません。

ただ、やはり複数人で開発する場合、あとで追いかけることを考えると、論理的で最小の変更単位であることが望ましいと思います。

また、``チケット単位、または戻したい単位でコミット``であるように、前述したPR/MRの単位で1コミットにすることを求められることがあります。これはそのソフトウェアのコミュニティによるものです。

この粒度を一般的に語ることができない(からこそ伊藤さんの記事でも結論に至っていない)のですが、なるべく他の挙動と独立した1つの変更単位でコミットすることを心がけたいですね。

### そのcommitは後かどう使うのか
なぜコミットの粒度にこだわるかというと、それはあとから使うからですよね。どうやって使うかというと

* ソフトウェア考古学的に追いかける
* cherry pickする

ということを思いつきました。

上記の場面から考えても、ある機能が正常に動く単位の塊であることが理想だと思います。

## commit messageの内容を考える
ついでにコミットメッセージについても考えてみましょう。

**論理的に意味のある、単一種類の変更**であるならば、メッセージもシンプルになるはずです。

> 個々のコミットには、きちんとしたチェックインメッセージを書いてください。理想的なチェックインメッセージは、何を変更したかを簡潔で明瞭に述べた概要の一文で始めるべきです。その後に必要であれば変更を行った理由を続けてください。適宜、バグの参照番号や他のサポート情報を含めてください(p185)

これに尽きますね。簡潔の1つのメッセージの言い切りからはじめ、変更の詳細ではなく**変更の理由**を書くことが重要です。変更内容はコードをみればわかりますからね。なぜ変えるのか、のほうがコミットメッセージにしか残らない情報になります。

関連するチケットトラッキングツールやリリース管理ツールがあれば、その番号を書くことでより追跡可能性が増すでしょう。

# おわりに
本テーマは、gitを愛する身として、一度考えてみたかったテーマでした。

gitを使う人間がもっとも着目すべきは変更です。その変更がどういう**意図**で、どういう結果をもたらすかに常に気を配らなければいけません。それぐらいソフトウェアは危ういものなんでしょう。

**論理的に意味のある最小単位**のコミットをすること。レビューワーに分かりやすいよう、機能単位でPR/MRを作ること。心がけましょう。