3人のgit初心者 - The git beginners of three -
イントロダクション
もう一週間も前のことになる。社内を歩いていたところ、行き倒れていた新入社員をうっかり踏んでしまった。
「おっと失礼。それにしても、どうしてこんなところで寝ていたのですか?」
わたしがさし出した手をとりながら、新入社員氏はこう答えた。
「寝てはいません。実は、gitの学習に躓いて転んでしまったのです。私がIT業界に来たばかりの、ずぶの素人であることはご存知ですよね?」
「ええ、それについては。確か某大学の音楽部ヨーロッパ古典管楽器科ルネサンス期専攻のクラシック・ビオラ奏者で、ドボルザークを研究していたのでしたか」
「私は文学部です。記憶力は大丈夫ですか? それはともかく......」
「私がわかることで良ければ、説明しますよ。mergeとpullの使い分け? CRLF改行に関する設定? .gitディレクトリ内でのコミット履歴の保存フォーマットについては、私から説明できる自信はないなあ...」
「いえ、そういうことではなく」
「では何が疑問なのですか?」
「gitとは一体何なのでしょうか?」
バージョン管理システムだよ、という答えを求めているわけでないのは明白だった。
「私は入社してから昨日まで、C言語でfizzbuzzプログラムを書いていました。fizzbuzzプログラムのためにMakefileも書きました。今日、新しい課題として、gitを学ぶように会社から言われたのですが、gitが何のために存在して、なぜわたしがgitを学ぶよう指示されたのか、いまいちピンと来ないのです」
なお、うちの会社は50人に満たない小さなIT企業で、決まった形での新入社員研修が無いから、新入社員は出された課題をこなしながら独学することになっている。
「なるほど。確かにそれはもっともな疑問です。ソフトウェア開発の経験を積まないと、バージョン管理システムgitの必要性を理解するのは難しいでしょうね。そういうことでしたら、わたしが口頭で説明するよりも、これからちょっと、残り2人のgit初心者に話を聞きに行ったほうが良いように思います。社長に許可を取って、これから少し出かけましょう。上手くすれば今日は直帰できるかも」
「あ、あとgitのインストール方法もわかりません」
「gitのインストール方法については、あとでgoogle検索というツールの使い方を説明します」
おひとりさまのgit
ある大学の研究室に行くと、髪の毛がボサボザで細身のギーク、研究よりも趣味のブラウザミニゲーム・コードをJavaScriptで書いているような大学生が、壊れたソースコードを前にして癇癪を起こしていた。
「まあまあ落ち着いてください。君の書いた3本目のゲーム、猫が100万回転生しながら地球侵略している宇宙人を皆殺しにするゲーム『All Nyan cat need is kill』は無くなってしまったわけではないのですから。ハードディスクが壊れたわけではないのでしょう?」
「ハードディスクって何?」大学生は首をかしげました。「確かにソースコードは無くなっていないよ。おれのMacは壊れたわけではないから、SSDにしっかり残ってる。でも、おれの作りかけの3作目のゲームだったJavaScriptコードは、今や何の役にも立たないゴミに変わってしまったんだ」
「もしかして、新しい機能を追加したら、さっきまで動いていたゲームが動かなくなってしまったのですか?」
「そうさ!」
「すばらしい! ......おっと失礼。あまりに都合のいいシチュエーションにいきなり出会えたものですから。やはりジョエル・スポルスキ氏の書くことは的を射ているなあ」
「ジョエル.....誰? まあいいや。それより開発履歴バックアップのフォルダからまだ動いていたゲームを復元して、もう一度、Nyanの軌跡に描かれる虹の色をカスタムできる機能を実装しなおさないと。」
「バックアップ! さらにすばらしいですね。バックアップはもしかしてDropbox上に置いてあるのでは?」
「そうさ。おれのDropboxは、友達みんなに登録してもらったから、無料で5GBまで使えるようになってる」
「開発はDropboxの外でやっていますね? 履歴からの復元には頼っていないのでは」
「その通りさ。Dropbox内で開発をやっていたら、履歴があっという間に編集で一杯になってしまうからね。それに、履歴が残りやすいように作業していても、Dropboxの履歴はいつ消えるかわからない。うっかりミスをやった際にはありがたい機能だけれど、プロジェクトのロールバック機能として頼るには心細すぎるよ」
「これは断言しても良いのですが、バックアップは、日付を付けたディレクトリになっていますね?」
「惜しいけれど、ほぼそのとおり。おれのDropboxフォルダの中にある、『AllNyanCatNeedIsKill 2017-03-12 14:33』が最新版さ。5GBはすぐに使い切ってしまうから、古いほうから優先で、歯抜けになるようバックアップを消して容量を空けているんだ」
「かなり手練れていますね。手動バックアップについての手痛い経験を、よほど積んだのではありませんか?」
「どうかな。第一作はとにかく勢いだけで作ったんだ。ついさっきまで動いていたコードを再び動くよう直すのに、まる3日悩んだりさ。それで、いつでも前の作業に戻れるよう、バックアップフォルダを作ることも覚えたんだ。
第一作を作っている途中で、親から貰ったラップトップが故障して、危うくすべてを失いかけたんだ。その時は偶然、友達に見せるつもりでUSBにコピーを作っていて助かったんだけどね。この事件がきっかけでバックアップの重要性を理解して、Dropboxを使い始めたのさ。
第二作では沢山作ったバックアップフォルダの『ゲーム2_丸12』とか『ゲーム2_最新版』『ゲーム2_最新版バックアップ』のうち、どれが直前のバックアップかわからなくなった。思い出せないから何個もあるバックアップを全部見てみる羽目になった。バックアップの管理はルールを決めてやらないと駄目だと思い知らされた。でもおかげでdiffコマンドの使い方を覚えたよ。
ああついでに、ファイル名に丸に囲まれた数字のような『環境依存文字』や、日本語のような『非ASCII文字』を使うと、いざという時に面倒だってこともね。
今では、毎日、新機能が追加される毎にディレクトリ全部をコピーしてバックアップを作ってる。バックアップディレクトリの名前はルールを決めて付けてるから悩むこともないよ。」
「なるほど。JavaScriptには慣れましたか?」
「もう2本もゲームをJavaScriptで書いて、いま3本目を書いているからね。最初はwindow.onloadの扱いもよくわかっていなかったけれど、今ではWebでサンプルコードをまったく見ない状態でも、息をするようにsetTimeoutのトリックで擬似マルチスレッドを実装できるし、マウスコールバックの関数を書いて画面のNyanを自在に動かすこともできるよ」
「では手動バックアップも簡単?」
「まあ稀に忘れてしまうこともあるけれど、今はもう息をするよりも簡単さ。バックアップを取りながらヘソでコーヒーを沸かすことだってできるね」
「手慣れていらっしゃいますね」
「手に馴染むくらい繰り返しゲームを書いてきたからね。実はもうそろそろ、バックアップフォルダ作成を自動化するbashシェルスクリプトを書こうかと思っていたところなんだ」
「そういうことでしたら...ソースコードを書くことやプログラムを開発することに慣れて新しいことを覚える余裕があり、自前のバックアップ手順が確立するほどバックアップの重要性を認識しており、何よりソースコードを管理したい本物のソフトウェアプロジェクトを抱えている、そんなあなたにはgitを覚えることをおすすめしますよ」
「うーん、gitか。実は、第一作のゲームを作り始めた時に、いろいろ調べたんだけれど。なんかよくわからなかったんだ。他にもVimとかbabelとか、アプリケーション開発って、覚えることが多すぎると思うよ」
「そうですね。Web系は特に多い。最低限でもクライアント側にHTML、CSS、JavaScriptが必要で、サーバを持つならPHP、SQL、そしてシェル...」
「さらには気が遠くなるほど多くの依存関係で絡み合ったJavaScriptライブラリ群、さ。おれはサーバは持ってないよ。セーブデータはcookieだし、デプロイはさくらのサーバにFFFTPでプロジェクトディレクトリを全部アップロードしてる。サーバ管理に必要なシェルコマンドを覚えたくなかったんだ。
gitはディレクトリをまるごとコピーするバックアップ手法よりも、ずっと覚えるのが面倒だと思う」
「ごもっとも」わたしはうなずいた。「一人で開発するソフトウェアプロジェクトでは、gitとよく管理されたバックアップディレクトリの間に、大きな違いは無いとわたしは思っています。
わたしも最初はディレクトリコピーでバックアップをとっていました。『ゲームが作りたいならJavaScriptより先にgitを覚えるべきだ』などと荒唐無稽な主張をするつもりはありません。
でも、今のあなたは、gitを覚えることで、いくつかの小さなメリットが得られますよ」
「ふうん。どんなメリットがあるの?」
「プロジェクトをバックアップした時点の状態に戻したくなったとき、作業が手作業より簡単かつ確実です。
すべてgitが覚えているので、手作業よりもバックアップのミスが減るはずです。
コードが動かなくなった時、前のcommitからの変更点が怪しいわけですが、gitならこの変更点を簡単に確認することができるので、デバッグが楽になります。
プロジェクトを失てしまった場合の備えとしては、githubという優秀なホスティングサービスがあって、個人で使う分には、履歴をすべて保持したまま、容量を気にする必要がないほど大きなフリースペースを利用できます」
「そんなに昔の履歴なんていらないよ!」
「わたしもそう思います。実際、わたしも個人開発で、最新より昔の履歴を使用することはまず無いです。でも、空き容量を気にせずにすめば、それだけ開発に集中できますよ」
「うん、それはわかるよ。おれも、今日が何日だか思い出す手間を省いて開発を高速化するために、シェルスクリプトを書こうと考えているんだから。メリットはありそうだけれど、なにか、gitを始める上で注意したほうが良いことはある?」
「あまり難しい操作をしないことです。特に、履歴をバグなしのクリーンな状態に保とうなどと考えないこと。
履歴の操作は、リポジトリを壊すかもしれない危険な操作です。初心者がやるべきではない。初心者が履歴の改変に手を出せば、リポジトリは永遠に失われます。
自分が書いたプロジェクトのcommit履歴、つまりセーブデータ一覧が汚く見えたとしても、commitを整理したり、順番を変えようとしたりしてはいけません。
初心者は新しいファイルのaddとcommitを忘れがちですが、既にやってしまった過去のcommitミスをgitのテクニックで無かったことにするのではなく、次の新しいcommitで追加しましょう。
1つ前のコミットにバグがあったとわかったら、しれっと修正して、"fix fooのバグを修正"というメッセージでコミットすべきです。
初心者がgitを使うとき、必要最低限のコマンドは、そう多くありません。プロジェクトをcommitすること。コーディング中の作業をdiffすること。それを超えるとしても、せいぜい現在の作業を捨てて最新のcommitの状態に戻すことまでです。
gitリポジトリはサーバが無くても使えます。どうしてもサーバが欲しければ、自分でサーバを立てるより、githubにアップロードすべきです。
gitは、慣れればバックアップディレクトリより便利で高度な操作が簡単にできますが、新しい挑戦は、gitを使ったあなたの開発ワークフローに慣れてからにしたほうが良いと思います」
「他には?」
「もうひとつあります。最初はgitを信頼しないことです。正確には、git初心者であるあなたを、ですが」
「わかった。あなたはバックアップディレクトリを作っておけ、って言いたいんだ」
「そのとおりです。あなたはgit初心者なのですから、ローカルリポジトリを壊すことがあるでしょうし、復旧方法がわからないこともあります。そんな時に、プロジェクトとgitを一緒に捨ててしまう結果にならないためにも、gitの外側にバックアップを用意しておくべきです。
gitリポジトリが壊れたと思ったら、サーバからgit cloneするか、バックアップディレクトリをコピーして、新しいローカルリポジトリで作業を再開すればいい」
「それだけ?」
「大きな注意点はそれだけです。あとは、細かい注意点として、Windows環境のコマンドラインでgitを利用する場合、日本語を含むパスの表示がBase64エンコーディングになるので、そこは少し面倒なところです。また、日本語のコミットメッセージは、コマンドラインで文字化けして読めなくなります。Macは使ったことがないのでわかりませんが、Unicodeを使うBSD系OSですから、たぶんWindows環境と同じ問題は起こらないのではないかと思いますが。でも、手練れた開発者であれば誰であれ、不可避な理由さえなければ、日本語ファイル名を使う愚か者はいないでしょう」
作者はMac経験が無いためフォルダ名にWindowsでは使えない':'を使っていたことがあるが、Macでも使えるのだろうか。
「おれはWindowsは使ってないから」
「Macでは、インストールはhomebrewでするんでしたっけ?」
「さあね。xcodeに含まれているかも。これから調べてみるよ。git、もうそろそろ覚えてもいい頃な気がしてきたからね」
「実のところ、少し遅かったくらいかもしれませんよ。でも間に合わないということではありません。happy hacking!」
「あ、それ知ってるよ。キーボードのことでしょう?」
「ところで、『虹の色をユーザが変更できる』機能とは一体? ツイッタあたりで誰かに『虹が4色に見える文化圏にも配慮しろ』とでも言われて炎上したのですか?」
「Nyanの軌跡を敵にぶつけて攻撃するゲームなんだ。虹の色は属性攻撃さ。」
「ただの装飾かと思ったら、意外とゲーム性の根幹にある機能なのですね...」
「『TRON』っていうクールな映画があるんだけど、知ってる?」
よってたかって開発するためのgit
某社のビルの廊下を歩いていると、作業着を着たハードウェア・エンジニアが、ラズベリーパイを10倍に拡大した模型のようなボードを抱えているのとすれ違った。
どうやらここは、Web系企業でないように見える。
「こんなところ、勝手に入って大丈夫なんですか?」
「この会社とは、仕事をもらったり仕事を出したりする相手という設定なんだ。今日は我社の新入社員氏を、相手会社のプロジェクトリーダ氏に紹介するために来たという設定なんだよ」
「いいかげんガバガバな設定ですね。イントロダクション章と矛盾していますし」
「小説はいいかげんなことを書いても大丈夫だから楽でいい、というのは森博嗣だったかな。こんな文章はあくまでIT系ポエム小説なのだから、本当に捉えられても困るよ」
そんなことより、あの方がプロジェクトリーダ氏だよ、と紹介し、名刺交換のあと、雑談に入った。
プロジェクトリーダ氏はため息をついてから話し始めた。
「君の会社は無垢な新人を採れるからいいよね。ウチの会社は経験者を採らないと会社が回らなくて」
「まるで我々の会社のほうが経営に余裕があるかのような台詞ですが、大きいのはそちらの会社の方です」
「ウチの会社は人事部も大きい組織で、新人もすぐに成果を出せるようになったと報告しなければいけないから、大学でプログラミングをしたことのある経験者だけを採ってる」
「正直、滅茶苦茶羨ましいです」
ごめん新入社員氏。君が悪いのではない。
「いや、変にプログラミング経験があるのは、大学院卒と同じように、時に害があってよろしくないこともある」
ちなみにわたしは院卒という設定だ。このプロジェクトリーダが歯にもの着せぬキャラであるということを示すエピソードのつもりかもしれないが、いい加減本題に関係なく物議を醸すだけの刺激的なサービス台詞はおわりにしないか?
「例えば、この前の新人は、emacsでしかコーディングできないと宣った。COBOL案件だったんだが」
「Oops」
「Windowsを触るのは嫌だという新人もいたね。Android開発をMacでするのは、まあ無理ではないのだろうけれど」
「...まあ、経験のあるプログラマは、多かれ少なかれ、ツールや開発環境に執着やこだわりがあるものですよね」
「わたしだって、昔はスペース2つ幅でないインデントは、気持ち悪いと思っていたけれどね。困るのは、新人たちがみんな、gitを使いたがることだよ。ウチの会社はずっとSVNなんだ」
「SVNって何ですか?」新入社員氏が割って入った。
「サブバージョン。gitよりも昔に生まれたバージョン管理システムのことです」わたしが答えた。「まあ、わたしは新人の方々のほうに同情的ではあります。わたしも社会人になる前はgitだけを使っていて、会社に入って古い案件をホストしているSVNサーバとのやり取りに慣れるまで、苦労しましたから」
「そういうものかな。血気盛んな新人たちは、SVNからgitに移行するよう煩いんだ。まあ気にしなければいいだけで、彼らもいずれ、Windows上のサクラエディタとTortoiseSVNで、C89コンパイラでビルド可能なTRONアプリケーションを書くことに慣れてくれると信じているのだけれど」
「まあ、それが仕事だというのであれば、いずれはそうすると思います。わたしも入社時はgitしか知らなくて、SVNに慣れるために苦労をしました。でも、既にSVNサーバ上に存在する業務のプロジェクトを、gitに移そうとは言いません。新しいプロジェクトに最初から参加する時は、ソースコード管理にはgitを使いたいと意見は出しますが」
「なんで新人はみんなgitを使いたがるのかなあ。単に慣れているから?」
「たぶん、新人のみなさんがgit導入のメリットを説明されたと思います。プロジェクトリーダ氏は、その話をきいて移行を検討した結果、SVNから切り替える手間、コストをかけるほど大きいメリットはない、と判断されたということだと思います。バージョン管理システムの必要性はわかるが、SVNで十分だと」
「そうなんだよね」
「わたしもそう思います。SVNからgitに『移行』する必要は、まあ、ぶっちゃけ無いです」
場の空気が凍った。
「あの、この話って、gitのメリットを語って導入を推進するために書かれた物語じゃないんですか?」
「いえ、プログラミング初心者にgitの必要性をアピールするのが、執筆初期の目的です。まあ、初志貫徹は怪しいですが。
...閑話休題。そうは言っても、バージョン管理システムの中から一つ選ぶなら、gitを推すのは事実です」
「どういうことなの?」
「人は誰しも、大小の違いはあっても、プログラミングを学ぶ過程は同じようなものです。
入社して初めてPCに触る新人も、生まれてすぐに無刻印HHKの刺さるPS2ポートを探して7歩いたという天才プログラマも、プログラミングを始めたときは一人です。そこから順番は前後しますが、自分の書いたコードを一つのフォルダに収めることを覚え、プロジェクトのコピーに日付を付けたバックアップを作ることを覚えます。そのうち、扱うプロジェクトが大きくなったために、複数人とコードを共有して開発し、コンフリクトに悩まされるようになります。
バージョン管理システムは、プロジェクトとプログラマが成長過程で知る痛みを和らげる手段として生まれました。未だにこれを知らないで銀行の夜間バッチを書いているCOBOL開発者は、あるいは幸せモノなのかもしれません。
gitは、現在の人類が知る限りで最高のバージョン管理システムの一つです。そして、SVNはgitよりほんの少し悪いだけで、大きな違いはありません。まあ、本当は全然『ほんの少し』ではないのですが、我々や御社の方々がその違いに触れる機会は、実のところ多くないでしょう。
しかし一方で、間違いなく言えることがあります。これまで御社に来た経験豊富な新人は皆がgit経験者でした。そして、これから御社に来る新人も全員がgit経験者です。SVN経験者が来ることは未来永劫ありません。なぜならgitにはgithubがあり、SVNにはgithubが無いからです。
git支持者はSVN慣れを過小評価していますが、SVN支持者はgit慣れを過小評価しています。確かに、既存の開発者はSVNを遣い慣れています。もちろん、学習コストを軽視すべきではありません。
しかし、SVNが将来、gitに逆転勝利する可能性はありません。プロジェクトが終わる場合を除けば、すべてのSVNリポジトリは、いつかgitに置き換えられる運命にあります。
SVNは現代において単なるレガシーであり、COBOLの仲間、将来性のないシステムです。SVNを使い続けるならば、御社はこれから新人を雇用する度に、彼の経験値が高いほどやる気を挫き、ストレスを与え、会社も無為な学習コストを積み重ね続けることになります」
「ひどい言いようだね」
「git支持者の過激な偏った主張、として受け流して頂ければ幸いです」
エピローグ
さて、話が一通り終わり、これから帰社すると定時になってしまうので、直帰という流れになった。この会社は、近所に美味しい中華料理店があり、いつも打ち上げはそこでするのだが、今日もタイミングが良いので、新人氏の歓迎等を兼ねて、そこで食事をしようという流れになった。
そういうわけで外を歩いていると、バージョン管理システムgitの話につられて来たのか、如何にもバージョン管理システムに一家言ありそうな、海外風の風貌をした人物に出くわした。
「あの、このあたりでソフトウェア管理システムについて話している気配がしたのでやって来たのですが」
「ちょうど話し終わったところでしたよ。もしかしてあなたもgit初心者なのですか?」
この小説は3人とタイトルを付けてしまったのだが。
「いいえ」
「では、フォルダに日付を付けてバックアップを作る派?」
「バージョン管理システムを使わないでソフトウェア開発をするなんて、考えられません」
「もしかしてSVNユーザ?」
「わたしはSVNにしがみつく古代文明の生き残りなどではありません。バージョン管理システムはSVNからさらに進化すべきです」
「ならあなたはgit上級者ですね?」
「いいえ」
「hg派ですか? まさかbazaarユーザではないと思いますが」
「そのどれとも違うよ。その質問は嫌がらせかとも思ってしまうけれど、きっと私の被害妄想だね。まあ、仕方がないことさ。
あえて言うなら、過去にgitに酷い目にあわされた、珍しくも哀れな開発者さ。まあ、言いがかりのきらいはあるけれどね。わたしの書いていたコードは、gitのせいで商業的価値をほとんど完全に失う結果となったのだから、これくらいは言ってもいいと思うよ」
「へえ、興味深いね」プロジェクトリーダ氏が反応した。「gitに管理させているソースコードを破壊された経験がある、とかかな?」
「いいえ。まったく違います。なぜならわたしのプロジェクトは、gitで管理されてはいなかったのですから」
「どういうことか、説明して頂けますか?」
「もちろん」
その人物は、どこか人が良さそうな口調で語り始めた。
「あなたたちは知らないだろうね。2005年当時、私が開発し販売していたBitKee
(この小説はここで途切れている。たぶん作者の筆が折れたのだろう。)
※ この小説はすべてフィクションであり、実在する人物・団体およびその他とは無関係であり、内容には作者の見解と異なるものが含まれています。こんな格好悪い注釈文入れなきゃならないならパームトップを持った女の子とか砲塔の付いた潜水艦とか登場させればよかった。