はじめに
- 第2回で、開発以外でVS Codeを使って、徐々にVS Codeに慣れてきた頃かと思います。
- 今回は、ソース管理において主流ソフトウェアとなっている「Git」にトライします。
※本記事を印刷してご覧になりたい場合は、iWorld会員向けに公開しているPDF版「VS Codeで、開発以外にできることを理解しよう」をご利用ください。
0.用語の確認
名称 | ざっくり意味 |
---|---|
リポジトリ | 過去の状態を記録できる「貯蔵庫」のようなもの |
リモート・リポジトリ | サーバー、クラウド・サービスで利⽤する「みんなで使う貯蔵庫」 |
ローカル・リポジトリ | ⾃分のPCで利⽤する「⾃分専⽤の貯蔵庫」 |
1.Gitとは何か
Gitとは、変更履歴を記録できる「バージョン管理システム」のことです。元々はLinuxカーネル開発のために作られたものですが、普及が広まって代表的な分散型バージョン管理システムとなりました。
Gitは誰が、いつ、どのようなファイルを、どのように編集・更新・追加・削除をしたか、という履歴を管理できます。
なぜ、ファイルの履歴管理が重要なのでしょうか。以下が、個⼈的に重要と思う理由です。
- 「ちょっと間違ったかも︖」「ちょっと違うことをした⽅が良いかも︖」と思ったときに、1世代、2世代前に戻せる
- 複数⼈で担当を分けた開発で、それぞれの開発機能が⼀部被っている時にデグレード・先祖返りを防ぐことができる(開発に限らず、ファイルやhtmlなどで先祖返りを経験したことがある方は多いのではないでしょうか)
⼤きな違いは、Gitが「分散型」で、SVNやCVNが「集中型管理」であることです。以下で、SVNとGitを⽐較します。
SVN開発のイメージ確認

SVNは集中型のソースコード管理システムであり、サーバーにインストールをしたリモート・リポジトリのみでソース管理をしていることが特徴です。
- SVNは、以下の流れで開発を行います。
- 最新のソースを取得する際は、リモート・リポジトリからローカルPCへダウンロード(チェックアウト)する
- ローカルPCでTEST.pyを編集する
- リモート・リポジトリにコミット(リモート・リポジトリへ直接登録)する
SVNは、上記のようなソース管理フローであることから、プロジェクト・メンバーが何を開発しているのかを⼤体把握できます。ただし、「先祖返り」が起きやすい管理であることが課題です。
- 以下に、具体例を挙げます。
- リモート・リポジトリから、TEST.pyをAさん→Bさんの順番でチェックアウトして、ソースを更新する。
- 先に、Bさんがリモート・リポジトリにコミットする。
- 次に、Aさんがリモート・リポジトリにコミットする。
- 上記の結果、Bさんの更新内容が反映されていない状態のTEST.pyがリモート・リポジトリに保管される。
上に挙げた例のように、SVNはローカル(=個々のPC)でのファイルの変更履歴管理ができず、コミットが直接リポジトリに反映されるため、競合が発⽣した場合、上書きで更新内容が消える可能性があります。
私⾃⾝、このようなケースに遭遇し、「先祖返り」で1つの機能が使えなくなったTEST.pyをソース管理してしまった苦い経験があります。
Git開発のイメージ確認

Gitの特徴は前述した通り「分散型」であり、リポジトリがリモートとローカルに存在しています。
ローカル・リポジトリがあることにより、ローカルでの開発履歴が保管されていきます。そして、ローカル・リポジトリ側に履歴情報があるため、リモート・リポジトリの最新情報との⽐較で、差分に気づくことが可能です。つまり、常に最新のソースを取り込みながら開発を進められます。
試したい変更がある場合は、ローカルで対応してローカル・リポジトリに保存します。したがって、ローカルでの変更内容を採⽤しないことになっても、リモート側は変更していないので、他の⼈に影響を与えることはありません。ローカル・リポジトリ側のみを、1世代前の変更が無い状態に戻せば良いのです。
また、Gitでは「先祖返り」は発⽣しにくく、「SVN開発のイメージ確認」で例示したような「Bさんによるソースへの更新内容が無くなる」ということは起きません。
- 「先祖返り」が発生しにくい理由を、以下のざっくりとした流れで確認しましょう。
- リモート・リポジトリから、TEST.pyをAさん→Bさんの順番で、ローカル・リポジトリに取り込む。
- 先に、Bさんが開発を終了して、リモート・リポジトリにTEST.pyを登録する。
- 次に、Aさんがリモート・リポジトリにTEST.pyを登録しようとした時、既にファイルが更新されていることに気づく。
- Aさんは、Bさんの更新内容を取り込んだ上で、リモート・リポジトリにTEST.pyを登録する。
同じファイルが更新されていることに気づくことができる理由は、Gitは同じファイルの変更があった場合に「どちらの変更を適⽤すれば良いか判断できない」ものの、「競合を検知できる」からです。
競合の状態は「conflict」と⾔い、⼿動で解決するようにメッセージされます。「conflict」が起きた場合にどちらを採⽤するかは、⼈間が⼿作業で決めていきます。
RPG開発でGitを使う意味は︖
GitをRPG開発で使う意味は、大きく分けて2つあります。
- 1つは、複数人によるチーム開発での生産性向上のためです。
- RPGⅢ(OPMプログラム)の開発では、同じソースを他の⼈と⼀緒に更新をするイメージは湧かないと思います。
- 一方、ILE RPG、FF RPGは、複数ソースからをモジュールをバインドして、1つのプログラムを作ることが可能です。
- さらに、サービス・プログラム(様々なプログラムから共通に利⽤するサブルーチンを1つにしたもの)を作成した場合は、開発状況によっては複数名で⼿を⼊れる可能性があります。
- もう1つは、煩雑なソース管理からの卒業のためです。
- Gitを使わないRPG開発のソース管理はどのようになっているでしょうか。
- ソース・メンバー名の後ろに数字をつけてバックアップしたり、別のソース・ファイルで保管をしているものの、1世代分しかソースが無い場合が多くはないでしょうか。
- どのソース・メンバーが最新で、何を理由に改修をし、誰がいつ対応したのか。このような情報はPDMだけでは管理できないので、これを機にGitにトライするのも良いのではないでしょうか。
2.Gitの基礎知識編
Step1︓Gitの管理範囲
Gitの管理範囲は、リモート・リポジトリとローカル・リポジトリだけではありせん。
ローカル・リポジトリに到達するまでに、2つエリアを経由してファイルを管理します。

- ワーキング・ディレクトリー(別名︓ワークツリー)
- PCで編集した「Gitで変更を監視しているファイル」が置いてあるディレクトリーのことです。
- ローカルPCでディレクトリーを開き、ファイルを編集するのが、この作業ディレクトリーです。「git add」コマンドでステージング・エリアへ移⾏します。
- ステージング・エリア(別名︓ステージ、インデックス)
- ワーキング・ディレクトリーで作成、更新、削除したファイルのうち、変更管理を記録したい「意味のあるまとまり」のみが、このエリアに移⾏されてきます。
- 「git commit」コマンドで、ステージング・エリアのファイルをローカル・リポジトリに⼀括登録します。
- ローカル・リポジトリ
- ステージング・エリアに移⾏させた「意味のあるまとまり」が、コミットによってローカル・リポジトリに登録され、履歴のスナップショットが作成されます。
- 「git push」コマンドで、リモート・リポジトリにコミット内容を送信、記録できます。
- リモート・リポジトリ
- ローカル・リポジトリからコミットされた変更点を保持しています。
- 「git pull」コマンドで、リモート・リポジトリのファイル履歴を取得して、ローカル・リポジトリに反映できます。
- 上記イラストにはありませんが、「git clone」コマンドで、リモート・リポジトリを複製(clone)元として、ローカル・リポジトリ⾃体を構築できます。
Git管理範囲と⼀緒にコマンドの話も出ていますが、各コマンドの説明は後述します。
覚えていただくべきポイントは、Gitを⽤いた開発の時は、ワーキング・ディレクトリー→ステージング・エリア→ローカル・リポジトリ→リモート・リポジトリの順番で記録を重ねていくということです。
Step2︓Gitの主要コマンド①
git init- ローカルPCで新しいリポジトリを作成する際に使⽤するコマンドです。
- Gitでバージョン管理を始める際に、リポジトリを初期化します。ここでいうリポジトリは、ローカル・リポジトリのことです。
- git add=編集履歴をステージングエリアに移すことです。
- 運⽤前提として、commitをするにはワーキング・ディレクトリーからステージング・エリアへの移⾏を最初に⾏う必要があります。
- ステージング・エリアでは、誤った変更が⼊ったファイルがあった際に「git rm」コマンドでステージング・エリアからワーキング・ディレクトリーに戻すことが可能です。
- 1つのcommitでは、1つの主題の変更だけを含めることが基本です。つまり、関連性のない変更を1つのコミットにまとめることは避けるべきです。
【例】ボタン・レイアウトを行い、ナビゲーション・バーの変更も⾏った。
– ナビゲーション・バー変更のファイルは1主題=1commitのルール違反となる。ナビゲーション・バーの変更はgit addの対象外にした。すなわち、ステージング・エリアには移⾏させなかった。
– ボタン・レイアウトのcommit後、ナビゲーション・バーの変更ファイルをgit add、commitをした。
- commit=スナップショットを作成することです。
- commitをすると、ワーキングディレクトリにあるファイルの実体が、Gitによりメタデータと実データに分離し、commit時点のスナップショットとして、メタデータと実データが格納されます。
― commitされたデータはリポジトリに格納され、管理されるようになります。 - commitをする際は、commitメッセージと呼ばれる⽂章を記述し、ファイルを追加、編集した内容(時には削除した内容)を特定の意味を付けて、リポジトリに⼀緒に格納するルールがあります。
- 1つのcommitでは、主題となる変更とは無関係な変更を含めません。
- かなりくだけた例になりますが、「貯蔵庫=リポジトリにあるものは、commitをすることで、その時点に戻すことができる」を、ちょっとした⽇常⽣活の⼀コマで表現したいと思います。
【例】
1. 新年会への参加を表明した
2. 新年会に参加した
3. ビールを飲んだ →ここで、commit
4. 日本酒を飲んだ
5. ワインを飲んだ
6. 体調が悪くなった
7. 翌日、二日酔いになった
現在が「7. 翌日、二日酔いになった」の状態だとすると、commitした「3. ビールを飲んだ」に戻すことが可能です。そして、commitした「3. ビールを飲んだ」以降、「水を沢山飲む」や「他の種類のお酒を飲むのは控える」といった行動(分岐)をすることで、「7. 翌日、二日酔いになった」の状態にならずに済む、ということです。
⼈間の⾏動の場合は元に戻せませんが、Gitではcommitによってスナップショットをとり、元に戻したり、元に戻して違う分岐を進ませることが可能とご理解ください。
- ローカル・リポジトリで⾏われたcommitは、git pushというコマンドでリモート・リポジトリに同期されます。
- リモート・リポジトリに同期されることで、PCのローカル・リポジトリで開発したファイルを、プロジェクトチーム内で確認できるようになります。 ※pushは、ローカル・リポジトリで作成している全てのブランチの情報をリモート・リポジトリへ反映するのではなく、特定のブランチの情報をリモート・リポジトリの特定のブランチへ同期します。
Step3︓ブランチ
「ブランチ」の概要-
- pushの説明に「ブランチ」が出てきましたので、Gitをチームで使う時の運⽤として「ブランチ」を理解しておきましょう。
- ブランチ=開発の枝のことです。
- 不特定多数によって同時並⾏で開発をすると、1つの開発履歴で作成し続けることが難しくなります。

-
- 図の例では、新機能を開発する際に、「X機能」はAさんが実装、「Y機能」はBさんが実装、という役割分担をしています。
- X機能とY機能は相互に影響を受けないため、同時並⾏で開発作業を続けた⽅が効率的です。このような場合、ブランチを作る(並⾏世界を作る)ことが推奨されています。
- ブランチのメリットは、各ブランチを起点にして別々に作業をし続け、機能や意味の単位を分け、各ブランチの先頭を参照することで個別バージョン管理が可能であることです。
- ブランチ運⽤を理解するには、「HEAD」を理解する必要があります。
- 「HEAD」は、現在のリポジトリの位置を指し、今作業をしているブランチの先頭を⽰すポインターのことです。

― 「HEAD」はブランチを切り替えると、切り替えたブランチを参照するようになります。これを「チェックアウト」と⾔います。(コマンドではgit checkout)
― 再度、「main(公開用)」に戻すと、「HEAD」の位置は元の位置に戻ります。
― また、「HEAD」はcommitをすると、最新のcommitの位置を⾃動で参照します。
Step4︓Gitの主要コマンド②
git checkout- 参照するブランチを切り替える(HEADの位置が切り替え先のブランチの最新のcommitへ変更される)ことです。
- checkoutをする際にmain等、既存のブランチをもとに新規ブランチを作成、ブランチを切り替えることが可能です。
- また、HEADはcommitをすると、最新のcommitの位置を⾃動で参照します。
- ある程度、機能開発が終わったタイミングで、mainブランチへ統合をする際に使⽤するのが、git mergeです。
- 2つ以上のブランチの開発履歴を、1つのブランチにまとめられます。
- リモート・リポジトリに対してのmergeと、ローカル・リポジトリ内でのmergeがあります。
以下はリモート・リポジトリ上でのmergeイメージです。

git fetch/git pull
- どちらもリモート・リポジトリの最新情報をローカル・リポジトリへ取得するコマンドですが、⼤きな役割の違いがあります。
- git fetchは、ローカル・リポジトリの最新のソースやファイルを、リモート・リポジトリのブランチに取り込みません。情報の取得にとどまります。
- git pullは、ローカル・リポジトリの開発中のブランチに、リモート・リポジトリの最新の情報を取り込みます。すなわち、ローカル・リポジトリのブランチで、リモート・リポジトリのファイルのファイルをmergeすることになります。
― つまり、git pullは、「リモート・リポジトリから各ブランチの最新情報をfetch」して、「ローカル・リポジトリの特定のブランチへ、最新情報をmerge」する、という2つの作業をしているのです。
おわりに
- 今回は基礎学習編なので、Gitの概要や要素、主要なコマンドをまとめました。
- ⼀気に情報が⼊ってきましたが、⼿を動かさないとピンとこないところがあると思います。
- VS Codeを使うと、Gitのコマンドをすべて覚えなくても、GUIの画⾯でサクサクとGitを始められます。
- 次回は、よりGitの操作感に慣れていきましょう︕
筆者
|
日本アイ・ビー・エム株式会社
Qiitaに、シュッとシリーズを投稿中 |