SI業界で脱トノサマSE

上流SI企業のSEがトノサマ商売を脱却するために技術を学ぶためのブログ

SVNしか知らなかった人が調べたGitの特徴

こんにちは。脱トノ(@DatsuTONOSAMA)です。
今日はバージョン管理ツールについてです。
私は今までバージョン管理ツールとして利用したことがあったのは

の2種類でした。特にSVNについては入社後初めて配属されたPJから直前のPJにおいてまで、ずっと利用してきました。
しかし、現在のPJではGitを利用しています。Gitと言うものを知ってから何度か使い方等について調べては見たのですが、いまいち頭に入ってこず、また仕事で使うこともなかったので敬遠していたのですが、いよいよ使い方を学ぶ必要が出てきたので、この場を借りて自分の理解とメモを残していこうと思います。

Gitについて

Gitの成り立ち

Wikipediaより引用

Git(ギット[2][3][4])は、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。Linuxカーネルソースコード管理に用いるためにリーナス・トーバルズによって開発され、それ以降ほかの多くのプロジェクトで採用されている。Linuxカーネルのような巨大プロジェクトにも対応できるように、動作速度に重点が置かれている。

動作速度に重点が置かれているというのが特徴のようですね。

リーナスは以下のような原則に基づいて設計を行っている。
CVSを「悪い見本」とする。設計上のことで確信が持てない場合は、CVSと逆の決断をする。リーナスは冗談めかして以下のように語っている。 “カーネルメンテナンスの最初の10年間、僕らは文字通りtarボールとパッチを使っていた。CVSよりもずっと優れたソース管理システムさ。僕は営利企業 (トランスメタ[32]) でCVSを7年間使わされたことで、CVSを強烈に憎むようになった。CVSを強烈に憎んでいると言う時には、このことも言っておかなくちゃいけないね。観衆の中にSVNSubversion)のユーザがいるなら、この場から去ったほうがいいかもしれない。僕がCVSを強烈に嫌悪しているということは、僕がSubversionが史上最大の無意味なプロジェクトであると思っていることも意味しているんだ。Subversionのしばらくのスローガンは‘ちゃんとCVSをやる’とかそんなものだったよね。そんなスローガンから始めたら、どこにも辿りつけないよ。CVSをちゃんとやるなんて不可能なのさ。”[

CVSSVN)が憎まれているというのが個人的にはツボでした。

Gitの特徴

GitはSVNと同じくバージョン管理ツールです。大きな違いは分散型リポジトリであるということ。SVN集中型リポジトリです。
私がGitについてよくわからないと思ったのがこの分散型リポジトリという言葉です。改めてこの言葉について調べてみました。

集中型リポジトリ

  • 一つのリポジトリに対して開発者がそれぞれアクセスし、チェックアウトやコミットをしていく。
  • コミットしたものはリポジトリに即反映される。

f:id:chika0321:20170618230403p:plain

分散型リポジトリ

f:id:chika0321:20170618230414p:plain

これだけではいまいちよくわからないですが、分散型リポジトリのメリットは以下であると私は理解しています。

  • リポジトリがローカルとリモートと2つあるので、開発者はローカルで好きに開発が可能(履歴管理が可能)で、必要なものだけをリモートリポジトリ(他の人と共有しているリポジトリ)にアップロードすることができる

SVNでもやろうと思えばできる気がしますが、SVNにおいてリポジトリが別になるとmergeとかのコマンドって使えないんですよね。
Gitの場合は一つのカタマリ(プロジェクト?)の中で複数のリポジトリが持てるので、「開発者がそれぞれ個人のリポジトリを持って、更にそれを集めてくるリポジトリがある」というのがポイントだと理解してます。

また、SVNと大きく異なるのはステージの概念だと個人的に思っています。
SVNを利用する際には、

  1. ファイルを作成
  2. ファイル管理に対象とする(addする)
  3. リポジトリにコミットする

の流れかと思いますが、Gitの場合、

  1. ファイルを作成
  2. ステージに追加(addする)
  3. ローカルリポジトリにコミットする
  4. リモートリポジトリにpushする

となります。ここで注目してほしいのが2.のところ。
SVNの場合はファイル管理に入れるかどうか(履歴はまだ見えない)だけですが、Gitの場合にはステージに追加した時点である種のファイル管理が始まっています。ステージに追加した時点で、リポジトリに追加したファイルの圧縮ファイルがリポジトリに追加されているためです。
ローカルにリポジトリを保持しているからこそですね。

GitHub

Gitについて調べていると必ず出てくるのがGitHubです。知っている人にとっては常識かもしれないですが、ド素人なりの理解を書いておきます。

wikipediaより引用

GitHub(ギットハブ)はソフトウェア開発プロジェクトのための共有ウェブサービスであり、Gitバージョン管理システムを使用する。 Ruby on RailsおよびErlangで記述されており、GitHub社によって保守されている。 主な開発者はChris Wanstrath、PJ Hyett、Tom Preston-Wernerである。 GitHub商用プランおよびオープンソースプロジェクト向けの無料アカウントを提供している。

Gitで登場するリモートリポジトリのホスティングサービスであるという理解です。
様々なOSSの開発がGitHub上で行われており、新参でもかんたんにOSS開発に参加できる、ということを実現しているのがGitHub

基本は無料で利用できますが、その場合はリポジトリがPublicになります。企業などで導入する場合、有料アカウントを作成して、Privateにすることも可能です。

Gitの基本コマンド

まだあまり使用したことがないですが、基本的なコマンドを書いておきます。

ファイルの取得

  • clone
  • リモートにあるリポジトリをローカルに複製する。svn checkoutと同じイメージ。
  • pull
  • リモートリポジトリから更新分のソースコードを取得する。svn updateに相当する。
  • fetch
  • pullに似ているが、リポジトリから取得したソースコードを、ローカルのソースにマージしない。差分を逐一確認してからマージしたい場合などに利用する。

ファイルのアップロード

  • add
  • ステージに追加=インデックスに登録。svn addに相当する。コミットのたびに必要。
  • commit
  • コミットする。svn commit とほぼ同じ。
  • push
  • リモートリポジトリへローカルのソースコードを反映させる。subversionにはないコマンド。リモートリポジトリへのcommitのイメージ。

その他

  • git reset HEAD^
  • 直前のコミットをなかったことにし(履歴も取り消す) 直前のコミットでコミットされたファイルは、ファイル内容はそのままで作業ディレクトリに移動する

わかりにくかったところ

作業リポジトリの概念

SVNしか知らなかった私にとってはリポジトリが2つあるということが非常に分かりづらかったです。
またそれに付随して、自分が作業しているリポジトリがどこかということを意識しながら作業するということも若干の違和感でした。

コマンドラインでgitを操作する場合、以下のような作業イメージになります。

# originブランチをmasterブランチ(ローカル)に持ってくる
git checkout origin master
# hoge.javaをコミット
git add hoge.java
git commit hoge.java
# バグフィックス用のブランチを作成
git branch bugfix
# 作業用ブランチをbugfixに切り替える ・・・ ★1
git checkout bugfix
# hoge.javaを修正してコミット
git add hoge.java
git commit hoge.java
#メインブランチに切り替え ・・・ ★2
git checkout master

★1を実行すると、作業用のディレクトリの中身がbugfixディレクトリ用に切り替わります。このときにはディレクトリパスは変わらず、中身のファイルだけが変わります。
そして★2を実行すると、bugfixブランチで修正したhoge.javaの中身が戻り、masterブランチのものに戻ります。
つまり、作業ディレクトリが1つの状態で、ローカルリポジトリ内の複数のブランチを切り替えながら作業することとなります。

SVNの場合には作業ディレクトリをそれぞれチェックアウトして作業します。eclipseを使う際にもworkspaceをそれぞれ作成して作業します。これを一つのディレクトリで実施するイメージですね。
これのメリットは作業時にいちいちディレクトリ移動せずにすむということでしょうか。まだあまりメリットは理解できていないです。。
一方でデメリットとしてはどこで作業しているかを常に意識していないと作業ミスが発生しやすいということでしょうか。
SVNにはswitchコマンドがあり、上記のような作業もやることは可能ですが、SVNの場合にはネットワーク越しのチェックアウトとなるため時間がかかります。Gitの場合は上記コマンドはすべてローカルでの実行となるため、素早く作業ができるというのがポイントだと思います。




Gitは現在の開発現場では常識となっていると思います。ただ、私が今まで参画してきたようなウォーターホールですすめる基幹システム開発の現場などでは、SVNが現役で利用されています。
今後のことを考えると、やはりGitに慣れておくことがエンジニアとして生きていくためには必要不可欠だろうと感じています。