Gitの効用

2017.6.25 (日)

バージョン管理ツールとしてGitはかなりのスグレものであるのは間違いないのですが、使い方を間違っている人を何人か見てきたのでちょっとコメント。

Gitはアップローダーではない

Gitを使って作業をしている際にこのツールを完全にアップローダーだと思っている人がいるのです。いにしえの FTPアップロードを思い出せば事足りると思うのですが、どうやらpushしてファイルアップをしているようでした。世の中には様々なアップローダーがあります。JAVAベースのチームサイトとか何かはファイルを本番化する際のアップローダーであります。またアップローダーと似たような機能では「同期」させることもあります。環境依存するパラメーターのみ同期せずにその他のファイルは完全に同期させることで新しい機能を追加してゆくということになります。しかしこれらのアップローダーはバージョン管理とは実際はあまり関係がありません。Gitはアップロードが本来の目的ではないからです。(サブバージョンはアップローダーに近い感じはちょっとします。)
Gitは基本的にはローカルという開発環境が主役になります。ここでは割愛したいところなのですが、ローカルとリモートという概念自体を勘違いしている人も大勢います。ローカルが自分のPCでリモートがサーバーと思っている人はここでアウトです。たぶんGitを使いこなすことができないかもしれません。
Gitの醍醐味はローカルで開発を続けることができることです。しかも殆ど自由に行うことができます。どんどん開発をすすめてゆくわけですが、Gitは少なくともアップロードはしません。代わりにリモートリポジトリからファイルを引っ張ってくる、つまりpull(もっと本来的にいうと、fetch & mergeです。)してくることで本来的な能力を発揮します。ファイルをアップロードせずにpullしてくることが主流といいますかGitのコア機能になるわけですが、ここからがもっと面白いのです。

  • Gitは自分の書いたコードを勝手に消したり削除したりしない。 merge
  • Gitは他の人が変更したコードをファイル単位、行単位で履歴を残す。(勿論自分の作業も含めて)diff log
  • Gitはどんなに複雑な作業もいったん戻ることができる。 reset
  • Gitは誰にも影響を受けないところで作業できる。 branch

ということになります。
コンフリクトしたは誰々のせいだと怒っている人を私はこの人生で3人出会いました。彼等はそのコンフリクトの原因を作った人を探したりしていました。これはGitの使い方としても間違いだし何かしら根本的に勘違いしています。Gitは競合を解決するために上記4つの機能があるからです。
また「ファイルが何か変!」と提言する人もいました。これも間違いです。変である箇所はコミット履歴からすべて解析が可能です。しかもこのファイルを変にする原因になるあなたの手作業以外の機能はGitのオートマージのみです。かつオートマージはどこをマージしたのかを明確に示してくれます。何か変にしたのは自分以外の誰でもありません。
「チキショウ。やっちまった。」という人がいます。resetで戻ってください。元に戻ります。こまめにコミットすれば被害は最小限に抑えられます。
そして最悪なことに上記3つの勘違いをしている人はブランチを使えなかったりするので大変危険なのです。

Gitは団体球技に近い

Gitは複数人で開発する際にその才能を発揮します。勿論私も1人Gitをごく頻繁にします。特に新しいことをはじめた際にはその記録をGitにコミットしてゆきます。これがないと過去の自分の作業を整理することができないからです。だがしかしです。複数人で行う作業にその最大の能力が理解でき恩恵を最大限に受けられるのです。
私はバスケットボールをしていましたが、Gitはバスケットボールによく似ています。ゴールとデプロイは殆ど同じ意味です。ボールを持っている人がorigin/masterかもしれません。ですが、origin/masterにしか目を向けないという選手はいないはずです。ボールをもっていない人の動きが得点につながるからです。
statusでコート内のすべての状況を確認するでしょう。addでフェイントをかけるでしょう。またここでほぼほぼ誰にボールを渡すのか、どういった運びにするのかという予想をつけるでしょう。commitで実際に行動に移すでしょう。パスをするかもしれません。ドリブルで進むかもしれません。ドリブルで進んでバックパスをするかもしれません。優秀な選手はこの状況をパターン化して解析し暗記します。同じようなパターンは見抜かれます。選手はcommit履歴、つまりlogを再度見て確認します。この作業をものすごい複雑に行います。masterと思われる主力選手にボールを運ばせながら、ときとしてサイドにボールを放り込んで相手を翻弄します。branchです。翻弄しつつも最終的には主力選手にボールを戻して得点につなげることがあります。mergeです。いやしかし、主力選手に相手をひきつけつつ、身長や体格に恵まれない選手がすきをついてゴールしてしまうこともあります。rebaseです。バスケットボールの動きはGitの動きにとてもよく似ています。
スピーディにどんどん進みます。

Gitの開発は散漫でもいいけどcommit時はまとめる

Gitでの開発は自由でよいのです。私もいろいろとあっちゃこっちゃ手をつけます。コメントアウトしたままにして自分にはわかりやすいようにしていたり、あとで使うかもしれないコードはコメントアウトしてそのまま残していたりします。メールの送信機能を作っている最中にCSSをさわりたくなるときもあります。モデル部分に手を入れている最中にもっと上位のAdstructに手を入れたくなるときもあります。ですが、commitはその機能、そのまとまり、その文脈でまとめて行ってください!そのためにaddというコマンドがあるのです。散漫な方は「git add -A」は使ってほしくないのです。機能ごとにコミットをまとめるのがコツです。これはどうしてそうなのか?
コンフリクトは機能単位(つまり要件定義の単位)で起こるべきであって、散漫で中途半端な機能、または作りかけで起こしてはいけないものなのです。コミットには非常にセンスが必要なのです。
最後にコミットコメントは機能に対する意味のある言葉でなくてはなりません。

リモートリポジトリはリモートリポジトリ

リモートリポジトリはテストサーバーではありません。なので、テストサーバーにファイルを反映させるにはpullするか、イベントフックでpush後の処理を書いてあげたりする必要があります。(誰かが書いたイベントフックに慣れているとそれがgitの機能だと勘違いする人も少なくないです。)
リモートリポジトリはいわば履歴のバックアップであり、開発環境の中心ではないのです。Gitは分散型の開発システムなので、つまり、リモートリポジトリが消えてなくなったところでたいした痛手にはならないようなシステムになっています。リモートリポジトリは再び作成してHEADをpushしてやればよいことなのです。リモートリポジトリをGit開発のコアに位置づけている方々は多くおられますが、たぶんちゃんとGitの恩恵を得られていない可能性があります。