こんにちは。テクマトリックスの長久保です。

昨今の開発現場でのデファクトスタンダードになっている「Git」。
今回はこの「Git」について、何がいいのか、どういった点でほかのバージョン管理より良いのか、どういった形で利用していくのかなど、Gitについて紹介するブログ記事になります。

本ブログについて

ブログの目的

  • Gitがどういったものか理解できる
  • 他のツールと比較してのメリットデメリットを整理する
  • 実際にGitの簡単な操作ができるようになる。

想定するユーザー

このブログは以下のユーザーを想定して記載します。

  • Gitに興味はあるけれど、まだ使ったことがない方
  • ソフトウェア開発において、バージョン管理の重要性を理解しているが、具体的にどのようなツールを使えば良いのか迷っている方
  • 共有フォルダやSubversionなどのバージョン管理システムを使用しているが、Gitへの移行を検討している方
  • チームでのコラボレーションをより効率的に行いたいと考えている方

ブログの構成

本シリーズは全4回で構成されており、次のような構成で進めていきます。

  • 第1回:本シリーズの概要、Gitの基本概念と入門
  • 第2回:共有フォルダと比較してのGitの優位性
  • 第3回:Subversionと比較してのGitの優位性
  • 第4回:GitおよびGitのホスティングサービスの優れた機能

このシリーズの第1回目にあたる今回は、Gitがどのようなツールなのか、いかにして現代のソフトウェア開発における標準的なツールとなったのかを解説します。

バージョン管理システム

Gitはバージョン管理システムの一種です。
バージョン管理システムを利用することで得られる代表的なメリットとして、以下が挙げられます。

  • 変更の記録と追跡
    ソフトウェア開発において、コードやドキュメントは日々変更されます。
    バージョン管理システムはこれらの変更を詳細に記録し、いつ、誰が、なぜその変更を行ったのかを追跡することができます。
  • リスクの軽減
    新しい機能の追加や既存のコードの変更は、常にバグの混入やデグレードのリスクを伴います。
    バージョン管理システムを使用することで、もし新しい変更が問題を引き起こした場合でも、簡単に以前の安定した状態に戻すことができます。これにより、開発者は安心して開発を進める事ができます。
  • 共同開発の促進
    現代のソフトウェア開発は複数の開発者が協力して行うことが多いです。
    バージョン管理システムは、異なる開発者が同じファイルに同時に作業する際の衝突を防ぎ、変更内容を効率的に統合する仕組みを提供します。これにより、スムーズな共同開発が可能になります。

共有フォルダとSubversionの限界

共有フォルダやSubversionは、ソースコード管理において長年にわたり利用されてきた手法です。しかし、これらの方法には、現代のソフトウェア開発プロセスの要求を満たす上での限界があります。
こちらの詳細については連載の第2回および第3回の記事にて記載します。

共有フォルダの限界

  • 衝突管理の不足
    複数の開発者が同時にファイルを編集する際に、最後に保存された内容のみが反映され、以前の編集が上書きされてしまいます。重要な変更が失われるリスクや、意図しない更新が発生してしまう可能性があります。また、同時に同じファイルを編集しようとした場合、ほかの人の編集が終わってから作業するといった、開発以外の待ち時間がかかってしまいます。
  • 変更履歴の欠如
    ファイルの変更履歴を追跡する機能がなく、誰がいつどのような変更を行ったかを把握するのが困難です。そのため開発者は管理用のドキュメントを作成し、変更内容を記録する必要があります。
  • 復旧が困難
    ファイルが誤って削除された場合の復旧が困難であり、以前の状態に戻すためには手動でのバックアップが必要です。これは特に大規模プロジェクトでの管理負担を増加させます。

Subversionの限界

  • 中央集権型の制約
    Subversionの中央集権型の仕組みは、サーバーにアクセスできない状況では開発者が作業を継続することができません。ローカル環境で大量の修正を保持して、サーバーにアクセスできるようになったタイミングで一括でコードをコミットすると、履歴管理などで不都合が生じる可能性があります。
  • ブランチとマージの複雑さ
    Subversionでのブランチ作成やマージのプロセスは、特に大規模なプロジェクトにおいて、時間がかかり複雑であるため、効率的な開発プロセスに支障をきたします。
  • 大規模プロジェクトでのパフォーマンス問題
    大量のファイルや長い変更履歴を持つプロジェクトでは、Subversionのパフォーマンスが低下することがあります。

これらの内容は、特に大規模プロジェクトや高速な開発サイクルが求められる現代のソフトウェア開発において、効率性や柔軟性の点で課題となります。
より進化したバージョン管理システム、特にGitを代表とする分散型バージョン管理システムへの移行が推奨される理由の1つです。

GitとSubversionの利用者数の推移

Stack Overflowの調査で見る利用者の推移

例えばStack Overflowの調査によると、次のように推移しています。

■2015年:https://survey.stackoverflow.co/2015/
Git:69.3%
SVN:36.9%
I don’t use source control:9.3%

■2018年:https://survey.stackoverflow.co/2018/
Git:87.2%
Subversion:16.1%
I don’t use version control:4.8%

2018年以降アンケート対象に入っていなかったため、2015年と2018年の比較になります。
Gitの利用者が増え、バージョン管理システム未使用やSubversionからの移行が進んでいることがわかります。

Googleトレンドで見る利用者の推移

以下の図は、2004年から現在までの日本においてのGitとSubversionの人気度の推移になります。
Googleトレンド:https://trends.google.co.jp/trends/

SubversionからGitへ興味が移り、Gitへの移行が進んでいることが推測できます。

では、なぜこれほどまでにGitへの移行が進んでいるのでしょうか。

Gitとは

改めてGitについて紹介します。
Gitは分散型バージョン管理システムの一種で、ソフトウェア開発で広く利用されています。2005年にリーナス・トーバルズ(Linuxカーネルの開発者)によって開発されたGitは、高い効率性、柔軟性、および安全性を提供することで、現代のソフトウェア開発の標準的なツールとなっています。以下に、Gitの主要な特徴と利点を公式ページより引用し、簡潔に説明します。

ブランチとマージ:Branching and Merging

Gitのブランチとマージの概念は、ソフトウェア開発プロセスにおいて中心的な役割を果たします。
ブランチ機能を利用することで、開発者は独立して新しい機能の開発やバグ修正を行うことができ、作業が他のブランチに影響を与えることはありません。これにより、複数のタスクを同時に進めることが可能になり、チームの生産性が飛躍的に向上します。

小さく早い(効率的なパフォーマンス):Small and Fast

Git は高速です。
Git を使用すると、ほぼすべての操作がローカルで実行されるため、どこかのサーバーと常に通信する必要がある集中型システムよりも速度が大幅に向上します。
Subversionと比較した場合において、Subversionにとって理想的な条件下であっても、GitはSubversionよりも1~2桁高速です。

分散型アーキテクチャ:Distributed

Gitの分散型アーキテクチャは、その設計の核となる要素です。
Gitの分散型アーキテクチャによって、各開発者がプロジェクトのリポジトリの完全なコピーをローカルマシンに持つことができます。開発者はネットワーク接続の有無にかかわらず、作業を続けることができます。ローカルリポジトリには、プロジェクトの全歴史が含まれているため、コミット、ブランチの作成、マージなどの操作をオフラインで行うことが可能です。
さらに、各開発者がプロジェクトの完全なリポジトリを持っているため、単一の故障点が存在せず、リポジトリのデータが失われるリスクが大幅に減少します。
分散型モデルでは、変更の統合も効率的です。開発者は自分のローカルリポジトリで作業を完了し、その後、変更を中央リポジトリや他の開発者のリポジトリにプッシュすることができます。このプロセスは、柔軟なワークフローをサポートし、チーム内でのコラボレーションを促進します。

データ保証:Data Assurance

Gitの情報保証機能は、ソフトウェア開発プロセスにおいて重要なセキュリティとデータの完全性を提供します。
Gitは、コミットされたすべてのファイルとディレクトリに対してSHA-1ハッシュを使用してチェックサムを生成します。このチェックサムは、ファイルの内容が何らかの形で変更された場合には変わるため、データの破損や意図しない変更を容易に検出することができます。これにより、Gitリポジトリ内のデータの完全性が保証されます。

ステージングエリア:Staging Area

Gitのステージングエリアは、ソフトウェア開発のワークフローにおける独特な概念の一つです。
ステージングエリアは、変更をコミットする前の準備段階として機能します。開発者は、作業ディレクトリ内で行った変更(新規ファイルの追加、既存ファイルの編集、ファイルの削除など)の中から、コミットに含める変更を選択的にステージングエリアへと移動させることができます。これにより、複数の変更がある場合でも、関連性のある変更のみをグルーピングしてコミットすることが可能になり、プロジェクトの履歴を明確で意味のあるものに保つことができます。

フリーかつオープン:Free and Open Source

Gitは、GNU General Public License version 2の下で配布されており、誰もが自由にダウンロード、使用、修正、および配布することができます。このフリーかつオープンソースなライセンスモデルは、世界中の開発者がGitのコードベースに貢献し、その機能を改善し、新しい機能を追加することを可能にしています。結果として、Gitは迅速に進化し、ソフトウェア開発の新たな要求に対応できるようになっています。

Gitのこれらの特徴は、個人の小規模なプロジェクトから大企業による大規模なソフトウェア開発プロジェクトに至るまで、あらゆるソフトウェア開発ニーズに対応する柔軟性とパワーを提供します。そのため、多くの開発者や企業にとって、Gitはソフトウェア開発プロセスの中心的なツールとなっています。

Gitを利用したコード修正の流れ

Gitを使っての開発の流れを簡単に紹介します。
今回はサンプルとして、ソースコードのtypoを修正します。

Hello World!がHello Warld!となっていた

今回は以下の流れに沿って不具合修正を行います。
より具体的な利用方法については第4回の記事にて詳しく記載します。

1.最新のメインブランチを取得

まずソースコードを修正するために、リモートリポジトリの内容をローカルリポジトリに取得します。
Subversionの場合はチェックアウト、共有フォルダの場合はローカルにダウンロードする行為がそれぞれ該当します。

git clone リポジトリパス

リモートリポジトリから取得が完了しました。

2. 不具合修正のための新しいブランチを作成

不具合修正用の新しいブランチを作成し、そのブランチに切り替えます。ブランチ名は、修正する不具合に関連した名前を付けると良いでしょう。今回は「fix-bug-123」というブランチ名でブランチを作成し、作業を行います。

git switch -c fix-bug-123

このコマンドを実行すると、ローカルに「fix-bug-123」というブランチができます。
ただし、リモートリポジトリに対してはこの時点では何も影響はありません。

作成したローカルリポジトリで開発を進めていきます。

「ブランチ」について
Subversionではブランチはリポジトリ内のディレクトリとしてコピーを作成し、それぞれ独立に運用します。そのため、ブランチ間の変更を追跡するのが困難で、マージも手間がかかる場合があります。
一方、Gitではブランチは独立した作業スペースとして管理され、ブランチ間のマージや切り替えが非常に容易になっています。これにより、複数の機能やバグ修正を同時に開発して、それぞれを独立したブランチで管理し、必要に応じてマージするといった、柔軟な運用が可能となります。

3. 不具合の修正

コードを編集し、不具合を修正します。

修正が完了しました。

修正が完了したら、変更をステージングエリアに追加し、コミットします。コミットメッセージには、修正内容の簡潔な説明とともに、例えば不具合起票のチケット番号など関連する不具合追跡システムのIDを含めることで、後で変更を追跡しやすくなります。

git add .
git commit -m "Fix bug #123: Hello Worldのtypoの修正"

Gitは一度ステージングエリアに変更を追加して管理します。

git add .

このコマンドは現在のディレクトリ(.が現在のディレクトリを指します)およびそのサブディレクトリ内のすべての変更(新規ファイル、変更されたファイル、削除されたファイル)をステージングエリアに追加します。
ステージングエリアは、次にコミットする変更を準備するための一時的な領域です。
この時点では変更はリポジトリの履歴等に登録されません。

git commit -m "Fix bug 123: 詳細な修正内容"

ステージングエリアに追加された変更をローカルリポジトリにコミットします。コミットには、変更に関する詳細なメッセージを付けることが推奨されます。このメッセージは、他の開発者が後でコミットの内容を理解するのに役立ちます。
このcommitコマンドはローカルリポジトリに対しての実行される操作であり、この時点ではリモートリポジトリには変更が反映されていません。

そのため、この時点ではあなた以外の開発者はfix-bug-123というブランチがあることも、現在あなたがどのような修正を加えているか知ることはありません。そのため、自由にコミットして履歴を管理しながら開発を進めることができます。
開発をしていて「動いていたはずのコードが動かなくなったから切り戻したい」「少し検証でsysoutデバッグを仕込みたい。終わったらきれいにしたい(元の状態にもどしたい)」ということがあります。
Gitの場合、ローカルリポジトリでも履歴管理が可能なので、このようなことも容易に実現可能です。

4. 修正をリモートリポジトリにプッシュ

修正を含むブランチをリモートリポジトリにプッシュします。

git push origin fix-bug-123

このコマンドを行った時点で、それまでの修正がリモートリポジトリに反映され、ほかの開発者からもfix-bug-123ブランチが見えるようになります。

実行が完了しました。
リモートリポジトリに修正が反映されました。

5. コードレビューとマージ

リモートリポジトリにpushされたタイミングで、レビュアーはコードのレビューを行うことができるようになります。

レビューに関して、GitHub、GitLab、Bitbucketなどのプラットフォームではプルリクエストやマージリクエストといった便利な機能があります。こちらについては第4回の記事で詳しく触れます。
レビューを通過し、テストが成功したら、修正用に作成したブランチをmainブランチにマージします。
マージするとソースコードだけでなく、fix-bug-123ブランチでの作業履歴がmainブランチにもマージされます。

今回はマージリクエストを利用して、fix-bug-123ブランチの内容をmainブランチにマージします。

マージリクエストを発行し、承認を行うことでマージが完了します。この際にコードレビュー時の指摘点を記録し、GitLab上でコメントのやり取りをすることができます。

後でコードレビューのやり取りを確認することも可能

また、例えばJenkinsを用いてCI環境を構築していればJenkinsの実行結果なども参照可能です。

6.ブランチの削除

一部の運用では、修正用ブランチをmainブランチにマージした後に削除することがあります。
コマンドでリモートリポジトリのfix-bug-123ブランチを削除する場合、以下のように記載します。

git push origin --delete fix-bug-123

補足

今回はコマンドで記載しました。
Gitをコマンドラインで使用する際に、複雑でわかりにくいことが原因でつまづく方が多いように感じています。
ただ、Subversionを利用する際にデファクトスタンダードとなっているTortoiseSVNのGit版と言えるTortoiseGitというツールを用いることもできますし、VSCodeやEclipseといった統合開発環境には統合開発環境上からGitを操作する機能も提供されているため、コマンドを覚えることなく利用することもできます。

まとめ

Gitは、その革新的な特徴と柔軟性により、現代のソフトウェア開発におけるバージョン管理の標準となりました。
次回は、共有フォルダと比較したGitの具体的な利点に焦点を当てます。
共有フォルダと比較し、Gitがいかにして開発プロセスを改善し、チームの生産性を向上させるかを詳しく説明していきます。

宣伝

弊社テクマトリックスでは、「ソフトウェア開発基盤構築ソリューション」として、ソフトウェアの品質を向上させるテスト自動化の基盤構築、ソフトウェア構成管理やクラウドサービスの提供、およびクラウド移行の支援を提供しております。

ソフトウェア構成管理向け環境構築

構成管理に関わる以下のサービスを提供しています。

  • Git環境の構築
  • 既存ツールからのGit移行
  • 構成管理の運用コンサルティング
  • Git構成管理トレーニング
  • ソフトウェア構成管理に関する無償アセスメント

詳細につきましては、次のボタンより参照下さい。

GitとJenkinsで始めるソフトウェア開発 無料ウェビナー

また、定期的に構成管理に関わるウェビナーも実施しております。

Gitはもちろん、CIにも興味がある方はぜひご参加ください。

By nagakubo

主にCI環境構築をメインで担当しています。 Certified CloudBees Jenkins Engineer (CCJE)