Git Workflowとは、Gitを使って一貫性のある生産的な方法で仕事を遂行するためのレシピや推奨事項です。 Gitワークフローは、ユーザーがGitを効果的かつ一貫して活用することを促します。 Gitには、ユーザーが変更を管理する方法に多くの柔軟性があります。 柔軟性を重視するGitには、Gitとの付き合い方についての標準的なプロセスはありません。 Git で管理されたプロジェクトにチームで参加する際には、変更の流れをどのように適用するかについて、チーム全員が合意していることを確認することが重要です。 チームの意見が一致していることを確認するためには、Git ワークフローを作成したり選択したりする必要があります。 公表されているGitワークフローの中には、あなたのチームに適したものがいくつかあります。
さまざまなワークフローがあるため、職場に Git を導入する際にどこから始めればよいのかわかりません。
これらのワークフローは、具体的なルールではなく、ガイドラインとして設計されていることを覚えておいてください。
成功するGitワークフローとは?
チームのためにワークフローを評価する際には、チームの文化を考慮することが最も重要です。 ワークフローはチームの有効性を高め、生産性を制限する重荷にならないようにしたいものです。
- このワークフローはチームのサイズに合わせて拡張できるか
- このワークフローでミスやエラーを元に戻すのは簡単か
- このワークフローはチームに新たな不必要な認知的オーバーヘッドを課していないか
- このワークフローはチームに新たな不必要な認知的オーバーヘッドを課していないか
ul
Centralized Workflow
Centralized Workflow は、SVN から移行するチームにとって素晴らしい Git ワークフローです。 Subversionと同様に、集中型ワークフローでは、プロジェクトへのすべての変更のための単一のエントリーポイントとして、中央のリポジトリを使用します。 trunk
master
master
以外のブランチは必要ありません。
分散型バージョン管理システムへの移行は大変な作業のように思えるかもしれませんが、Git を活用するために既存のワークフローを変更する必要はありません。
しかし、開発ワークフローにGitを使うことは、SVNに比べていくつかの利点があります。 まず、すべての開発者にプロジェクト全体のローカルコピーを与えることができます。 この隔離された環境により、各開発者はプロジェクトに対する他のすべての変更から独立して作業することができます。ローカルリポジトリにコミットを追加し、都合がつくまで上流の開発を完全に忘れることができます。 SVNとは異なり、Gitのブランチは、コードを統合し、リポジトリ間で変更を共有するためのフェイルセーフなメカニズムとして設計されています。 一元化ワークフローは、開発者がプッシュやプルを行うリモートのサーバーサイドのリポジトリを利用するという点で、他のワークフローと似ています。 他のワークフローと比較して、集中管理型ワークフローでは、プルリクエストやフォークのパターンが定義されていません。
仕組み 集中型ワークフロー
開発者はまず、中央のリポジトリをクローンします。 プロジェクトのローカル コピーでは、SVN と同様にファイルを編集し、変更をコミットしますが、これらの新しいコミットはローカルに保存され、セントラル リポジトリからは完全に隔離されます。
変更を公式プロジェクトに公開するには、開発者は自分のローカル master
svn commit
master
ブランチにまだないすべてのローカル コミットを追加する点が異なります。 セントラル・ベア・リポジトリの初期化
まず、誰かがセントラル・リポジトリをサーバー上に作成する必要があります。 新しいプロジェクトであれば、空のリポジトリを初期化することができます。 それ以外の場合は、既存の Git または SVN リポジトリをインポートする必要があります。
セントラルリポジトリは常にベアリポジトリ(作業ディレクトリを持たない)であるべきで、以下のようにして作成します。
ssh user@host git init --bare /path/to/repo.git
user
には必ず有効なSSHユーザー名を使用してください。 host
には、サーバーのドメインまたはIPアドレス、/path/to/repo.git
には、レポを保存する場所を指定します。
ホストされたセントラル リポジトリ
セントラル リポジトリは、Bitbucket Cloud や Bitbucket Server のようなサードパーティの Git ホスティング サービスで作成されることがよくあります。 上述のベア・リポジトリを初期化するプロセスは、ホスティングサービスが代行してくれます。
セントラル リポジトリのクローン
次に、各開発者はプロジェクト全体のローカル コピーを作成します。
git clone
コマンドで行います。
git clone ssh://user@host/path/to/repo.git
リポジトリをクローンするとき、Git は自動的に origin
というショートカットを追加し、「親」のリポジトリを指すようにします。
変更とコミット
リポジトリがローカルにクローンされると、開発者は標準的な Git のコミット プロセス (編集、ステージ、コミット) を使用して変更を加えることができます。 ステージングエリアに慣れていない方のために説明しますと、ステージングエリアとは、作業ディレクトリ内のすべての変更を含めることなくコミットを準備する方法です。
git status # View the state of the repo git add # Stage a file git commit # Commit a file
これらのコマンドはローカル コミットを作成するため、John はセントラル リポジトリで何が起こっているかを気にすることなく、このプロセスを何度でも繰り返すことができることを覚えておいてください。
新しいコミットをセントラル リポジトリにプッシュする
ローカル リポジトリに新しい変更がコミットされたら、その変更をセントラル リポジトリにプッシュする必要があります。
git push origin master
このコマンドは、コミットされた新しい変更をセントラル リポジトリにプッシュします。 変更をセントラル・リポジトリにプッシュする際、他の開発者からの更新が以前にプッシュされていて、意図したプッシュ更新と競合するコードが含まれている可能性があります。 Git は、この衝突を示すメッセージを出力します。 このような場合は、まず git pull
を実行する必要があります。
コンフリクトの管理
セントラル リポジトリは公式なプロジェクトを代表するものであり、そのコミット履歴は神聖で不変なものとして扱われるべきです。
開発者が自分の機能を公開する前に、更新された中央のコミットを取得し、その上に自分の変更をリベースする必要があります。 これは、「他の人がすでに行ったことに自分の変更を加えたい」と言っているようなものです。
ローカルの変更が上流のコミットと直接衝突した場合、Git はリベース処理を一時停止して、その衝突を手動で解決する機会を与えます。 Gitの良いところは、コミットの生成とマージ・コンフリクトの解決の両方に、同じgit status
git add
コマンドを使うことです。 これにより、新しい開発者は自分のマージを簡単に管理することができます。
例
典型的な小さなチームがこのワークフローを使ってどのように共同作業を行うか、一般的な例を見てみましょう。
John works on his feature
ローカル リポジトリでは、John は標準的な Git のコミット プロセスである edit、stage、commit を使用して機能を開発できます。
これらのコマンドはローカル コミットを作成するので、John は中央リポジトリで何が起こっているかを気にすることなく、このプロセスを何度でも繰り返すことができます。 一方、メアリーは自分のローカル リポジトリで、同じ編集/ステージ/コミット プロセスを使用して、自分の機能に取り組んでいます。
John が機能を公開する
ジョンが機能を完成させたら、他のチームメンバーがアクセスできるように、彼のローカルコミットを中央リポジトリに公開する必要があります。
git push origin master
origin
は、ジョンが中央リポジトリをクローンしたときに Git が作成した中央リポジトリへのリモート接続であることを覚えておいてください。 master
origin
master
master
ブランチのようにしようとGitに指示します。
Mary tried to publish her feature
John が変更を中央リポジトリに正常に公開した後、Mary が機能をプッシュしようとするとどうなるか見てみましょう。 全く同じプッシュコマンドを使うことができます。
git push origin master
しかし、彼女のローカル履歴は中央リポジトリから離れているので、Git はかなり冗長なエラーメッセージを出してリクエストを拒否します。
Mary rebases on top of John’s commit(s)
メリーさんは、git pull
svn update
のようなもので、上流のコミット履歴全体をMaryさんのローカルリポジトリに引き込み、ローカルのコミットと統合しようとします。
git pull --rebase origin master
--rebase
master
ブランチの先端に移動するように Git に指示します。
このオプションを忘れていてもプルは動作しますが、誰かが中央リポジトリと同期する必要があるたびに、余計な「マージコミット」が発生してしまいます。
Mary resolves a merge conflict
ブランチに1つずつ転送することで機能します。 つまり、マージコンフリクトを1つの巨大なマージコミットで解決するのではなく、コミットごとに解決するということです。 これにより、コミットをできるだけ集中的に行い、プロジェクトの履歴をきれいに保つことができます。
Mary と John が無関係な機能に取り組んでいるのであれば、リベースの過程でコンフリクトが発生することはまずありません。
CONFLICT (content): Merge conflict in
Gitの素晴らしい点は、誰でも自分のマージコンフリクトを解決できることです。 今回の例では、Maryさんがgit status
を実行してどこに問題があるのかを確認するだけです。 コンフリクトしたファイルは [Unmerged paths (マージされていないパス)] セクションに表示されます:
# Unmerged paths: # (use "git reset HEAD ..." to unstage) # (use "git add/rm ..." as appropriate to mark resolution) # # both modified:
そして、ファイルを好きなように編集します。
git rebase
git add git rebase --continue
これで完了です。
もしここまで来て、何が起こっているのかわからなくなっても、慌てないでください。 次のコマンドを実行すれば、すぐに元の状態に戻ります。
git rebase --abort
Mary は機能の公開に成功しました
セントラル リポジトリとの同期が完了した後、Mary は変更を正常に公開することができます:
git push origin master
今後の課題
ご覧のように、わずかな Git コマンドを使用して、従来の Subversion 開発環境を再現することができます。
集中型ワークフローは小規模なチームに最適です。
集中型ワークフローは小規模なチームに向いていますが、チームの規模が大きくなると、上記のような対立解消プロセスがボトルネックになる可能性があります。 もしあなたのチームが集中型ワークフローに慣れていて、共同作業を効率化したいと考えているのであれば、フィーチャーブランチワークフローのメリットを検討する価値は十分にあります。 それぞれの機能に独立したブランチを割り当てることで、新しい追加機能を公式プロジェクトに統合する前に、綿密な議論を始めることができます。 ほとんどの一般的な Git ワークフローは、個々の開発者がプッシュしたりプルしたりするある種の集中型レポを持っています。 以下では、その他の一般的なGitワークフローについて簡単に説明します。 これらの拡張ワークフローは、機能開発、ホットフィックス、そして最終的なリリースのためのブランチ管理に関して、より専門的なパターンを提供します。
機能ブランチ
機能ブランチは、集中化ワークフローの論理的な拡張です。 フィーチャー ブランチ ワークフローの中核となる考え方は、すべての機能開発は master
master
ブランチには壊れたコードが決して含まれないことになり、継続的インテグレーション環境にとって大きな利点となります。
Gitflow Workflow
Gitflow Workflowは、2010年にnvieのVincent Driessen氏がブログで発表し、高い評価を受けました。 Gitflow Workflowは、プロジェクトのリリースを中心に設計された厳密なブランチモデルを定義しています。 このワークフローでは、Feature Branch ワークフローで必要とされる以上の新しい概念やコマンドは追加されません。 その代わり、異なるブランチに非常に具体的な役割を割り当て、それらがいつ、どのように相互作用するかを定義します。
Forking ワークフロー
Forking ワークフローは、このチュートリアルで説明した他のワークフローとは基本的に異なります。 コードベースの「中心」として機能する単一のサーバーサイド リポジトリを使用する代わりに、すべての開発者にサーバーサイド リポジトリを与えます。 つまり、各開発者は、プライベートなローカル リポジトリとパブリックなサーバー サイド リポジトリの 2 つの Git リポジトリを持つことになります。
ガイドライン
すべてのサイズのGitワークフローはありません。 前述のように、チームの生産性を高めるようなGitワークフローを開発することが重要です。 チーム文化に加えて、ワークフローはビジネス文化を補完するものでなければなりません。 ブランチやタグといった Git の機能は、あなたのビジネスのリリース・スケジュールを補完するものでなければなりません。 もしあなたのチームがタスク追跡型のプロジェクト管理ソフトウェアを使っているのであれば、進行中のタスクに対応するブランチを使いたいと思うかもしれません。
短命のブランチ
ブランチが本番ブランチから離れている期間が長ければ長いほど、マージの衝突やデプロイメントの課題のリスクが高くなります。
短命なブランチ
元に戻さなければならないマージを未然に防ぐためのワークフローを持つことは重要です。 ブランチをテストしてから master
ブランチにマージするというワークフローはその一例です。 しかし、事故は起こるものです。
リリーススケジュールに合わせる
ワークフローは、あなたのビジネスのソフトウェア開発のリリースサイクルを補完するものでなければなりません。 一日に何度もリリースする予定であれば、master
ブランチを安定させておきたいでしょう。
まとめ
このドキュメントでは、Git のワークフローについて説明しました。 Centralized Workflow」について、実践的な例を交えて詳しく見ていきました。 集中型ワークフローを発展させ、さらに特殊なワークフローについても説明しました。
- 万能な Git ワークフローはありません
- ワークフローはシンプルで、チームの生産性を向上させるものでなければなりません
- ビジネス要件が Git ワークフローを形成するのに役立つはずです
次の Git ワークフローについては、Feature Branch ワークフローの包括的な説明をご覧ください
。