皆さん、構成管理に何を使っていますか。

「ファイルサーバで頑張ってます!」という人はいないことを信じて、きっとSVNかGitを使っていることでしょう。

私が新人の頃にはまだまだSVNが主流で、入社時研修からいくつかの案件を通してSVNやVSSを使用していました。

今の会社に入社してから社内標準としてGitに触れ、最近では参画する案件でもGitを使うことが多くなりました。

このGitの使い方(?)に関して、SVNに慣れている・Gitに触ったことが無い方々に申し上げたい。

SVNと同じ感覚で使わないでください。

具体的に言うと、SVNで言うコミットとGitにおけるプッシュを一緒にしないでください。

発端

今回このような記事を書こうと思った理由ですが、先述の通り最近の案件でもGitを使うことが多くなってきました。

そうした中で、参画時に毎回Gitの運用方法を確認しているのですが、どうもSVNと同じような使い方を教えている気がしてならないのです。

複数人に対し、「○○ブランチをプルしてきてください」「タスク完了後はプッシュしてください」。

いや、それ通ったら他の人の変更消えますけど。

もちろん、Gitもそこまで馬鹿ではないのでちゃんとエラーを出してくれますが、そのエラーを見て何かしようと思っても、SourceTreeを使ってもエラーはすべて英語であり、慣れていない人にとってはどう対処したらいいか分からなくなる可能性の方が高いと思います。

アレコレしてるうちにエラーは解消されてプッシュも出来たけど、ローカルの変更内容が全部消えている、なんてことにもなりかねません。

「最近はやりのGitを使ってみよう」という気持ちは分かるのですが、「Gitよくわかんないけど、構成管理なんだからSVNと似たような考え(それはほぼ同じ考え)でいけるだろう」とはならないで頂きたい。

Gitの使用経験がある者としては、SVNと同様に扱われるというのは恐怖でしかありません。

私のGit遍歴

余談ではありますが、私がGitを使ってきた過去を少しお話しようと思います。

興味のない方は次の項へとお進みください。

Gitとの出会い

一番最初のGit経験は今の会社に入社し、一番最初の(1人月くらいの)案件に参画した時でした。

メンバー構成としては40代半ばのリーダー(Git経験者)、私(開発経験あり、Git未経験)ともう一人のメンバー(開発未経験)という感じ。

リーダーは実作業を持っていなかったので、必然的に環境構築は私が担当することに。

それまでの案件では既に環境構築手順書が整備されている状態で仕事をしていたので、自分で開発環境を整えるというのは新鮮な経験でしたね。

ここで慣れないLinuxのコマンドを、これまた慣れていないMacからSSHで接続して叩いたりと、かなり苦労したのを覚えています。

ちなみにリーダーから諸々アドバイスも頂いたのですが、あたかも知っている風に話す割に的を得ておらず、ほとんど役に立たなかったというのも鮮明に覚えています。

かくして初めて触るGitを構築するところから、私のGit使用の歴史は始まりました。

Gitでの苦労 その①

当時はGitbucketとSourceTreeを使用していました。

SourceTreeはまだいいのですが、Gitbucketは全て英語なので理解するのに苦労した記憶があります。

また当時はGitの使い方みたいな記事も、主要コマンドの紹介のみで、開発での利用シーンを考慮した記事もほとんどなかったように思います。

その為、リーダーの要領を得ないアドバイスと、使ってみた感じから「こんな感じで使えばいいのかな」という自分なりの方法で運用していました。

ちなみにその方法というのが、作業ブランチへDevelopブランチをマージするときに、作業内容の保持の為にスタッシュを利用する(逐次ローカルリポジトリへのコミットは行わない)というものでした。

Gitでの苦労 その②

先述の案件が終了し、次に参画した案件でもソース管理にGitを利用することになったのですが、そこでスタッシュの使い方を誤っていたことに気付きます。

スタッシュの使い方、というよりは一連のフローをそもそも誤っていたんでしょうね。

スタッシュを行うにはローカルリポジトリにコミットしていない変更が必要になりますが、一つのタスクに着手している間に(そのタスクが完了するまで)コミットしない、というケースは少ないかと思います。

SVNを使っている案件では、毎日定時前にコミットしてから帰る、というルールが設けられることもあるくらいですからね。

特にその当時携わっていた案件の言語は、開発環境がまだ発展途上だったこともあって、ちょっと変更を加えただけでも意味不明なエラーが頻発するような状況でした。

その為、動いた段階で逐次コミットし、変更を加えたために不具合が発生した時はいつでも動いた段階に戻せるようにしておく必要がありました。

その結果スタッシュが使えないことが判明。Gitの使い方を見直すことになりました。

SVNとGitの違い

様々なサイトなどで取り扱われていると思うので、メリット・デメリットなど詳しくは説明しません。

SVNはリポジトリ(大元)がサーバ上にのみ存在します。なのでコミット後ならローカルが吹っ飛んでも、そのコミット内容はサーバ上で生き続けます。

対してGitはリポジトリ(大元)がサーバ上にある点はSVNと変わらないのですが、このリポジトリをローカル環境にも持つことが出来ます。出来る、というと少し語弊があるかもしれません。

ローカルでの変更内容はローカルのリポジトリにコミットされ、サーバ上のリポジトリと同期をとる必要があります。

仮に、コミットはしたけど同期はとっていないという状況でローカル環境が吹っ飛んだ場合、そのコミット内容も一緒に吹っ飛びます。

Gitの使い方

これまでGitを利用してきた私が辿り着いたフローをご紹介します。とあるプロジェクトで一緒になったGit経験者に聞いても「これだね」って返ってきたので、恐らく運用上問題ないでしょう。

図だけだと不完全なので補足していきます。なお、Masterブランチの作成に関しては省略します。

新規案件のプロジェクトや、既存システムのプロジェクトとして捉えてください。

①Developブランチの作成(リモートリポジトリ)

案件の開始にあたって、新規の場合は一番最初の環境構築あるいは製造開始にあたってベースとなるプロジェクトから、改修の場合は既存のプロジェクトから、Developブランチを作成します。

一つの案件ごとにGitリポジトリを立てることが多いので便宜上名前を「Develop」としていますが、一つのシステムにつき一つのGitリポジトリを立てて、そのシステムに対して継続的に案件が発生するようであれば、プロジェクト名などでもいいかもしれません。

②③作業ブランチの作成(ローカルリポジトリ)

リモートリポジトリに作成したDevelopブランチをローカルリポジトリにプルします。

ローカルブランチにプルしたDevelopブランチから作業ブランチである「Work1」「Work2」を作成します。

これら作業ブランチは、Work1はAさんがローカルで作成したブランチ、Work2はBさんがローカルで作成したブランチ、と捉えて頂いても問題ありません。

④作業ブランチへのコミット(ローカルリポジトリ)

ローカルでの作業内容を都度コミットしていきます。

SVNとは異なり、ローカルリポジトリへのコミットの為、たとえビルドエラーが出ていても本人さえ問題なければ(他の人には全く影響しないので)構いません。

⑤Work1ブランチをDevelopブランチへマージ(リモートリポジトリ)

この辺から少し煩雑になってきます。

Work1ブランチの作業完了時点でDevelopブランチには、Work1ブランチ作成時点以降の変更が加えられていませんので、そのままマージすることが出来ます。

このマージに際してはまずWork1ブランチをリモートリポジトリにプッシュします。

それからWork1ブランチからDevelopブランチへのマージを要求(プルリクエスト・マージリクエストを投げるとも)します。

このプルリクエスト・マージリクエストはGitの管理画面から行うことが出来ます。(SourceTreeからは出したことが無いので分かりません…。)

プルリクエスト・マージリクエストが上がって来たら、Git(リモート)リポジトリの管理者(チームリーダーなど)がその要求内容(変更内容など)を見て、承認あるいは拒否を行います。事実上のコードレビューですね。

ここで承認されれば無事、Developブランチへのマージが完了となります。

⑥Work2ブランチの最新化(ローカルリポジトリ)

Work2ブランチでの作業も終わり、これからDevelopブランチへのマージを行おうという段階です。

ここではDevelopブランチのバージョンに注意する必要があります。

というのも、Work2ブランチを作成した時と現在のDevelopブランチは、Work1の変更がマージされているという点で異なるため、このままでは機械的にマージすることが出来ません。

そこで、Work2ブランチをDevelopブランチの変更(Work1ブランチのマージ分)に合わせて最新化する必要があります。

具体的に何をするかというと、まずリモートリポジトリのDevelopブランチをプルして、ローカルリポジトリのDevelopブランチを最新化します。

その後、ローカルリポジトリのDevelopブランチを、同じくローカルリポジトリのWork2ブランチに対してマージします。

これでWork2ブランチの最新化が完了したことになります。

⑦Work2ブランチをDevelopブランチへマージ(リモートリポジトリ)

⑥でWork2ブランチをDevelopブランチへとマージできるように最新化したので、作業としては⑤と同じです。

Work2ブランチをリモートリポジトリにプッシュし、Developブランチに対するプルリクエスト・マージリクエストを作成します。

Gitリポジトリ管理者はリクエストを受けて変更内容を確認し、承認されればWork2ブランチのDevelopブランチへのマージは完了となります。

⑧DevelopブランチをMasterブランチへマージ(リモートリポジトリ)

案件の最後、もうソースに変更はありませんよ、という段階になってMasterブランチへのマージを行います。

Masterブランチに対しては、Developブランチを作成した時点から他の変更が加わっていない為、そのままプルリクエスト・マージリクエストを作成することが出来ます。

Masterブランチをリリースして、案件が終了となります。

最後に

今回このお話のターゲットとなる方は、SVNの考えに則って、⑤⑥⑦⑧の細かいところを見落としがちではないでしょうか。

今回ご紹介した運用方法はあくまで私(+α)の行き着いた方法であり、「これよりももっといい方法がある!」「ここをこういう風にするとよりいい!」というご意見は大歓迎です。

以上です。(アイコン:Git icon icon by Icons8

スポンサーリンク