EurekaMoments

新米エンジニアが一人前を目指す修行の日々を記していくブログです。

Gitによる複数人でのバージョン管理をSourceTreeを使って体験してみる

はじめに

今の職場におけるバージョン管理システムをSVNからGitに変更することを提案したいと考えており、それの参考にと思い下記の書籍を読みました。

いちばんやさしいGit&GitHubの教本 人気講師が教えるバージョン管理&共有入門 (「いちばんやさしい教本」シリーズ)

いちばんやさしいGit&GitHubの教本 人気講師が教えるバージョン管理&共有入門 (「いちばんやさしい教本」シリーズ)

インストールや初期設定の手順から、実際にブランチを切りながらバージョン管理していく流れまで述べられていて大変参考になりました。ただし、これらは全てGit bashからのコマンド操作によるものがメインであり、今後職場で導入提案をするならGUIツールを使った場合の操作手順を把握しておきたいと考えました。
今回の記事では、GitのGUIツールとして人気の高いSourceTreeを使いながら、Gitでの複数人バージョン管理を一人で自作自演しながら体験してみた流れを紹介していきます。

前提条件

  • Gitのインストール及び初期設定が既に完了している
  • OS: Windows 10 Home 64bit
  • リモートリポジトリはGitHub上に作成

作業対象とするGitHubリポジトリ

今回は下記のリモートリポジトリをクローンして作業します。
github.com

SourceTreeについて

SourceTreeのインストール手順や基本的な使い方については、下記の記事に分かりやすく書かれているので参照ください。
prog-8.com

今回のシナリオ

  • 作業者: Shisato(自分)、作業者A、作業者Bの3名
  • 全体の作業内容: 上記リポジトリのREADME.mdのファイルに、本記事と同じ内容の文章を書く。
  • Shisatoの作業ブランチ: タイトルから導入部分まで
  • Aの作業ブランチ: メイン内容の部分
  • Bの作業ブランチ: 参考資料の部分
  • Step1: リモートリポジトリをローカルにクローンする
  • Step2: 3人それぞれのブランチをmasterから作成して作業開始
  • Step3: Bの作業が先に完了→プルリクを作成してマージ
  • Step4: Shisatoの作業ブランチにBの完了分をマージして作業継続→完了したらプルリクを作成してマージ
  • Step5: Aの作業ブランチにShisatoとBの完了分をマージして作業継続→完了したらプルリクを作成してマージ
  • Step6: 追加作業でブランチ作成してマージしようとしたらコンフリクト→コンフリクトを解消してマージ

Step1: リモートリポジトリをローカルにクローンする

まずは、リモートリポジトリをローカルリポジトリにクローンするためのフォルダを作成します。今回は、GitWithSourcetreeという名前のフォルダを作りました。

f:id:sy4310:20190105145859p:plain

そして次に、SourceTreeを開いてリモートリポジトリをクローンします。新しいタブを開いて上のメニューから「Clone」を選ぶと、下記の画面のようにクローンの操作を行う画面に遷移します。続いて、上から順にリモートリポジトリのURL、既に作成したクローン先のローカルフォルダ、ブックマーク名を入力します。

f:id:sy4310:20190105151450p:plain

最後に、画面したの青ボタン「クローン」をクリックすると、先ほど設定したローカルフォルダにリモートリポジトリの中身がクローンされ、SourceTree上ではそのリポジトリのバージョン管理を可視化する画面に遷移します。

f:id:sy4310:20190105152931p:plain

f:id:sy4310:20190105153015p:plain

Step2: 3人それぞれのブランチをmasterから作成して作業開始

現時点のSourceTreeの画面の左上メニューから「ブランチ」を選択します。

f:id:sy4310:20190105155056p:plain

選択すると下記のようにブランチ作成画面に映ります。

f:id:sy4310:20190105155624p:plain

ここで入力する各項目の意味は下記の表の通りです。
ここでは、まず3人分の作業ブランチを作ってしまうので、新規ブランチ作成後のチェックアウトの項目のチェックは外しておきます。

f:id:sy4310:20190105155508p:plain

最後に「ブランチを作成」ボタンをクリックすると、親のmasterブランチを起点にしたトピックブランチが作成されます。ここまでの操作を繰り返して、下記の3つの作業ブランチを作成します。

  • Shisatoの作業ブランチ: Introduction_Shisato
  • Aの作業ブランチ: Main_A
  • Bの作業ブランチ: Reference_B

作成後のSourceTreeの画面は下記のようになり、ベースとなるmasterブランチと同じ状態で上記の3つのブランチが作成されていることが分かります。

f:id:sy4310:20190105161355p:plain

Step3: Bの作業が先に完了→プルリクを作成してマージ

ここからは分担した作業ごとにブランチを切り替えながら進めていきます。SourceTree上でブランチを切り替える際は、下記の画面で切り替えたいブランチ名をダブルクリックすることで切り替わります。

f:id:sy4310:20190105164018p:plain

最初はmasterブランチになっているので、上記の画面ではmasterの横に印が付いています。ここではまず、一番作業量が少ないBが先に作業を終えてマージするというシナリオなので、作業ブランチをmasterからReference_Bブランチに切り替えます。上記の画面でReference_Bの名前をダブルクリックすると、作業ブランチがReference_Bブランチに切り替わり、下記の画面のようになります。

f:id:sy4310:20190105165337p:plain

作業対象ファイルであるREADME.mdは、クローン直後では下記のような状態であり、タイトルと概要のみが書かれています。これに、Bの担当分である参考資料のパートを追加します。

f:id:sy4310:20190105171749p:plain

追加した後のファイルは下記のようになります。

f:id:sy4310:20190105174048p:plain

ファイルの編集が終わったところで、SourceTreeの画面に戻ってみましょう。すると、下記のように画面が更新され、コミットされていない変更があるということが示されています。

f:id:sy4310:20190105174359p:plain

まずは、編集したファイルをステージに追加しましょう。画面左下の「作業ツリーのファイル」から対象ファイルを選択して右クリックし、メニューから「追加」を選びます。すると、下記画面のようにコミット対象としてステージに追加された状態に遷移します。今度は、「Indexにステージしたファイル」のグループに移動していることが分かります。

f:id:sy4310:20190105175032p:plain

そして今度は、左上のメニューから「コミット」を選択します。

f:id:sy4310:20190105181138p:plain

すると下記の画面に遷移するので、画面下のコメント欄にコメントを記入して、右下の「コミット」ボタンを押します。これでコミットは完了です。

f:id:sy4310:20190105181819p:plain

そして今度は、このコミット内容をリモート側に反映させるためにプッシュを行います。コミット後の画面左のブランチ一覧から現在作業中のReference_Bブランチを右クリックします。

f:id:sy4310:20190105182740p:plain

右クリック後に開いたメニューから「プッシュ先」を選択し、そこで表示されるものの中から「origin」を選択します。すると、下記のようにプッシュ操作を行う画面が開きます。

f:id:sy4310:20190105184022p:plain

ここで、プッシュ先のリポジトリがorigin、対象のローカルブランチとリモートブランチがReference_Bとなっていて、かつチェックが付いていることを確認し、問題がなければ右下の「プッシュ」ボタンを押します。それによって、リモートのoriginリポジトリのReference_BブランチとローカルのReference_Bブランチが同期され、SourceTree上では下記のような状態になります。

f:id:sy4310:20190105190517p:plain

さて、ここまで来てようやくマージ作業に移れます。GitHub上のリモートリポジトリをブラウザで開くと下記画面のようになるので、ここからプルリクエストを作成しましょう。

f:id:sy4310:20190105191814p:plain

今回は作業者は3人ですが、Gitのアカウントは自分一人だけなのでReviewerの設定などは行わず、そのままプルリクエストを作成します。

f:id:sy4310:20190105192518p:plain

完全に自作自演ですが、一応変更内容をレビューして問題がないことをコメントしてからマージします。

f:id:sy4310:20190105193114p:plain

マージ後に、GitHub上でCommits履歴が下記のようになっていれば無事にマージは完了です。

f:id:sy4310:20190105193914p:plain

Step4: Shisatoの作業ブランチにBの完了分をマージして作業継続→完了したらプルリクを作成してマージ

ここからは、作業ブランチをShisato担当分のIntroduction_Shisatoブランチに切り替えて進めます。ただその前に、まずはBによってリモートにマージされた分をローカルに反映しておきましょう。SourceTreeでブランチをmasterに切り替えると、プルで反映するべき変更が示されるようになります。

f:id:sy4310:20190105194843p:plain

左側のブランチからmasterを右クリックし、メニューから「origin/masterをプル」を選択するとプル操作を行う画面が開きます。プル元のリポジトリがorigin、ブランチがmaster、プル先のローカルブランチがmasterであることを確認したら「OK」を押します。すると、リモート側の変更がローカルのmasterブランチに反映されます。

f:id:sy4310:20190105203130p:plain

次に、これから作業するIntroduction_Shisatoブランチに切り替えて、masterに取り込んだ変更をマージします。ブランチを切り替え、画面上のメニューから「マージ」を選択すると、現在のブランチにマージするコミットを選択する画面が開きます。

f:id:sy4310:20190105204108p:plain

ここでコミットをmasterブランチにおける最新のものにして「OK」とすれば、そのコミットがIntroduction_Shisatoブランチにマージされて、下記のようにmasterブランチと肩を並べた状態になります。

f:id:sy4310:20190105212736p:plain

ここから、Shisatoの担当分であるメイン内容手前までの部分を追加して、前述した通りの手順でコミット、マージを行いこのステップは完了です。
マージして、ローカルのmasterブランチに反映させた状態は下記の通りになります。

f:id:sy4310:20190105222051p:plain

Step5: Aの作業ブランチにShisatoとBの完了分をマージして作業継続→完了したらプルリクを作成してマージ

Step4までの間でShisatoとBがコミット、マージした分を、まずはMain_Aブランチにマージします。チェックアウトで作業ブランチをMain_Aブランチに切り替えて、それにmasterブランチへの最新コミットをマージします。
そして、この記事のメインであるStep1~Step5までの作業分をマージした後のリモートブランチであるorigin/masterのコミット履歴は下記のようになります。ちょっとファイルの保存忘れで一部コミットから漏れてしまった部分があったので、最後に再度コミットし直しています。

f:id:sy4310:20190106001531p:plain

Step6: 追加作業でブランチ作成してマージしようとしたらコンフリクト→コンフリクトを解消してマージ

最後に、masterブランチとトピックブランチとの間で変更をコンフリクトを起こした場合の対処も試してみます。内容としては、Step5までにかけて修正してきたREADME.mdファイルの冒頭のタイトル部分をお互いに異なる修正をしてコミットしてしまったというものです。
まずは、作業用のトピックブランチとしてmodify_titleというブランチを作成してチェックアウトします。

f:id:sy4310:20190106004504p:plain

そして、タイトル部分に対して下記のような修正を加えてコミット、プッシュし、プルリクエストを作成した状態で放置します。

f:id:sy4310:20190106004715p:plain

今度は、作業ブランチをmasterに切り替え、同じタイトル部分に先程とは異なる修正を加えてみます。この作業では修正してからローカルのmasterブランチにコミット、プッシュするところまで行います。加える修正の内容は下記の通りです。

f:id:sy4310:20190106013349p:plain

この時点で両ブランチのコミット履歴は下記の通りになっています。

f:id:sy4310:20190106013751p:plain

ここで、作業ブランチをmodify_titleブランチに切り替えて、masterブランチに入った変更をマージしてみます。すると、同じ部分に対して異なる変更を加えたためにコンフリクトが起きました。SourceTree上でマージ後にコンフリクトを起こした際は、下記のような警告メッセージが表示されます。

f:id:sy4310:20190106014522p:plain

このようにコンフリクトが起きた際は、コンフリクトを起こしたファイルを開いて正しく編集し直してから再度コミット、プッシュします。ファイルをエディタで開いてみると、下記のようにmodify_title側と、取り込んだmaster側の両方の変更が表示されており、比較できるようにしてくれます。

f:id:sy4310:20190106015259p:plain

ここは一旦コンフリクトを解消するために、取り込んだmaster側の変更を取り込む形でファイルを編集するということで下記のようにします。

f:id:sy4310:20190106020846p:plain

そして、これを再度コミット、プッシュしてプルリクエストを作成し直せば正常にマージできるようになります。

最終的なコミット履歴

コンフリクト後に細かいところを直して、最終的に全ての変更をコミットした後の履歴は下記のようになります。ここでは、SourceTree、GitHub、Visual Studio Codeでそれぞれ可視化した履歴を比べてみようと思います。

SourceTreeで可視化した履歴

もう少し広いスペースで見やすく表示してくれたらいい、という印象。
f:id:sy4310:20190106121459p:plain

GitHubで可視化した履歴

文字が大きめで見やすくなっていて、コミットした作業者がだれかもアイコン付きで分かるのでいいですね。ただし樹形図が表示されないので、ブランチの分かれ方をちゃんと管理するなら、まだSourceTreeの方がマシかなと感じました。
f:id:sy4310:20190106123147p:plain

Visual Studio Codeで可視化した履歴

Git Historyという拡張機能によって可視化したものですが、SourceTreeとGitHubのいいとこ取りをしたような可視化でいい感じですね。コミットやマージなどの操作もできるのでいいのですが、操作の仕方はSourceTreeの方が分かりやすいと思います。 f:id:sy4310:20190106124128p:plain

比較した感想

トータルで見ればSourceTreeがベストかな、と感じました。バージョン管理の操作はSourceTree、ファイル編集はVisual Studio Code、変更のレビューやマージはGitHubというようにそれぞれの役割を決めて、三者を組み合わせるのが今のところ一番だと思います。

参考資料