とても便利そうだけどなんとなくとっつき辛い…
使ったことのない人にとってGitはそんなイメージがあるのではないでしょうか
そんなGitについて,個人開発・偶に趣味でやる日曜プログラマー的目線から見た入門記事を書いていきます
対象とする読者は以下の方です
- Gitをまったく知らない,これから始めてみようという初心者
- チーム開発で急にGitを使うと言われ,とりあえずどんなものかざっくりと理解しておきたい方
- ファイルの管理についてスマートな方法を探している方
Git導入のモチベーション
「そもそもなんでGitが必要なの?」という方向けの説明です(長いので読み飛ばしてもらって構いません)
例えば,いまあなたが何かプログラムを作っている最中だとします
仮に,下の図のような状態だったとしましょう
一応,プログラムが良い感じに動いてきたのでsugoi_pg
をsugoi_pg_ver1
として保存しておきました
しかし,あなたは後から機能を追加したくなったのでsugoi_pg_dev
の開発を始めました
sugoi_pg_dev
の開発が無事に完了し,あなたはこれをsugoi_pg_ver2
として世に出すことにしました!
けれど,開発意欲収まらないあなたは更なるアップデート版を制作することを決定し,
引き続きsugoi_pg_dev
で開発を行い,遂にsugoi_pg_ver3
を完成させ,リリースすることが出来ました!
以上の状況をまとめると下の写真のようになります
また,ファイル構造は下記のようになっています
段々ややこしくなってきましたね
ここで,あなたには以下のような困難が襲い掛かってきます
- 最新版(
sugoi_pg_ver3
)の機能の一部にバグが見つかったが,sugoi_pg_ver2
から大幅にアップデートを加えてあり,どのタイミングでバグが混入したのか分からない・覚えていない - 一時的に機能テストをしたかったので
sugoi_pg
フォルダをコピーして使っていたらsugoi_pg_コピー
sugoi_pg_コピーコピー
のようなファイルが生成され,どれがなんだか分からなくなってしまった - 開発が順調に進み多くのバージョンが生まれたが,HDDの容量を圧迫してきていて辛い
ここに,プログラムをフォルダ単位で管理していた場合の限界が見えてきました
まとめると以下の通りです
- プログラムを扱う際のまとまりが大きすぎて不必要な情報まで含んでしまう
- 細かい変更を追いづらい
バージョン管理システムはこのような不便な点を解消するために生まれました!
バージョン管理システムは 差分 という考え方を使うことでファイルを賢く管理しています
実際にバージョン管理システムがどのようにファイルを管理しているのか,一例をあげて考えていきます
以下のような,1~10までの整数を足し合わせた数を表示するプログラムがあったとします
total = 0
for i in range(10):
total += i
print( total ) # 45
これを以下のように,1~100までの整数を足し合わせた数を表示するプログラムに改造した場合を考えましょう
total = 0
for i in range(100):
total += i
print( total ) # 4950
この二つのプログラムを保存しようと思ったとき,どのようにすれば良いでしょうか?
二つのファイルに名前を付けて別々に保存する(例えば,sum10.py
sum100.py
のように)というのも一つの手ですね
実際,このくらい単純なプログラムを管理するだけならこの方法でも良いでしょう
しかし,先ほどのsugoi_pg
の例のようにプログラムが複雑になってくると段々負担が増えてきてしまいます
ここで,少しこのプログラムに注目してみてください
計算結果はそれぞれのプログラムで違いますが,実際にコードの中で変更されたのは「2行目のrange(100)の部分だけ」ですね
そこで,最初のプログラムだけは全て保存しておいて, 別の場所に,
「もう一つのプログラムは2行目をfor i in range(10)
からfor i in range(100)
に書き換えればOK」
と記録しておけば,一つの基本となるファイルと “ちょっとの追加情報” だけで,二つのプログラムを表現できたことにならないでしょうか?
これがバージョン管理の基本的な考え方になり,”ちょっとの追加情報” が冒頭で述べた差分にあたります.
上のsugoi_pg
をバージョン管理システムで管理した際の様子をご覧ください
最初に作ったsugoi_pg
を基本に,加えられた変更を差分の形で保存しています
これにより,たくさんあったsugoi_pg
を一カ所で,しかも過去の細かい変更までを簡単に遡って管理することができるようになりました!
これらバージョン管理システムの特徴は複数人で一つのプログラムを開発するときにも役に立ちます
とにかくGitを導入する
「細かいことはいいから早く使わせてくれ!」という方向けに,まずは導入方法を説明します
Gitを使えるようにするためにはまずGit本体が必要です
とにかくこれを入れないと話になりません
そして,多くの人はGitを使いやすくするためのサポートツールも一緒にインストールしています
GitそのものはCUI(コマンドプロンプトのように,黒い画面に文字列で操作する)で動作するので,
初めての人は分かりやすいようにGUI(マウスで直感的に操作できる)ツールを入れると良いという話です(これはお好みで)
Git本体は以下のURLからインストールできます
https://git-scm.com/
自分のOSに対応したものをインストールしてください
また,Gitには初めからGUI用のツール「Git GUI」が入っていて,一緒にインストールしてくれます
GUI用ツールには様々なものがあり,Git GUI以外のもので使いやすいものもたくさんあるので,お好みで選んでいただいて構いませんが,本記事ではGit GUI を使っていきたいと思います(他には Source Tree なんかが有名です)
インストール時の設定方法等は以下の記事が分かりやすいかと思います
Windows: Git GUIを使う準備
はじめの一歩
ここではGitを使ったバージョン管理を始めるための基礎の説明と準備をします
まずは,Gitがどのような仕組みで動いているのかを簡単に理解しておきましょう
下の画像をご覧ください
“ワークスペース” が実際にあなたがファイルを保存し,色々と弄ることが出来るフォルダになります
このワークスペースをGitで管理するように設定すると,”リポジトリ” というものが生成されます
よく意味の分からない言葉ですが,単純に「変更履歴(差分)を保管しておく場所」と認識しておいてください
リポジトリが生成されると,これを管理する為の “.git” というフォルダが出来ますがこれは特に弄らないでおきましょう
基本的な流れとしては,
- ワークスペースで作業を行う
- Git を使って変更履歴(差分)をリポジトリに登録
- 前のバージョンに戻したくなった時や変更を取り消したい時はリポジトリを操作して状態をワークスペースに復元する
という感じになります
ちなみに,チームで開発を行うときは以下のような仕組みで動いています
いくつものローカルワークスペース(あなたや他のチームメンバーのパソコンの中の作業環境)があって,
さらに全体で一つの共有リポジトリ(”リモートリポジトリ” という)を使いながら作業を進めていく
という形になります
扱うのはやはり差分情報だけなので,動作が軽いことや変更点の認識のしやすさ,変更の修正や復元などがやりやすいなどの利点があります
Dropboxなどを使って開発のやり取りをファイルベースで行っていた人は今すぐGitを使いましょう!
Gitの仕組みが分かってもらえたところで,早速ローカルワークスペース内にリポジトリを作成してみましょう
ローカルリポジトリの作成
まずは,あなたが管理したいファイルを適当に用意しましょう
それらを適当なフォルダに入れておいてください
用意したフォルダを開いて右クリックをし,Git GUI Here
を選択してください
もしGit GUI Here
が表示されていない人はGitのインストールが上手く行っていない可能性があるのでもう一度確かめてみてください
すると,Git GUIの画面が開くと思います
ここでCreate New Repository
を選択してください
上のような画面が開いたら,Browseを選択し,先ほど用意したフォルダを選択してください
Create
を押すとリポジトリの生成が始まります
いかがでしょう
とても簡単に出来たのではないでしょうか?
この調子でいきましょう!
Gitを使ったバージョン管理
ここでは,あなたがGitに関する最低限の操作を覚え,実際にGitを使ってあなたのファイルを管理するために必要なことを説明します
解説
Gitの取っつき辛さの一つに専門用語やコマンドの多さがあります
まずは,基本的に良く使われるコマンドに絞って一つ一つ見ていきましょう
コミット(commit)
コミットが何かを簡単に言い表すと,” 確定 ”という意味になります
「〇〇の機能を追加したのでコミットした」というと,「〇〇の機能の開発が終了したので変更内容を確定した」といった意味になります
まだピンと来ない方は,名前を付けて保存だと思ってください(これは少々語弊がありますが…)
どのファイルをコミットするかは自分で選ぶことができ,必ずしも一度に全てのファイルをコミットする必要はありません
また,コミットを行った場合,変更内容は ローカルリポジトリ に登録されます
大事な点として,コミットにはコメントを付けることが出来ます.出来るだけ分かりやすいコメントを付ける癖をつけておくと,管理がしやすくなるので習慣づけるようにしましょう
下で紹介する リセット を使えば直前のコミットした場所まで戻ることが出来ます
リセット(reset)
直前のコミットを起点に変更された内容を全て消去します
「色々と弄っていたら収拾がつかなくなってきたのでちゃんと動いていたところまで戻したい」といったときに使うことになります
また,オプションを指定することで直前ではなく “ある特定のコミット” までリセットすることも可能です
ブランチ(branch)
日本語で “枝” という意味です
文字通り,リポジトリを枝分かれさせて管理させることが出来ます
ある枝の変更内容は違う枝には反映されないという特徴があります
また,ブランチを作成することを “ブランチを切る” という言い方をすることがあります
基本的にどのようにブランチを切っても良いことにはなっていますが,チーム開発の場合,git-flow,git hub flow,git lab flowのようにある程度ブランチの切り方のテンプレートが出来ている場合があるので参考にすると良いでしょう(ブランチモデルで検索)
プッシュ(push)
(この操作はリモートリポジトリの内容を変更します)
ローカルで起きた変更をアップロードする操作です
これにより,ローカルリポジトリの変更内容がリモートリポジトリに登録されます
プッシュする前には必ず,修正すべき箇所や問題点がないかよく確認するようにしましょう
プル(pull)
リモートリポジトリの変更内容でローカルリポジトリをアップデートするコマンドです
こちらはプッシュと違い,リモートリポジトリの内容を変更しないので,安心して使って大丈夫です
マージ(merge)
違う変更同士をくっつける(統合する)操作がマージです
個人開発の場合はあまり問題になりませんが,基本的にGitを使っていて一番面倒臭いことが起こる処理になります
mergeコマンドを使うことで,違うブランチ同士をまとめて一つのブランチに統合することが出来ます
また,プッシュ・プルを行う際も,リモートリポジトリの内容とローカルリポジトリの内容との間でマージが行われています
ここで,「同じファイルが違うコミットで別々に変更されているとき」マージが失敗しエラーとなってしまいます
この状態をコンフリクト(conflict)と言います.コンフリクトは日本語で”衝突”という意味ですが,文字通り変更内容が衝突していてどちらを選べばいいか分からなくなっている状態を表しています
具体例を挙げると,「file1 が branch1 と branch2 で別々に変更されていた」とか「file1に変更を加えたのでプッシュしようとしたら誰かが先に file1 を変更してプッシュしていた」といった場合に起こります
コンフリクトが起きた場合,解消するには慎重さが求められるため,よく確認・相談して行うようにしましょう
クローン(clone)
リモートリポジトリの内容をそのままそっくりローカルにコピーするコマンドです
既に開発が進んでいるプロジェクトに後から参加する場合,最初に実行するコマンドになるでしょう
Gitで管理されたファイルをインターネットに公開するためのサービスは充実しており,実行可能な形式(.exe など)ではなく,ソースコードのままプログラムが公開されているというケースも多くなってきました(特に,コードをそのまま実行可能なpython等の言語が出てきてから顕著です)
これらのプログラムをダウンロードする場合に clone
コマンドを用いることがあり,「なんだか良く分からないけど clone
ってやつは見覚えがある!」という方ももしかしたら居るかもしれません
以上が基本的な内容になります
その他にも様々なコマンドがありますが,入門用ということで,ここでは一部を簡単に紹介するに留めておきます
- プルリクエスト(pull request):ローカルリポジトリの変更内容を他の開発者に通知する機能です.変更内容をいきなりプッシュすると不具合等があった場合に困ってしまうため,まずはプルリクエストを送り,誰かに変更内容を確認してもらってからプッシュするという流れをとると安心です.
-
リバート(revert):ある特定のコミットの内容を取り消した新しいコミットを作成する機能です.リセットと似ていますが,リセットの場合はその時点まで変更内容を消して戻すのに対して,リバートを用いた場合はそのコミットの内容を取り消したコミットを新規作成して上書きするような形になります.状況に応じて使い分けましょう
-
チェリーピック(cherry-pick):他のブランチのある特定のコミットだけを今のブランチに反映させる機能です
紹介しきれないので,あとは各々で調べて頂ければ幸いです
実践
いよいよ実践編です!
実際にGit GUIを使って最初のコミットを行い,ブランチを切ってみるところまでやってみましょう!
“はじめの一歩 – ローカルリポジトリの作成” の項ですでにローカルリポジトリの作成までは終わっているかと思います(まだの人は是非戻って見てきてください)
一度ローカルリポジトリの作成をしてしまえば,次回起動時からは自動的に作成したリポジトリが読み込まれるので,Git GUIを閉じてしまった方は再度起動してみてください
それでは,何か適当にファイルを作って追加してみましょう!
ここでは
# test.py
print("Hello, Git!")
というファイルを追加してみました
それでは,Git GUI の Rescan
というボタンを押してみましょう
先ほど作成したファイルが左上の欄に表示されたはずです
次に,Stage Changed
というボタンを押して,OK
をクリックします
そうすると先ほど作成したファイルが左下に移動したと思います
この Stage
という操作で,コミットに含めるファイルを選択することができるので覚えておきましょう
最後に右下のコメント欄に任意のコメントを記述して, Commit
ボタンを押せば完了です!
ブランチを切るにはメニューバーから Branch
– Create
を選択します
作成するブランチの名前を指定したらあとはデフォルトの設定のままで構わないので Create
を押しましょう
現在のブランチが develop
に変わっていれば成功です
(masterブランチに戻るには,メニューバーからBranch
– Checkout
をクリックし,masterブランチを選択してCheckoutを押します)
折角なので,developブランチに何か適当なコミットを加えてみましょう
ここでは以下のファイルを追加しました
# dev_feature.py
total = 0
for i in range(10):
total += i
print(total)
先ほどと同様の手順でコミットします
出来ました
ここで,ファイルの様子を見てみます
masterブランチにチェックアウトしてみました
dev_feature.pyが消えて,きちんとmasterブランチの内容が読み込まれていることが確認できます(ちょっと感動ですね!)
最後に,現在のリポジトリの様子を分かりやすく可視化してみましょう
メニューバーから Repository
– Visualize All Branch History
を選択します
変更内容が一目瞭然で分かりやすいですね
Tips
大したお話でもないのですが小噺的に
コミットの粒度
多分,何も考えずにGitを使うと,始めは時系列ベースでコミットを進めていくと思います
時系列ベースとはどういうことかというと,例えば 20xx年〇月〇日 更新分 全 nn ファイル
といった感じで,その日までにあった変更を全部まとめて一つのコミットにしてしまうような感じです
これは機能ベースに改めた方が上手くいくことが多いです
例えば, ユーザーからの入力受取機能追加: 関連した 3 ファイルを更新
といった感じです
機能ベースにコミットをまとめることで以下のような利点があります
- 後から見たときに変更内容を辿りやすい
- 後から見たときに修正が容易になる
- 開発途中の中途半端なファイルがコミットに含まれない(バグの予防)
そして,なるべくですが,「一つのコミットで更新される内容は一つの機能」に絞った方がいいでしょう
<更新内容>1.xxxの機能を追加 2.yyyの機能を追加 3. zzzの機能を追加 ……
などと書かれたコミットは見る気も起きず,管理も大変になるだけです
For Non-Programer
Gitで管理できるものは何もプログラムのソースコードだけではありません
テキストで表現されたありとあらゆるファイル,Excelやpdf等のドキュメント,画像など実に多岐に渡ります
例えば,HTMLを書いているWebデザイナーの方や,執筆中の小説を管理したい作家の方などにもGitは有効です
工夫次第でGitは優れたパフォーマンスを発揮してくれることでしょう
後書き
お疲れさまでした.以上で本記事の内容は終了になります.
紹介しきれていない機能がまだたくさん残っていますが,既に基本的な知識は読者の皆様に伝わっているものと期待します
Google先生で Git (調べたい機能・コマンド)
などで検索すると,様々な情報がヒットするので是非,各自で調べてみてください
また,私はGitを使ったまともなチーム開発は未経験のため,本記事における記述には誤りが多分に含まれているものと思います
スペルミスや「ここの説明間違ってるよ」といったご指摘,また「この機能の説明も追加して」といったご要望は随時受け付けておりますので是非コメントを頂ければと思います
最後までお読みいただきありがとうございました!!
コメント