GitとSubversionの構造的な違い|GitのブランチはSubversionのブランチとは全く違うモノ

Author

奥村 和彦Kazuhiko Okumura

奥村 和彦

こんにちは。プリセールスエンジニアの奥村です。

最近はVCS(バージョン管理システム)のデファクトスタンダードと言っても過言ではないGitですが、まだまだSubversionをご利用されているお客様も多く「Git(Bitbucket)に移行したいがSubversionとの違いやメリットがよくわからない。」と言ったご質問をいただくことがあります。

私自身もこれまでの職場ではSubversionもしくはCVSを利用していて、Gitは勉強用のスニペットコードで利用する程度でしたので同様の疑問を持っていたのですが、リックソフトでBitbucketに触れたことでGitとSubversionとの違いやGitの良さを実感することが出来ました。そこで私が勉強した中でも特にGitを理解することに役立ちました、GitとSubversionの構造的な違いについてお話ししたいと思います。

今回のブログではGitコマンドの説明や使い方までは触れておりません。ですがGitコマンドをご理解する上できっとお役に立つ話だと思います。

Gitは分散型リポジトリです

Gitは分散型バージョン管理システム(Distributed Version Control System)と呼ばれます。その対比として、Subversionは集中型バージョン管理システム(Centrlized Version Control System)と呼ばれることもあります。

Subversionはサーバーにインストールした"リモートリポジトリ"だけが、ソースコードのバージョンを管理しています。開発者はリモートリポジトリにアクセスして自分のローカルPCに指定したバージョンのソースコードをダウンロード[チェックアウト]して開発します。修正や追加したソースコードはリモートリポジトリへ登録[コミット]します。

コミット

それに対してGitは開発者自身のローカルPCに"ローカルリポジトリ"を持ちます。開発者はこのローカルリポジトリに修正や追加したソースコードをコミットするのがSubversionとの大きな違いです。

ローカルリポジトリはリモートリポジトリの完全なコピー["クローン"]として作成します。ローカルリポジトリにコミットしたソースコードは、リモートリポジトリに反映["プッシュ"]することでローカルリポジトリとリモートリポジトリの内容を同じに合わせます。個々のローカルPCにもリポジトリを構築するので分散型と呼ばれています。

分散型

分散型バージョン管理は集中型と比べて次のようなメリットがあります。

コミットの都度、リモートリポジトリにアクセスする必要がありません

ローカルリポジトリでソースコードを管理するので「ブランチを切り替える」「コミットする」「差分を比較する」「マージする」といった操作の度にリモートリポジトリアクセスする必要がありません。
(※リモートリポジトリとは定期的に通信して最新情報を取得しておく必要はありますが。)

ローカルリポジトリで自由なブランチ管理やコミットができます

ローカルリポジトリは自分専用のリポジトリとなるので、ちょっとしたことを試したいときに気軽にブランチを作成してコミットすることができます。作成したブランチやコミットはマージするときに新しいコミットにまとめること[squash]ができますので、ちょっとしたブランチやコミットを正式な"開発コミット"に整えてからリモートリポジトリにプッシュできます。

リポジトリに障害が発生したときに別のリポジトリから復元できます

リモートリポジトリとローカルリポジトリは完全なコピーですので、リモートリポジトリに障害が発生してもローカルリポジトリから復元することができます。
(※復元する元のローカルリポジトリに最新情報が取り込まれている["フェッチ"]場合に限りますが。)

複数のリモートリポジトリに関連づけることができます

リモートリポジトリから別のリモートリポジトリをコピー["フォーク"]した場合、ローカルリポジトリはフォーク元とフォーク先の両方のリモートリポジトリとアクセスして同期することができます。これを利用すると例えば、あるパッケージ製品のリポジトリからお客様向けにカスタマイズしたリポジトリをフォークした場合、ローカルリポジトリでコミットしたパッケージのバグ修正や機能開発をパッケージリポジトリとカスタマイズリポジトリの両方へプッシュでき、フォーク元とフォーク先のリポジトリの共通部分を同期させることができます。

分散型であるGitに移行してもコミットやマージはSubversionと同じ感覚で使うことができます。また新たにプッシュやフェッチ、プルといった操作が追加されますが、分散型リポジトリの仕組みを理解することでそれほど難しい操作でないことは感じ取っていただけると思います。

GitのブランチはSubversionのブランチとは全く違うモノです

SubversionとGitの大きな違いはブランチ管理あると私は考えています。最近のソースコードのバージョン管理では、機能開発やバグ修正の専用ブランチを作ってリリース用ブランチへマージする開発スタイルが主流になってきており、開発プロジェクトにおいてコードのブランチ管理は必要不可欠であると言えます。ですがSubversionのブランチ管理はとても難しいため、次のような経験があるユーザーも多いのではないでしょうか?

  • ブランチ作成スピードが遅い
  • ソースコードの差分比較処理が遅い
  • 正しくマージされない
  • コンフリクトの解消方法が分かりづらい
  • よくわからないコンフリクトが発生する
  • 解消したコンフリクトが何度も発生する
  • よくわからないので更新ファイルを退避してから、ローカルPCのワークディレクトリを全削除して、チェックアウトし直す
  • よくわからないので更新ファイルを退避してから、ブランチを削除してから、ブランチを再作成する

これはSubversionの変更管理方法がファイルごとに変更履歴を管理していることに起因します。ある時点から現在までの変更内容を抽出するには期間内の変更履歴を順番に追跡する必要があります。またSubversionのブランチは単なるコピーです。しかしコピーした後は同期しないため、変更履歴はコピー元とコピー先で異なり、マージするときはそれぞれの変更履歴を追跡しながら処理しなければなりません。もちろんSubversionでこの処理を最適化するような仕組みはありますが処理としては少し複雑な感じがします。

ここからSubversionは差分比較に弱いためマージやコンフリクトに掛かるコストが高く、ブランチ運用が難しいことがお分かりいただけると思います。

ブランチ運用が難しい

その点GitはSubversionとは真逆と言っても過言では無いほど異なるアプローチでブランチを管理します。ポイントは2つです。

コミットにその時点の全ファイルの情報を持つ

Gitはコミット単位に変更履歴を管理しています。コミットを行うと次のような情報を登録します。

  • コミットのリビジョンID(ファイルのチェックサムから算出)
  • 一つ前のリビジョンID
  • 全ファイルのツリー情報のスナップショット

このコミット情報により2つのコミット間の差分はスナップショット同士を比較するだけで済みます。どれだけコミット数が多くなっても、複雑になっても比較対象のコミット同士だけで、差分の比較が出来て、コンフリクトの箇所やマージする部分が容易に特定できます。

また一つ前のリビジョンIDによってリポジトリ内の全てのコミットをツリーで表現してコミット履歴を追跡することができます。

てコミット履歴を追跡

全てのリポジトリが同じコミットツリーを共有する

リモートリポジトリからクローンしたローカルリポジトリはコミット情報の内容や構造も全て同じな完全なコピーです。クローンした後もリモートリポジトリとローカルリポジトリ間の同期(プッシュやフェッチ、プルなど)によって同じ情報を維持します。これによって複数ユーザーが個々のローカルリポジトリで行ったコミットであってもリモートリポジトリを通して共有化されますので、コンフリクトの解消やマージ処理が簡単に実施できるようになっています。

全てのリポジトリが同じコミットツリーを共有

Gitのブランチの正体

本題のGitのブランチですがここまでの説明でピンっと来た方もいるかもしれませんが、コミット情報がそのまま"ブランチ"として扱われます。なぜならGitのコミット情報は「その時点の全ファイルの情報スナップショット」を持っているためで、Gitのブランチは膨大なコミットの中から、ある一つのコミットに目印を付けているのです。

以下の表は、Gitブランチに対する操作イメージです。

Gitブランチの操作 行なっていることのイメージ
作成 最新コミット情報に目印をつける
コミット コミット情報を作成して目印を移動する
マージ コミット情報間のファイルをマージして、新しいコミット情報を造りそこに目印を移動する。
※マージの方法は幾つかあり、上記とは異なるケースもあります。)
削除 コミット情報から目印を無くすこと(コミット情報は削除しない)

Gitのブランチは差分比較に強くマージやコンフリクトに掛かるコストも低いことがお分かりいただけるでしょうか。Gitのブランチは変幻自在なのです。

Gitのブランチは変幻自在

Gitは「分散型リポジトリ」や「コミットの変更履歴を活用したブランチ」といったSubversionとは全く異なる発想で作られたバージョン管理システムです。その仕組みは、現在のアジャイル開発やDevOpsといった高い生産性が求められる開発フローにとても合っていると思います。
Gitのようにツールを導入する際には学習コストも掛かるのですが、今回説明したGitの構造およびSubversionとの違いをご理解いただければ少しでもスムーズな切り替えを可能にすると考えています。特にGitの`branch`,`rebase`,'merge(Fast-Forward/Mergeコミット/squash)'と言ったコマンドを理解するのに役立てられると思います。

BitbucketはGitのホスティングサービスです

最後にGitのホスティングサービス、AtlassianのBitbucketをご紹介させてください。

Gitのホスティングサービスとは、リモートリポジトリを管理するWebアプリケーションです。Gitはコマンド(CUI)を使って操作しますが、これをWeb画面のGUIで操作することができます。その他にもホスティングサービスごとに特有のGitの拡張機能を搭載します。Gitホスティングサービスの代表的な製品と言えばGitHubだと思いますが、BitbucketもGitHubと同等の機能やAtlassian製品ならではの機能があります。

今回はオンプレミス用のBitbucket Severの特徴について紹介します。

Gitのリモートリポジトリをグラフィカルなインターフェースで管理できる。

リモートリポジトリ内のソースコードを確認したり、コミット履歴から変更内容や差分情報を画面で確認できます。また、ユーザーのプロフィールや権限の管理、リポジトリやブランチのアクセス権限の設定などをグラフィカルなインターフェースを通して操作できるため、Gitの管理が容易になります。

Gitのリモートリポジトリをグラフィカルなインターフェースで管理できる

ソースコードにレビューコメントを記録できます

コミット情報にステップ単位でコメントを入力し、チームのコードレビューやコミュニケーションを記録することができます。

ソースコードにレビューコメントを記録できます

プルリクエスト機能が使えます

開発用に作成したブランチのコードを元のブランチにマージするためのレビューと承認依頼が行える、プルリクエスト(プルリク)が利用できます。プルリクを利用することでmainブランチなどの本番用開発コードへ、不用意にマージされることを防ぐことができます。

またプルリクエスト承認後のブランチのマージ戦略(Mergeコミット/Fast-Forward/Squash/Rebase)やgit-flowに従ったブランチ戦略の設定も行えるのはBitbucketの特徴の一つです。

プルリクエスト機能が使えます

Atlassian製品特有の機能があります

BitbucketはJiraやBambooといったAtlassian製品と連携することで強力なアプリケーション連携機能を利用することができます。
更にBitbucket DataCenterであればアクティブ-アクティブクラスタリングやスマートミラーリングによる耐障害性や可用性、信頼性を向上させることもできます。

Atlassian製品特有の機能があります

SubversionからGitに移行したくなったら

Subversion(あるいはCVS)と比較し、GitおよびGitのホスティングサービスを導入することで、開発の効率化やスピードアップおよび生産性向上が期待できそうに感じていただけたでしょうか?

特にソースコードのマージ処理では、Gitの分散型リポジトリやブランチ管理によってコンフリクトの発生自体を減らしたり、コンフリクトを解消する作業が簡単になると思います。

Git自体はフリーで利用できますが、リポジトリの運用管理やプルリクエストと言ったコードの品質を上げるための拡張機能を持つGitホスティングサービスを導入することで更に開発効率が上がりますし、開発も楽しくなると思います。
この分野ではGitHubが有力なツールだとは思いますが、セキュリティポリシーや運用ルールの制約でオンプレミスやプライベートクラウドでGitを利用する必要があったり、AtlassianのJiraとの連携をお考えでしたらBitbucket Serverに歩があります。

BitbucketでのGitの導入をお考えでしたら、お気軽にリックソフトにご相談ください。

お問い合わせはこちらから。

デモや製品説明のご相談

製品について詳しくはこちらをご覧ください。

Bitbucket

この機会にぜひお試しください。

30日無料トライアル申し込みはこちら