#はじめに
この前、新卒の人に対して Git を教えたんですが、これがまた難しい。
バージョン管理システムだということは理解しやすいと思うのですが、リポジトリとかブランチとかコミットとかイメージが湧きにくい。
そういう時、自分は別の物に例えてもらえるとイメージがしやすくて好きです。
アバウトに伝わってしまったり、誤解を生んでしまったりすることもあるので賛否両論あると思いますが、
入りとして概要をイメージできてるととても覚えやすいですし、その後に実際に触ってる中で細かい知識を軌道修正すれば良いので、細かい仕様を説明されても理解力が追いつかない自分にとっては、物に例えてもらえると非常に助かるのです。
そんなわけで、今回は物に例えて Git を説明してみることにしたんですが、すっごいグダグダになってしまったため、改めて記事として整理しようと思います。
今回は教育のために、おもしろさとわかりやすさを追求した、挑戦的な感じに記事をまとめようと思います。
登場人物
新卒くん
新卒生の彼は Git を知りません。
今回は新卒くんに Git を教えて行くという体です。
私
新卒君にGitを教えたい人
Nくん
Git の例えの中で出てくる人 (リポジトリを擬人化したもの)
Aさん、Bさん、etc
同じく例え話内の人。
Nくんを教育したい人たち。
Gitとは (通常編)
プログラムソースなどの変更履歴を管理する分散型のバージョン管理システムのこと。
Gitは分散型という特徴をもっていて、各々のローカルにリポジトリをコピーして修正することができます。
とまぁ普通はこんな感じで、リポジトリとかブランチとかコミットとか教えて行きます。
だけど、新卒くんはもう頭がパンクしています。
新卒くん:「リポジトリ...? ブランチ...? キャンディちょうだい」
私:「彼の脳は自我の崩壊を選択した...」
Gitを例えてみた編
では Git を物に例えてみます。
repository と commit
そう、例えるなら__リポジトリは人生__であり、__コミットはその人の積み重ねた歴史__ではないでしょうか?
Nくんを立派な人に育てたいと思い、周りの人間があれやこれやを彼にやらせます、そしてNくんは自分の人生に結果をコミットして歴史を刻んでいくのです。
clone と local repository
しかし、周りの人間がNくんに対して思うままに教育をしていくと、Nくんの中でどういう化学反応がおきるかわかりません。
特に思春期などは些細なことが彼の中で大きな問題になりかねないため、周りも慎重にならざるをえません。
しかし、幸いなことにNくんは分身ができるのです。
Nくんの分身はNくんの本体(以後、オリジナル)に戻ることで、分身が学んだ経験などが本体に合成される特性があります。
そのため、人々はNくんの分身を連れて帰り、各々教育をしました。
この分身を連れ帰る行為を__クローン__と言います。
この、分身を家に連れて帰ることが Git の分散型の所以です。
ローカルリポジトリでいくらコミットをしてもオリジナルに合成するまでは、本体には影響しません。
branch
これで、みんな家に帰ってから好きに教育することができます。
しかし、Aさんははこう思います。
「Nくんにはあれもこれもさせてみたい。しかし、教育に失敗してグレてしまったらオリジナルに合成させてもらえないし。。。」
でも大丈夫!なんと分身のNくんはさらに分身ができるのです!
しかも、Nくんは合体した時に分身の経験したことを取り込むことができるので、教育したい事柄ごとに分身を切り分けて、教育が完了したら合体させればいいのです。
そうすることで、同時に教育ができるだけでなく、失敗した場合はオリジナルには取り込まないという選択もできるので、とっても効率的ですね。
Aさんはさっそく家に連れ帰ったNくんの分身をさらに分身させて、分身1には英語を教えて、分身2にはバイクを教え、分身3にはサッカーを教えることにしました。
ただ、同じ人間が複数人いるため、名前をつけて識別します。
連れ帰ってきた分身は「master」、そこから分離した分身1は「feature/english」、分身2は「feature/bike」、分身3は「feature/soccer」
この名前をつけた分身が__ブランチ__になります。
さて、その後「feature/bike」は暴走族になってしまいました。
なので、「feature/bike」は見捨てることにします。
見事にいい子に育てくれた「feature/english」、「feature/soccer」は「master」に合体させます。
この合体させることを マージ といいます。
すると、英語とサッカーを習得した「master」が誕生するわけです。
fetchとPULL
そんなある日、オリジナルであるNくん本体にBさんが「空手」を習得した分身をマージしました。
そのころAさんは護身用に空手の境地である「菩薩の拳」を教えたいと考えていたので、空手ができる能力を手に入れれば、「菩薩の拳」を覚える近道になります。
そこで、オリジナルであるNくんの家に、また分身を作ってもらうようにお願いをしに行きます。
この時点でオリジナルのNくんから分離した分身は「空手」が使えます。
Aさんは新しい分身を連れ帰り、家にいるサッカーと英語ができる分身「master」にマージすることが目的です。
今回は家にすでに分身がいて、そいつに取り込ませることが目的ですが、まずはどんな感じに育っているのかを連れ帰り観察し、マージするかどうかを検討します。
これを fetch と言います。
ちなみに、連れ帰りマージするまでの作業を一括で行うことを pull といいます。
##push
Aさんは「空手」の能力を自分家の分身に取り込み、そこから育て上げて見事に「菩薩の拳」を覚えさせました。
満足したAさんは自分家の分身をオリジナルのNくんに戻そうと考えます。
そして、オリジナルのNくんのところまで連れて行きオリジナルにマージします。
これを push と言います。
これにより、新たにCさん、DさんがNくんを育てようと連れ帰った分身はみんな「菩薩の拳」が使えます。
ここで初めてみんなに修正の影響が出るようになるわけですね。
##コンフリクト
AさんがオリジナルのNくんの更新を取り入れようとして、分身にマージしようとした時に問題が起きました。
じつはAさんは車の免許をとらせていたのですが、その間にCさんも車の免許をとらせていたのです。
しかもCさんが先にオリジナルのNくんにマージしていたため、Nくんはすでに免許証を持っています。
同じ人間が2つ免許証を持つわけにもいかないので、どちらの免許証を反映するのか決定するまでマージはできません。
これが コンフリクト になります。
結局Aさんは自分が取得させた免許証を国に返上し、マージしましたとさ。
Commit ID
みんなが教育した分身を取り込んだNくんは全知全能の神になることができました。
そう、まさにすばらしい人生を歩むことができました。
しかも分身も含めた全てのNくんは、自分に変化が会った時のことを固有ID付きで日記に記載していたのです。
そのため、全てを取り込んだオリジナルのNくんは日記を見るたびに、何があったのか鮮明に思い出すことができます。
この日記にふってある固有IDが __コミットID__になります。
N君は何度も何度も人生を振り返り言いました「おゝ我が人生」と。。。
#最後
私:「逆にわかりにくくなってしまった感が否めないが、新卒くんはなんとなく理解できたかな?」
新卒くん: 「オゥ トワ ラヴィ (おゝ我が人生)」
私:「そう!そうだよ!新卒くん! Gitとは人生なんだよ!わかってくれたんだね!ひゃっほーい!」
#余談
初めはもっとわかりやすくなる予定だったのですが、結構しんどかったです。
こんな記事をQiitaにあげていいのかと思いつつ、結構頑張って書いた時間を無駄にしたくないので公開することにしました。
あと、rebase とか混ぜるともうN君は時空を操る存在になってしまうので、今回は説明を省きました。
あくまで、基本のイメージを掴んでもらうことが目的なので。
当初は submodule の説明も入れたかったのですが、今回はやめておきます。笑
たぶん、この例えの流れにいれるなら、submodule は結婚相手であったり、子供であったり、別の人生を歩んでいて、N君に影響を及ぼす存在ですかね。
ちなみに、マニアックな元ネタでしたが、自分的には無理矢理ネタを絡めることができて結構満足できました。笑