GitLab入門:ブランチ作成ガイド – 並行開発と効率的なコード管理の基礎
はじめに
ソフトウェア開発の世界において、バージョン管理システムはもはや不可欠なツールです。中でもGitは分散型バージョン管理システムとして広く普及しており、そのGitをベースにしたWebサービスであるGitLabは、コード管理だけでなく、プロジェクト管理、CI/CD(継続的インテグレーション/継続的デリバリー)など、開発ライフサイクル全体をサポートする強力なプラットフォームとして多くの開発チームに利用されています。
GitやGitLabを使いこなす上で、最も基本的ながら非常に重要な概念の一つが「ブランチ(Branch)」です。ブランチを理解し、適切に活用することは、チームでの並行開発を円滑に進め、安全かつ効率的にコードを管理するために不可欠です。
しかし、GitやGitLabに初めて触れる方にとって、「ブランチとは何か?」「なぜ必要なのか?」「どうやって作成し、管理するのか?」といった疑問は少なくないでしょう。特に、チーム開発においては、自分一人で開発する場合とは異なるブランチの使い方やルールが存在します。
この記事では、GitおよびGitLabにおけるブランチの概念から、具体的な作成・操作方法、そしてチーム開発で役立つGitLabの機能(保護されたブランチ、マージリクエストなど)までを、初心者の方にも分かりやすく、かつ詳細に解説します。GitLabを使った開発を始めたばかりの方、ブランチの概念をしっかり理解したい方、チームでのブランチ運用に自信を持ちたい方にとって、この記事が確固たる基礎を築く一助となれば幸いです。
本記事は非常に長いですが、それぞれのセクションが独立している部分もあるため、必要に応じて特定の章だけを参考にすることも可能です。ただし、全体を通して読むことで、GitとGitLabにおけるブランチの利用に関する包括的な知識が得られるように構成されています。さあ、GitLabでのブランチ作成の旅に出かけましょう。
1. Gitの基本概念を知る
GitLabはGitの上に構築されたサービスであるため、まずGitそのものの基本的な概念を理解することが重要です。ここでは、ブランチを理解する上で最低限知っておきたいGitの用語を解説します。
-
リポジトリ (Repository):
リポジトリは、プロジェクトのファイルやディレクトリ、そしてそれらの変更履歴(コミット)を全てまとめて保存する場所です。例えるなら、プロジェクト専用のタイムカプセルや保管庫のようなものです。リポジトリには、ローカルコンピュータ上に存在する「ローカルリポジトリ」と、GitLabのようなリモートサービス上に存在する「リモートリポジトリ」があります。通常、開発者はローカルリポジトリで作業し、変更内容をリモートリポジトリと同期させます。ローカルリポジトリは、Gitコマンド(git cloneなど)によって作成または取得され、.gitという隠しディレクトリの中に履歴情報などが格納されます。リモートリポジトリは、GitLabのサーバー上に存在し、チームメンバー間でのコード共有や統合、バックアップの役割を果たします。 -
コミット (Commit):
コミットは、プロジェクトのファイルやディレクトリに対する一連の変更を「記録」する操作です。git addでステージングしたファイル群(スナップショット)に対して行われます。各コミットは、スナップショット自体の内容に加え、誰が(Author)、いつ(Date)、どのような変更を行ったか(Commit Message)という情報を持っています。また、各コミットは一つ前(またはマージコミットの場合は複数)のコミットへのポインタ(親コミット)を持っています。これにより、プロジェクトの履歴が時系列で追跡可能になります。コミットはGitの基本的な単位であり、全ての変更はコミットとして記録され、ブランチ上に連なります。コミットは、その内容と親コミットに基づいて計算されるユニークなハッシュ値(SHA-1ハッシュ、通常40桁の16進数)によって識別されます。例えば、a1b2c3d4e5f6...のような文字列です。このハッシュ値によって、特定の時点でのプロジェクトの状態を正確に参照できます。 -
ブランチ (Branch):
ブランチは、開発の作業を分岐させるための仕組みです。例えるなら、メインとなる一本のタイムライン(コミットの連なり)から、一時的に脇道を作り、そこで独立した作業を行い、作業が完了したら再びメインのタイムラインに合流させるようなものです。Gitにおいて、ブランチは単なる履歴のコピーではなく、特定のコミットを指し示す非常に軽量な「ポインタ」です。例えば、mainブランチが最新のコミットXを指している状態で新しいコミットYを作成すると、mainブランチのポインタは自動的にYを指すように移動します。新しいブランチを作成するという操作は、単に現在のコミットを指す新しいポインタ(ブランチ名)を作るだけです。これにより、複数の開発者が同じプロジェクト内で並行して異なる機能開発やバグ修正を行うことが可能になります。通常、新しい機能開発やバグ修正を行う際には、メインのブランチ(慣習的にmasterやmainと呼ばれることが多い)から新しいブランチを作成し、そのブランチ上で作業を進めます。ブランチは、プロジェクトの多様な作業ストリームを管理するための基本的なツールです。 -
マージ (Merge):
マージは、分岐したブランチの変更内容を、別のブランチ(通常は元のブランチやメインのブランチ)に取り込む操作です。脇道での作業(あるブランチでの開発)が完了したら、その変更内容をメインの道路(別のブランチ)に合流させるイメージです。git merge <マージしたいブランチ名>コマンドを実行することで行われます。Gitはマージを実行する際に、マージ元とマージ先のブランチの共通の祖先コミットからの変更を比較し、それらを統合しようとします。多くの場合、新しい「マージコミット」が作成され、このコミットがマージ元とマージ先の両方のブランチの先端を親として指すことになります。これにより、マージの履歴が明確に残ります。ただし、マージ元ブランチがマージ先ブランチから分岐後に一切新しいコミットが追加されていない場合など、直線的に統合できる場合は「Fast-forwardマージ」が行われ、マージコミットは作成されずにマージ先のブランチポインタが単に移動することもあります。異なるブランチで同じファイルの同じ箇所を変更していた場合などには、「マージ競合(Merge Conflict)」が発生することがあります。 -
フェッチ (Fetch) / プル (Pull) / プッシュ (Push):
これらはローカルリポジトリとリモートリポジトリの間で変更内容を同期するための操作です。リモートリポジトリは、チームメンバー間でコードを共有したり、バックアップとして利用したりするために用いられます。通常、ローカルリポジトリは一つまたは複数のリモートリポジトリと関連付けられます。慣習的に、メインのリモートリポジトリはoriginという名前で参照されます。- フェッチ (
git fetch): リモートリポジトリの最新の状態(コミット、ブランチ情報など)を取得し、ローカルリポジトリ内のリモートトラッキングブランチ(例:origin/main,origin/feature/xxx)を更新します。しかし、ローカルの作業ブランチ(例:main,feature/xxx)にはこれらの変更をすぐに反映させません。リモートにどのような変更があるかを確認したい場合に利用します。これにより、自分の作業を中断せずにリモートの状況を把握できます。 - プル (
git pull): リモートリポジトリの最新の状態を取得し(git fetch)、その変更内容をローカルの現在のブランチに自動的にマージまたはリベースして統合します。git fetchとそれに続くgit mergeまたはgit rebaseを組み合わせた操作と考えることができます。他の開発者がリモートにプッシュした変更を自分のローカルに取り込みたい場合に利用します。デフォルトではマージが実行されますが、設定によってリベースに変更することも可能です。git pull origin mainのように、どのリモートのどのブランチからプルするかを指定するのが一般的です。 - プッシュ (
git push): ローカルリポジトリでの変更内容(コミット)をリモートリポジトリにアップロードします。自分のローカルでの作業結果を他の開発者と共有したい場合に利用します。git push origin <ローカルブランチ名>:<リモートブランチ名>の形式で、特定のローカルブランチを特定のリモートブランチにプッシュします。通常はgit push origin <ブランチ名>のように、ローカルとリモートで同じブランチ名を使用します。リモートにプッシュされていないローカルコミットをリモートブランチの先端に追加する操作です。
- フェッチ (
-
リモートリポジトリ (Remote Repository):
ネットワーク経由でアクセスできるGitリポジトリです。GitLab上に作成されるリポジトリがこれにあたります。ローカルリポジトリは、通常一つ以上のリモートリポジトリと関連付けられます。リモートリポジトリは、チームメンバー間でコードを共有したり、バックアップとして利用したりするために用いられます。git remoteコマンドで関連付けられているリモートリポジトリの一覧を確認できます。git remote add origin <リモートリポジトリのURL>のようにして、ローカルリポジトリにリモートリポジトリを追加・関連付けることができます。 -
HEAD:
現在作業しているブランチの先端(最新コミット)を指し示す特別なポインタです。より正確には、現在チェックアウトしているコミットまたはブランチを指します。通常、HEADは特定のブランチ(例:refs/heads/main)を指しており、ブランチを切り替えるとHEADもそのブランチの先端を指すように移動します。コミットを作成する際、GitはHEADが指しているコミットを新しいコミットの親とします。また、特定のコミットハッシュを直接チェックアウトした場合など、HEADがどのブランチも指さずに特定のコミットを直接指す状態を「detached HEAD(分離されたHEAD)」と呼びます。
これらの概念を理解することが、GitLabにおけるブランチ操作をスムーズに行うための第一歩となります。
2. GitLabとは何か、なぜ使うのか
GitLabは、Gitを中核としたWebベースのDevOpsプラットフォームです。単なるGitリポジトリのホスティングサービスに留まらず、開発プロセス全体をサポートする多機能を提供します。
- Gitリポジトリ管理: プロジェクトのコードをGitリポジトリとしてホストします。これ自体がGitLabの最も基本的な機能です。GitリポジトリをGitLab上で管理することで、コードの共有、変更履歴の追跡、複数ユーザーでの共同作業が容易になります。Web UIを通じてリポジトリ内のファイルを参照したり、過去のコミット履歴を視覚的に確認したりすることも可能です。
- イシュー・トラッカー (Issue Tracker): タスク、バグ、機能要望などを管理するための機能です。イシューには担当者の割り当て、ラベル付け、期日設定、コメントでの議論などができ、開発の進捗管理や課題管理に役立ちます。マージリクエストと関連付けることで、「この変更でどのイシューを解決したか」を明確にできます。
- マージリクエスト (Merge Request): ブランチ間の変更を統合する提案を行うための仕組みです。これはGitLabにおけるチーム開発の中核機能と言えます。これにはコードレビュー、CI/CDパイプラインの結果表示、議論、承認などの機能が集約されており、チーム開発における品質向上とコミュニケーションの中心となります。(これはGitLabではマージリクエストと呼ばれますが、GitHubなどではプルリクエスト(Pull Request)と呼ばれます。機能としては非常に似ています。)フィーチャーブランチで開発した内容をメインブランチに取り込む際に、必ずマージリクエストを作成し、チームメンバーのレビューを経てからマージするというワークフローが一般的です。
- CI/CD (継続的インテグレーション/継続的デリバリー): コードのテスト、ビルド、デプロイメントなどを自動化する機能です。GitLab CI/CDはリポジトリ内に配置する
.gitlab-ci.ymlというファイルでパイプライン(自動化ワークフロー)を定義します。コミットやマージリクエストの変更を検知して自動的にパイプラインを実行できるため、コードが変更されるたびに自動的にテストを実行し、問題がないことを確認したり、ステージング環境や本番環境に自動的にデプロイしたりすることが可能です。これにより、高品質なソフトウェアを迅速かつ頻繁にリリースできるようになります。 - コンテナレジストリ: Dockerイメージなどのコンテナイメージを保存・管理できます。CI/CDパイプラインでビルドしたイメージをここに保存し、Kubernetesなどのコンテナオーケストレーションプラットフォームから利用する、といった連携が可能です。
- パッケージレジストリ: 各種プログラミング言語のパッケージ(npm, Maven, PyPI, NuGet, RubyGemsなど)をホストできます。プロジェクト内で利用するライブラリやモジュールを内部で管理したい場合に便利です。
- Wiki: プロジェクトに関するドキュメントを管理できます。プロジェクトの概要、設計情報、開発ルールなどをチーム内で共有するのに役立ちます。Gitリポジトリとして管理されるため、変更履歴の追跡やバージョン管理が可能です。
なぜGitLabを使うのか?主な理由は以下の通りです。
- チーム開発の効率化: 複数の開発者が並行して作業し、コードレビューを通じて品質を向上させ、変更履歴を共有・管理できます。マージリクエストを中心としたワークフローは、チーム間の連携を強化し、開発プロセスを透明化します。
- 開発プロセスの統合: リポジトリ管理からイシュー管理、コードレビュー、CI/CD、デプロイまで、開発の多くの側面を一つのプラットフォーム上で管理できます。これにより、ツール間の連携設定の手間が省け、ワークフローがスムーズになり、ツールの切り替えによるコンテキストスイッチのコストを削減できます。
- コードの安全性と信頼性: リモートリポジトリにコードを保存することで、ローカルの障害からコードを保護できます。また、保護されたブランチなどの機能により、重要なコードラインへの不用意な変更を防ぎ、コードの整合性を保つことができます。アクセス権限設定も柔軟に行えます。
- 自動化: CI/CD機能により、テスト、ビルド、デプロイといった反復的な作業を自動化し、開発者の負担を減らし、ヒューマンエラーを防止できます。これにより、開発者はより創造的な作業に集中できます。
- DevOpsプラットフォーム: コードのビルドからテスト、デプロイ、監視まで、DevOpsツールチェーンに必要な機能が統合されています。これにより、開発チームと運用チームの連携を促進し、開発サイクルの高速化と安定化を実現できます。
GitLabは無料プラン(Free Tier)でも基本的なGitリポジトリ機能やCI/CDの一部を利用できますが、チーム開発向けの高度な機能(例:承認ルール設定、セキュリティスキャン、より詳細なCI/CD設定、エピックやポートフォリオ管理など)は有料プラン(Premium, Ultimate)で提供されます。入門レベルでは無料プランで十分な機能を利用できます。
3. GitLabプロジェクトの作成と基本的な操作
GitLabでブランチを使い始める前に、まずはGitLabプロジェクトを作成し、ローカル環境との連携を設定しましょう。
3.1 GitLabアカウントの作成
まだGitLabアカウントをお持ちでない場合は、GitLabのウェブサイト (gitlab.com) にアクセスし、アカウントを作成してください。通常、メールアドレスやGitHub/Googleアカウントなどを使って登録できます。
3.2 新規プロジェクトの作成
GitLabアカウントにログインしたら、新しいプロジェクトを作成します。このプロジェクトがあなたのGitリポジトリ(リモート)となります。
- GitLabのトップページまたは左サイドバーの「Menu」>「Projects」>「Your projects」から、「New project」ボタンをクリックします。
- プロジェクト作成のオプションが表示されます。「Create blank project」を選択します。これは、まっさらな新しいGitリポジトリを作成する場合に選びます。
- プロジェクトの情報を入力します。
- Project name: プロジェクトの名前をつけます。これはGitLab上での表示名になります(例:
My Web Application)。 - Project slug: プロジェクトのスラッグ(識別子)です。URLやローカルクローン時のディレクトリ名として使用されます。通常はプロジェクト名から自動生成されますが、編集も可能です。英数字、ハイフン、アンダースコアが使用できます(例:
my-web-application)。 - Group or user: プロジェクトを個人のネームスペース下(例: 自分のユーザー名)に作成するか、所属するグループ下(例: チーム名)に作成するかを選択します。個人で学習目的で使う場合は自分のユーザー名を選びます。チーム開発の場合は、通常、チームや会社のグループ内に作成します。
- Visibility Level: プロジェクトの公開範囲を設定します。
Private: プロジェクトを作成したユーザー、または明示的にメンバーとして追加され、アクセス権限を与えられたユーザーのみがアクセスできます。チーム開発で最も一般的な設定です。Internal: GitLabにログインしているユーザーであれば誰でもアクセスできます。企業の内部ネットワークなどで利用する場合があります。Public: インターネット上の誰でもアクセスできます。ログインしていないユーザーも含め、誰でもプロジェクトの内容(コード、イシューなど)を閲覧できます。オープンソースプロジェクトなどで利用します。
- Initialize repository with a README: リポジトリ作成時にREADMEファイルを追加するかどうかです。チェックを入れておくと、初期コミットが作成され、クローンがすぐにできる状態になるため、入門としては、チェックを入れておくことをお勧めします。プロジェクトの概要などを記述するファイルです。
- Project name: プロジェクトの名前をつけます。これはGitLab上での表示名になります(例:
- 必要に応じて、
.gitignoreファイルやライセンスファイルを追加するオプションもありますが、最初はREADMEだけでも構いません。 - 「Create project」ボタンをクリックします。
これでGitLab上に新しいプロジェクト(リモートリポジトリ)が作成されました。プロジェクトページが表示され、READMEファイルが含まれた最初のコミット(イニシャルコミット)が作成されていることが確認できます。このページには、後でローカルからこのリポジトリにアクセスするために必要なクローンするためのURL(HTTPSまたはSSH)が表示されます。
3.3 ローカル開発環境の準備
Gitを使った開発を行うには、ローカルコンピュータにGitをインストールする必要があります。また、コードを編集するためのテキストエディタやIDE(統合開発環境)も必要です。
- Gitのインストール: Gitの公式サイト (git-scm.com) から、お使いのOS(Windows, macOS, Linux)に合わせたインストーラーをダウンロードしてインストールしてください。各OSごとの詳しい手順は公式サイトに記載されています。インストール後、ターミナル(コマンドプロンプトやGit Bashなど)で
git --versionと入力してGitのバージョンが表示されれば成功です。 -
ユーザー名とメールアドレスの設定: Gitでコミットを行う際に、誰がコミットしたかを識別するためにユーザー名とメールアドレスを設定します。これはGitの初期設定として一度だけ行っておけば、そのコンピュータ上の全てのGitリポジトリに適用されます。
bash
git config --global user.name "Your Name"
git config --global user.email "[email protected]"--globalオプションを外せば、特定のリポジトリに対して個別の設定を行うことも可能です(プロジェクトディレクトリ内で実行)。 -
SSHキーの設定 (推奨): リモートリポジトリとの通信方法としてHTTPSとSSHがあります。HTTPSはユーザー名とパスワード(またはパーソナルアクセストークン)での認証が必要ですが、SSHは公開鍵認証を使用するため、一度設定すればパスワード入力を省略でき、より便利で安全です。
SSHキーペア(公開鍵と秘密鍵)を生成し、生成された公開鍵をGitLabのユーザー設定に登録することでSSH接続が可能になります。SSHキーの設定方法は、GitLabのドキュメント(”Add an SSH key to your GitLab account”などで検索)を参照してください。SSHを使う場合は、GitLabプロジェクトページのクローンURLとしてSSHのURL(例:[email protected]:your-username/your-project.git)を使用します。 -
エディタ/IDE: VS Code, Sublime Text, Atom, JetBrains IDEs(IntelliJ IDEA, PyCharm, WebStormなど)など、お好みのものを用意してください。多くのモダンなエディタやIDEには、Git連携機能が組み込まれています。
3.4 プロジェクトのクローン (git clone)
GitLab上のリモートリポジトリを、ローカルコンピュータに複製します。この操作を「クローン」と言います。これにより、ローカルにリモートリポジトリの内容が全く同じ状態でコピーされ、ローカルリポジトリとして作業できるようになります。
- GitLabのプロジェクトページにアクセスします。プロジェクトのトップページにクローンするためのURLが表示されています。通常、「Clone」ボタンをクリックすると、HTTPSとSSHのURLを選択してコピーできます。お好みの方法(HTTPSまたはSSH)でURLをコピーします。
- ローカルコンピュータで、プロジェクトを配置したい任意のディレクトリ(フォルダ)に移動します。ターミナル(コマンドプロンプトなど)を使用します。例えば、
Documentsフォルダに移動したい場合はcd Documentsと入力します。 -
以下のコマンドを実行します。コピーしたGitLabのクローンURLを
<your_project_url>の部分に置き換えてください。bash
git clone <your_project_url>例: HTTPSの場合
bash
git clone https://gitlab.com/your-username/my-web-application.gitSSHの場合
bash
git clone [email protected]:your-username/my-web-application.gitコマンドを実行すると、指定したディレクトリ内にプロジェクト名のディレクトリ(例:
my-web-application)が作成され、リモートリポジトリの全てのファイルと履歴がダウンロードされます。ダウンロードされたディレクトリが、あなたのローカルリポジトリになります。 -
クローンしたプロジェクトディレクトリに移動します。
bash
cd my-web-applicationこれで、GitLab上のプロジェクトをローカルで作業できる状態になりました。クローン直後、ローカルリポジトリはリモートリポジトリのデフォルトブランチ(通常
mainまたはmaster)に対応するローカルブランチに自動的にチェックアウトされています。
3.5 簡単な変更、コミット、プッシュ
ローカルリポジトリでファイルに変更を加え、その変更をコミットし、GitLab(リモートリポジトリ)にプッシュする基本的な流れを体験してみましょう。これは、後述するブランチを使った開発の基礎となる操作です。
- ファイルの変更: クローンしたプロジェクトディレクトリにあるREADME.mdファイルなどをエディタで開き、適当な内容を追加または変更します。例えば、「Hello, GitLab!」といった一行を追加します。
-
現在の状態を確認:
git statusコマンドを使うと、現在のリポジトリの状態を確認できます。どのファイルが変更されたか、どのファイルがステージングされているか、どのブランチにいるかなどが表示されます。bash
git status変更を加えた直後は、README.mdが「Changes not staged for commit」(ステージングされていない変更)として表示されるはずです。
-
変更のステージング: Gitに「この変更を次のコミットに含めますよ」と伝える操作を「ステージング」または「インデックスに追加」と言います。
git addコマンドを使います。ステージングされた変更は、Gitのインデックスという領域に一時的に保持されます。“`bash
README.md ファイルの変更をステージングする場合
git add README.md
または、現在のディレクトリ以下の全ての変更(新規ファイル、変更、削除)をステージングする場合
git add .
“`再度
git statusを実行すると、README.mdが「Changes to be committed」(コミットされる変更)として表示されるはずです。 -
変更のコミット: ステージングした変更内容をローカルリポジトリに記録します。
git commitコマンドを使います。コミットには必ず「コミットメッセージ」をつけます。これは、そのコミットでどのような変更を行ったのかを簡潔に説明するもので、プロジェクトの履歴を理解するために非常に重要です。bash
git commit -m "Add a greeting message to README"-mオプションを使うと、コマンドラインで直接メッセージを指定できます。-mをつけずにgit commitだけを実行すると、設定されているテキストエディタ(デフォルトではVimなど)が開き、そこでより詳細なメッセージを入力・保存することになります。良いコミットメッセージを書く習慣をつけましょう。一般的に、一行目は変更の要約(50文字以内目安)、二行目は空行、三行目以降に詳細を記述します。コミットが成功すると、コミットハッシュ(短い識別子)とコミットメッセージが表示されます。これで、あなたのローカルリポジトリに変更履歴が一つ追加されました。このコミットは、現在チェックアウトしているブランチ(クローン直後なら通常
mainまたはmaster)の先端に追加され、そのブランチのポインタが新しいコミットを指すように移動します。 -
リモートへのプッシュ: ローカルで作成したコミットをGitLab上のリモートリポジトリにアップロードします。
git pushコマンドを使います。“`bash
現在のブランチをリモートの対応するブランチにプッシュする場合
git push origin main
または git push origin master (プロジェクトの設定による)
“`
originはローカルリポジトリが関連付けられているリモートリポジトリのデフォルト名、main(またはmaster)はプッシュしたいローカルブランチの名前です。このコマンドは、「ローカルのmainブランチの先端にあるコミットと、それに繋がるまだリモートにない親コミットを、リモートのoriginにあるmainブランチに送る」という意味になります。通常、初めて特定のローカルブランチをリモートにプッシュする際は、ローカルブランチとリモートブランチを関連付け(トラッキング設定)を行うと便利です。
bash
git push -u origin main-uオプション(または--set-upstream)を使うと、ローカルのmainブランチがリモートのorigin/mainブランチをトラッキングするよう設定されます。一度設定を行えば、次回以降はこのブランチにいる状態で単にgit pushと実行するだけで、関連付けられたリモートブランチ(この例ではorigin/main)にプッシュされるようになります。同様に、単にgit pullと実行するだけで、関連付けられたリモートブランチからプルするようになります。プッシュが成功すると、リモートリポジトリ(GitLab)に変更内容が反映されます。GitLabのプロジェクトページをブラウザで確認すると、README.mdが更新されていること、そして新しいコミットが履歴に追加されていることが確認できるでしょう。
4. ブランチの重要性
セクション1でGitのブランチ概念を説明しましたが、ここではなぜブランチがソフトウェア開発においてそれほど重要なのか、より掘り下げて説明します。
ブランチを使うことの主なメリットは以下の通りです。
- 並行開発: 複数の開発者が同時に異なる機能の開発やバグ修正に取り組むことができます。各開発者は自分のブランチ(例:
feature/add-user-profile,feature/implement-payment-gateway)で作業するため、他の開発者の作業と完全に分離された状態で開発を進められます。これにより、互いの変更が混ざり合うことによる混乱を防ぎ、並行して効率的に開発を進めることが可能になります。 - 機能の分離: 新しい機能や実験的な変更を、安定しているメインのコードライン(例:
mainやmasterブランチ)から分離して開発できます。開発途中のコードは未完成であったり、バグを含んでいたりする可能性がありますが、これがメインブランチに直接影響を与えないため、メインブランチは常に比較的安定した状態を保つことができます。これにより、いつでも安定版のコードベースからリリースやデプロイを行うことが可能になります。 - 実験と破棄: 新しい技術やアプローチを試したい場合に、気軽にブランチを作成してその上で自由に実験できます。例えば、「このライブラリを使ってみたらどうなるだろう?」といった試みや、大規模なリファクタリングの検討など、成功するかどうかわからない作業を安全に行えます。もしその試みがうまくいかなくても、そのブランチを削除するだけでよく、メインのコードラインには一切影響しません。実験の結果が良好であれば、そのブランチをメインブランチにマージすることで変更を取り込むことができます。
- 安定版の保護:
mainやmasterのような主要なブランチは、通常、本番環境にデプロイされるコードや、プロジェクトの安定版を代表するものです。これらのブランチを保護することで、権限のないユーザーによる変更や、レビューを受けていない変更が直接プッシュされるのを防ぎます。これにより、安定版のコードが不用意な変更や未承認の変更によって壊されるリスクを最小限に抑えることができます。GitLabの保護されたブランチ機能は、この目的のために設計されています。 - コードレビューの促進: マージリクエスト(プルリクエスト)は、ブランチを使って開発された変更内容をメインのブランチに統合する前に、チームメンバーがコードをレビューするための仕組みです。特定のフィーチャーブランチに全ての変更を集約し、そのブランチとターゲットブランチ(例:
main)の差分をレビューしてもらうというプロセスは、ブランチがあるからこそ成り立ちます。コードレビューは、バグの早期発見、コード品質の向上、知識の共有、チーム内での共通理解の促進に不可欠です。
もしブランチを使わずに開発するとどうなるでしょうか?全員が同じ一つのブランチ(例えばmain)で直接作業することになります。
- 誰か一人が大きな機能開発でコードを大きく変更している最中に、別の誰かが緊急のバグ修正を行いたい場合、互いの作業が同じコードベース上で同時進行するため、変更が混ざり合ってしまい、非常に混乱しやすくなります。お互いの変更が衝突しやすくなり、手動での調整に多大な時間と労力がかかります。
- 開発途中の不安定なコードが常にメインブランチに存在することになり、メインブランチが不安定で、そこから安定したリリース版をいつでも作成することが困難になります。
- 新しい実験的な機能を試す際にも、メインブランチ以外に作業場所がないため、試みが失敗した場合に元に戻すのが難しくなります。試行錯誤がしづらくなります。
- コードレビューを効率的に行う仕組みがありません。誰かの変更をレビューするには、その変更がプッシュされた後にコード全体を見たり、手動で差分を確認したりする必要があり、非常に手間がかかります。
このように、ブランチは現代のチーム開発において、安全かつ効率的に並行開発を進めるための基盤となる仕組みなのです。多くの開発チームは、フィーチャーブランチワークフローと呼ばれるスタイルを採用しています。これは、新しい機能開発やバグ修正ごとに専用のブランチを作成し、そのブランチで作業を進め、完了したらメインブランチにマージするという方法です。このワークフローはシンプルで強力であり、GitLabの機能(マージリクエスト、保護ブランチなど)と非常に相性が良いです。
マージ競合: ブランチを使った並行開発で避けられないのが「マージ競合」です。これは、二つ以上のブランチで同じファイルの同じ箇所が異なる内容に変更されており、Gitがどちらの変更を採用すればいいのか自動的に判断できない場合に発生します。例えば、開発者AがファイルXの行10を「Aの変更」に修正し、同時に開発者BがファイルXの同じ行10を「Bの変更」に修正し、それぞれのブランチでコミットしてマージしようとした場合に競合が発生します。マージ競合が発生した場合、Gitはマージ処理を中断し、競合が発生したファイルを特別な形式(<<<<<<<, =======, >>>>>>>といったマーカー付き)で表示してくれます。開発者は、手動で競合している箇所を編集し、AとBの変更をどのように組み合わせるか、あるいはどちらか一方の変更を採用するかなどを決定し、最終的にどの内容にするかを決定してコミット(マージ競合の解決コミット)する必要があります。マージ競合の解決は、ブランチを使った開発における重要なスキルの一つです。幸い、GitLabのWeb UIや多くのエディタ/IDEは、マージ競合の解決を支援する機能を提供しています。
5. Gitにおけるブランチ作成の基本コマンド
ここでは、ローカルGitリポジトリでのブランチ作成、切り替え、一覧表示、削除といった基本的なコマンド操作を解説します。GitLabと連携させる前段階として重要です。これらの操作は全てローカルリポジトリに対して行われます。
これらのコマンドは、ローカルリポジトリのディレクトリ内でターミナルを開いて実行します。クローンしたプロジェクトのディレクトリにcdコマンドで移動してから実行してください。
-
現在のブランチを確認する:
bash
git branch実行すると、あなたのローカルリポジトリにあるブランチの一覧がリスト表示されます。現在作業しているブランチ(つまり、
HEADが指しているブランチ)にはアスタリスク(*)がつきます。また、ブランチ名の色が変わっていることもあります(ターミナルの設定による)。クローン直後は通常、リモートのデフォルトブランチ(mainまたはmaster)に対応するローカルブランチ(例:main)にいるはずです。-aオプションをつけると、ローカルブランチだけでなくリモートトラッキングブランチ(リモートリポジトリのブランチの状態をローカルにキャッシュしたもの)も一覧表示されます。bash
git branch -a出力例:
* main
feature/my-new-feature
remotes/origin/main
remotes/origin/feature/add-contact-form
この例では、ローカルにはmainとfeature/my-new-featureブランチがあり、現在mainブランチにいます。リモートのoriginにはmainとfeature/add-contact-formブランチが存在し、それに対応するリモートトラッキングブランチがローカルにあります。 -
新しいブランチを作成する:
現在のブランチ(例えば
main)の先端コミットから分岐して、新しいブランチを作成します。この操作は、単に新しいブランチ名と、それが指し示すコミット(デフォルトでは現在のHEADが指すコミット)を記録するだけです。作成するだけでは、まだ作業対象のブランチは切り替わりません。bash
git branch <新しいブランチ名>例:
feature/my-new-featureという名前のブランチを作成する(現在のブランチから分岐)bash
git branch feature/my-new-featureブランチ名には、アルファベット、数字、ハイフン(
-)、アンダースコア(_)、スラッシュ(/)などが使用できます。スラッシュ (/) を使ってfeature/,bugfix/,release/のように階層構造を持たせることがよくあります。これは単なる命名規則ですが、GitLabのWeb UIなどでブランチがグループ化されて視覚的に整理される場合があります。どのようなブランチ名を使うかは、チーム内でルールを決めておくと良いでしょう。特定の過去のコミットからブランチを作成したい場合は、コマンドの最後にコミットハッシュを指定します。
bash
git branch <新しいブランチ名> <コミットハッシュ> -
ブランチを切り替える:
作業対象を別のブランチに切り替えます。これを「チェックアウト」とも言います。ブランチを切り替えると、Gitはワーキングツリー(ローカルのファイル群)の内容を、切り替え先のブランチの先端コミットが指す状態に更新します。これにより、そのブランチで作業していた時のファイルの状態で開発を続けられます。
Gitの新しいバージョン(2.23以降)では、作業ブランチの切り替えには
git switchコマンドが推奨されています。これは、ファイルの復元などに使われるgit checkoutコマンドと役割を分離したためです。bash
git switch <切り替えたいブランチ名>例:
feature/my-new-featureブランチに切り替えるbash
git switch feature/my-new-feature成功すると、「Switched to branch ‘feature/my-new-feature’」のようなメッセージが表示されます。
古いバージョンや互換性のために
git checkoutコマンドを使うことも可能です。bash
git checkout <切り替えたいブランチ名>例:
feature/my-new-featureブランチに切り替える(checkout使用)bash
git checkout feature/my-new-featureブランチを切り替える前に、現在のブランチでの変更内容をコミットまたはスタッシュ(後述)しておくのが安全です。未コミットの変更がある状態でブランチを切り替えようとすると、Gitから警告が出たり、切り替えが拒否されたり、あるいは変更が切り替え先のブランチに持ち越されてしまったりすることがあります。特に、現在のブランチと切り替え先のブランチで同じファイルの同じ箇所が変更されている場合は、競合が発生する可能性があり、Gitは切り替えを拒否します。
-
新しいブランチを作成し、すぐに切り替える:
ブランチを作成してからすぐにそのブランチに切り替える、という二つのステップを一つのコマンドで行うことができます。これは新しい機能開発などを始める際に、メインブランチから分岐して作業を開始する際に非常に便利な操作です。
git switchコマンドの場合:bash
git switch -c <新しいブランチ名>例:
feature/another-featureブランチを作成し、そこに切り替えるbash
git switch -c feature/another-feature-cオプションは、「指定したブランチ名が存在しない場合は作成してから切り替える」という意味になります。もしブランチが既に存在する場合は、単にそのブランチに切り替えます。git checkoutコマンドの場合:bash
git checkout -b <新しいブランチ名>例:
feature/another-featureブランチを作成し、そこに切り替える(checkout使用)bash
git checkout -b feature/another-feature-bオプション(小文字)は、「指定したブランチ名が存在しない場合は作成してから切り替える」という意味になります。git checkoutの-bオプションは、git branch <新しいブランチ名>とgit checkout <新しいブランチ名>を連続で実行するのと同じです。 -
ブランチを削除する:
役目を終えたブランチは、ローカルリポジトリやリモートリポジトリから削除して整理するのが一般的です。これにより、ブランチ一覧がすっきりし、不要なブランチによる混乱を防げます。ブランチを削除しても、そのブランチが指していたコミットや、そのコミットに繋がる履歴がすぐに失われるわけではありません(他のブランチから到達可能な限り、Gitの内部ではオブジェクトとして保持されています)。
ローカルブランチを削除する場合:
マージ済みのブランチを削除する場合(安全な削除):
bash
git branch -d <削除したいローカルブランチ名>例:
feature/my-new-featureブランチを削除するbash
git branch -d feature/my-new-feature-dオプションは、削除しようとしているブランチの先端コミットが、現在いるブランチ(通常はマージ先ブランチ)から到達可能であること、すなわちそのブランチの変更が他のブランチに「マージ済みである」ことを確認してから削除します。マージされていない変更が含まれている場合は、エラーとなって削除できません。これにより、誤って未完了の作業を含むブランチを消してしまうことを防ぎます。マージされていないブランチを強制的に削除する場合:
bash
git branch -D <削除したいローカルブランチ名>例:
feature/experimental-featureブランチを強制的に削除するbash
git branch -D feature/experimental-feature-Dオプション(大文字)は、マージされているかどうかにかかわらず強制的にブランチを削除します。マージされていない変更は、もし他のブランチから参照されていない場合は失われる可能性があります。使用には十分な注意が必要です。一時的な実験ブランチなど、本当に不要になったブランチを確実に削除したい場合に利用します。リモートブランチを削除する場合:
GitLab上のリモートブランチを削除するには、
git pushコマンドを使用します。bash
git push origin --delete <削除したいリモートブランチ名>例:リモート(origin)上の
feature/old-featureブランチを削除するbash
git push origin --delete feature/old-featureまたは、より短い記法として、プッシュ元を空にする方法もあります。
bash
git push origin :<削除したいリモートブランチ名>例:リモート(origin)上の
feature/old-featureブランチを削除する(短縮記法)bash
git push origin :feature/old-featureマージリクエストをマージする際に「Delete source branch when merge request is accepted」オプションにチェックを入れておけば、GitLabが自動的にリモートブランチを削除してくれます。
-
リモートトラッキングブランチ:
git branch -aコマンドで確認できるremotes/origin/<ブランチ名>のようなブランチは「リモートトラッキングブランチ」と呼ばれます。これらはローカルリポジトリ内に存在しますが、直接チェックアウトして作業するためのブランチではありません。git fetchやgit pullを実行することで、GitLabなどのリモートリポジトリにあるブランチの最新状態を表すように更新されます。リモートブランチがどのような状態にあるかを示す「参照」として機能します。ローカルブランチは、通常、対応するリモートトラッキングブランチを「トラッキング」するように設定されます(git push -uなどで設定)。これにより、git pullや引数なしのgit pushがどのリモートのどのブランチを対象とするかをGitが判断できるようになります。
これらのコマンドを組み合わせることで、ローカルでのブランチを使った基本的な開発ワークフロー(ブランチ作成 -> 切り替え -> 変更 -> コミット -> 元のブランチに戻る -> マージ)を実行できます。GitLabとの連携は、これらのローカルでの作業をリモートリポジトリと同期させることで実現します。
6. GitLabと連携したブランチ操作
ローカルで作成したブランチやコミットは、GitLab(リモートリポジトリ)にプッシュすることで他の開発者と共有できます。また、GitLabのWeb UIから直接ブランチを作成したり管理したりすることも可能です。GitLabの機能を活用することで、チームでのブランチ運用がより効率的かつ安全になります。
6.1 ローカルブランチのリモートへのプッシュ
ローカルで新しいブランチを作成し、そのブランチ上でコミットした変更をGitLabにアップロードするには、git pushコマンドを使います。これにより、あなたのローカルでの作業結果をチームメンバーが確認できるようになります。
-
ローカルで新しいブランチを作成し、そのブランチに切り替えます。現在のブランチが
mainであると仮定します。
“`bash
# main ブランチが最新であることを確認
git switch main
git pull origin main新しいフィーチャーブランチを作成し、切り替える
git switch -c feature/add-contact-form
2. この新しいブランチ(`feature/add-contact-form`)上でファイルの変更、ステージング、コミットといった一連の作業を行います。bash例えば、contact.html ファイルを作成し、コードを記述・保存…
git add contact.html
git commit -m “Implement basic contact form structure and page”
``feature/add-contact-form`)をリモート(GitLab)にプッシュします。
3. このローカルブランチ(bash
git push origin feature/add-contact-formこのコマンドを実行すると、ローカルの
feature/add-contact-formブランチの最新コミットと、それに繋がる親コミットの中でまだリモートのoriginに存在しないものがアップロードされます。リモートに同名のブランチが存在しない場合、GitLab上にfeature/add-contact-formという名前の新しいブランチが作成されます。通常、初めて特定のローカルブランチをリモートにプッシュする際は、ローカルブランチとリモートブランチを関連付け(トラッキング設定)を行うために
-uオプション(または--set-upstream)を使用します。bash
git push -u origin feature/add-contact-form一度関連付けを行えば、次回以降はこのブランチにいる状態で単に
git pushと実行するだけで、関連付けられたリモートブランチ(この例ではorigin/feature/add-contact-form)にプッシュされるようになります。同様に、このブランチにいる状態で単にgit pullと実行すれば、リモートのorigin/feature/add-contact-formからプルするようになります。
プッシュが成功すると、GitLabのプロジェクトページで、新しいブランチが作成されていることを確認できます。左サイドバーの「Repository」>「Branches」のページを見ると、一覧に表示されているはずです。また、プッシュ時にターミナルに表示されるメッセージに、そのブランチからマージリクエストを作成するためのURLが表示されることもあります。このURLをクリックすると、すぐにマージリクエスト作成画面に遷移できて便利です。
6.2 GitLab Web UIからのブランチ作成
ローカルでコマンドを使うだけでなく、GitLabのWeb UIからも簡単にブランチを作成できます。これは、簡単な修正を加えたい場合や、特定のコミットから一時的にブランチを作成したい場合、あるいはGitコマンドに慣れていない方にとって便利な方法です。
- GitLabのプロジェクトページにアクセスします。
- 左サイドバーの「Repository」>「Branches」を選択します。ブランチ一覧ページが表示されます。
- ブランチ一覧ページの上部にある「New branch」ボタンをクリックします。
- ブランチ作成フォームが表示されます。
- Branch name: 新しく作成するブランチの名前を入力します(例:
fix/typo-on-homepage,refactor/database-connection)。ローカルで作成する場合と同様に、命名規則を考慮して分かりやすい名前をつけましょう。 - Create from: どのブランチ、タグ、またはコミットから新しいブランチを分岐させるかを選択します。デフォルトでは、プロジェクトのデフォルトブランチ(通常
mainまたはmaster)が選択されています。ここをクリックすると、既存のブランチやタグの候補が表示されます。入力フィールドにコミットハッシュを直接入力して、特定の過去のコミットから分岐させることも可能です。通常はmainやdevelopのような安定版のブランチを選択します。
- Branch name: 新しく作成するブランチの名前を入力します(例:
- 「Create branch」ボタンをクリックします。
これでGitLab上に新しいブランチが作成されました。このブランチはまだローカルリポジトリには存在しません(リモートにのみ存在します)。ローカルリポジトリでこの新しいブランチを扱いたい場合は、まずリモートの最新情報を取得する(git fetch origin)必要があります。その後、git switch <ブランチ名>またはgit checkout <ブランチ名>で、リモートトラッキングブランチ(例: origin/fix/typo-on-homepage)に対応するローカルブランチを作成し、そこに切り替えることができます。
“`bash
リモートの最新情報を取得(新しいブランチの情報も含まれる)
git fetch origin
新しく作成されたリモートブランチを元に、ローカルブランチを作成して切り替える
git switch fix/typo-on-homepage
または git checkout fix/typo-on-homepage
“`
git switch <リモートトラッキングブランチ名>(例: git switch origin/fix/typo-on-homepage)と実行すると、detached HEAD状態になってしまうため、通常は上記のようにブランチ名だけを指定してローカルブランチを作成・切り替えるのが正しい方法です。
6.3 保護されたブランチ (Protected Branches)
GitLabの「保護されたブランチ」機能は、特定の重要なブランチ(例: main, master, develop, release/*など)への不用意な変更や直接プッシュを防ぐための強力なセキュリティ機能です。これにより、安定版のコードラインの整合性を保ち、ワークフローを強制することができます。
保護されたブランチには、誰が直接プッシュできるか、誰がマージリクエスト経由でマージできるかといったアクセス権限を細かく設定できます。
なぜ保護されたブランチを使うのか?
- 安定版の保護: 本番環境やリリース候補となるブランチが、開発途中の不安定なコードや未レビューの変更によって破壊されるのを防ぎます。これにより、いつでも安心してこれらのブランチからデプロイやリリースを行える状態を維持できます。
- マージリクエストワークフローの強制: 保護されたブランチに「Allowed to push」を「No one」に設定することで、権限を持つユーザー(通常はMaintainers)であってもそのブランチに直接プッシュすることを禁止できます。これにより、全ての変更が必ずマージリクエストを経由するように強制できます。マージリクエストを通すことで、チームメンバーによるコードレビューや、CI/CDパイプラインによる自動テストの実行が必須となり、変更の品質を確保できます。
- 権限管理: 特定の役割を持つユーザーやグループのみに、保護ブランチへのマージやプッシュを許可するといった細かい権限設定が可能です。例えば、マージはプロジェクトのメンテナーのみが行えるようにし、プッシュはCI/CDシステムのみが行えるように設定するといった、よりセキュアな運用が可能です。
- 強制プッシュの防止: 保護されたブランチに対して強制プッシュ(
git push --forceなど)を禁止できます。強制プッシュはリモートリポジトリの履歴を書き換えてしまう危険な操作であり、チームメンバーのローカルリポジトリとの整合性を壊す可能性があります。保護されたブランチに対して強制プッシュを無効にすることは、履歴の安定性を保つ上で極めて重要です。
保護設定の手順:
- GitLabのプロジェクトページにアクセスします。
- 左サイドバーの「Settings」>「Repository」を選択します。
- ページをスクロールし、「Protected branches」セクションを見つけます。ここに現在保護されているブランチの設定一覧が表示されます。
- 新しく保護したいブランチを設定するには、「Protect a branch」という見出しの下にあるフォームを使用します。
- Branch: 保護したいブランチ名を選択または入力します。ドロップダウンには既存のブランチが表示されます。特定の名前を持つブランチだけでなく、特定のパターン(例:
release/*,hotfix/*)にマッチする全てのブランチを保護することも可能です。*はワイルドカードとして機能します。プロジェクトのデフォルトブランチ(例:main)は通常、初期設定で保護されています。 - Allowed to merge: このブランチへのマージリクエストをマージすることを許可するユーザーやグループ、またはロール(役割:Developer, Maintainerなど)を選択します。通常、ここにはマージの最終承認権限を持つロール(例:
Maintainers)や、特定の承認者グループを設定します。デフォルトはMaintainersです。 - Allowed to push: このブランチに直接プッシュすることを許可するユーザーやグループ、またはロールを選択します。通常、
mainなどの重要なブランチではここをNo oneに設定することで、マージリクエストを経由しない直接プッシュを禁止し、マージリクエストのワークフローを強制します。 もし、特定の自動化されたプロセス(例: CIジョブがバージョンタグをプッシュする場合など)のために直接プッシュを許可する必要がある場合は、Maintainersや特定のユーザー・グループを設定します。開発者が自分のフィーチャーブランチをプッシュできるように、通常、フィーチャーブランチにはこの設定は適用しません(またはフィーチャーブランチのパターンを保護対象に含めない)。 - Allowed to force push: 強制プッシュ(
git push --forceなど)を許可するかどうか。通常は無効(チェックを外すか、No oneを選択)にします。特定の自動化された処理などで例外的に許可する場合を除き、No oneに設定することを強く推奨します。
- Branch: 保護したいブランチ名を選択または入力します。ドロップダウンには既存のブランチが表示されます。特定の名前を持つブランチだけでなく、特定のパターン(例:
- 必要な設定を選択したら、「Protect」ボタンをクリックして設定を保存します。
これで、設定したブランチは保護され、許可されていないユーザーや方法(直接プッシュなど)での変更が制限されます。例えば、「Allowed to push」が「No one」に設定されたブランチにローカルから直接プッシュしようとすると、Gitからエラーが表示され、プッシュが拒否されます。変更を保護ブランチに取り込むには、必ず別のブランチからマージリクエストを作成し、レビューと承認のプロセスを経る必要があります。
既存の保護設定を変更したい場合は、一覧から対象のブランチを探し、「Unprotect」ボタンで一度保護を解除してから再設定するか、GitLabのバージョンによっては設定変更のUIが表示される場合があります。
7. GitLabでのマージリクエスト (Merge Request) を活用する
ブランチを使った開発ワークフローの中心となるのが、GitLabにおけるマージリクエスト(MR)です。マージリクエストは、あるブランチ(ソースブランチ)で行われた変更を、別のブランチ(ターゲットブランチ、通常はmainやdevelopなど)に取り込んでほしいという「提案」であり、その提案に対する議論、コードレビュー、CI/CDパイプラインの実行結果表示、承認、そして最終的なマージを行うためのワークスペースです。GitLabでは、マージリクエストは単なるマージの要求以上の、開発プロセス管理の中核を担う機能となっています。
マージリクエストとは何か?
マージリクエストは、単に「ブランチをマージしてほしい」というリクエストではありません。そこには以下のような情報が集約され、チーム開発におけるコラボレーションと品質管理のハブとなります。
- 変更内容 (Changes): ソースブランチとターゲットブランチの間のコードの差分(Diff)。どのファイルが、どのように変更されたかを一覧で確認できます。新規ファイルの追加、既存ファイルの変更・削除、ファイル名の変更などが分かりやすく表示されます。
- コミット履歴 (Commits): ソースブランチに加えられたコミットの一覧。どのようなステップで開発が進められたかを確認できます。
- パイプライン (Pipelines): このMRの変更内容に対して実行されたCI/CDパイプラインの結果が表示されます。自動テスト(ユニットテスト、統合テストなど)、コード品質チェック(リンター、静的解析)、セキュリティスキャンなどのジョブが実行され、その成否やログを確認できます。CI/CDパイプラインにパスしていることがマージの必須条件となるように設定するのが一般的です。
- 議論 (Discussion): 変更内容についてチームメンバーと議論するためのコメント機能。MR全体に対する一般的なコメントだけでなく、コードの特定の行に対してコメントを残す(インラインコメント)ことも可能です。これにより、具体的なコードに対するフィードバックや質問を効果的に行えます。コードレビューコメントを解決済みとしてマークする機能もあります。
- コードレビュー (Code Review): レビュー担当者がコードを読み、改善点を提案したり、潜在的なバグや設計上の問題を指摘したりします。GitLabは、レビュー担当者のアサイン、コードレビューコメント、変更提案(Suggest Changes)といった機能を提供します。提案された変更は、MRの作者がボタン一つでコミットとして取り込めます。
- 承認 (Approvals): 変更内容に対するレビューが完了し、問題がないことを保証するための仕組みです。保護されたブランチ設定により、マージに最低限必要な承認者の数や、特定のユーザー・グループからの承認を必須とするといったルールを設定できます。承認者はMRを承認(Approve)することで、その変更を推奨する意思を示します。
- 関連するイシュー: この変更が解決するイシューやタスクへのリンク。MRのDescriptionに特定のキーワード(例:
Closes #<イシュー番号>,Fixes #<イシュー番号>)を含めることで、MRがマージされた際に自動的に関連するイシューをクローズすることも可能です。これにより、開発タスクとコード変更を紐付けて管理できます。
マージリクエストを作成する手順:
通常、開発者はローカルでフィーチャーブランチを作成し、そこで作業を進め、コミットを繰り返しながらリモートにプッシュします。開発が一段落ついた段階で、そのブランチの変更内容をターゲットブランチ(例えばmain)に取り込んでもらうために、マージリクエストを作成します。
GitLabでのMR作成は、いくつかの方法があります。どの方法を選んでも、最終的には同じMR作成フォームに辿り着きます。
- ブランチプッシュ後の画面から作成: ローカルから新しいブランチをGitLabにプッシュした直後、ターミナルに「Create merge request for feature/your-branch-name: https://gitlab.com/…」のようなURLが表示されることがあります。そのURLにアクセスすることで、該当ブランチをソースとするMR作成画面にすぐに遷移できます。これが最も迅速な方法の一つです。
- GitLab Web UIのブランチ一覧から作成: GitLabのプロジェクトページにアクセスし、左サイドバーの「Repository」>「Branches」を選択します。ブランチ一覧ページで、MRを作成したいブランチを探し、その行にある「Create merge request」ボタンをクリックします。
- GitLab Web UIのサイドバーから作成: GitLabのプロジェクトページにアクセスし、左サイドバーの「Merge requests」を選択します。マージリクエスト一覧ページの上部にある「New merge request」ボタンをクリックします。すると、ソースブランチとターゲットブランチを選択する画面が表示されるので、適切なブランチを選んで「Compare branches and continue」ボタンをクリックすると、MR作成フォームに遷移します。
- GitLab Web UIからファイルを編集して作成: GitLabのWebエディタでファイルを編集し、コミットする際に「Start a new merge request with these changes」というオプションにチェックを入れることで、その編集内容を含むMRを直接作成できます。これは、READMEファイルや簡単な設定ファイルなどの修正を行う際に便利です。
MR作成フォームでは以下の情報を設定します。これらの情報は、チームメンバーがMRの内容を理解し、レビューやマージの判断を行う上で非常に重要です。
- Source branch: マージしたい変更が含まれているブランチ(あなたが作業したフィーチャーブランチやバグ修正ブランチなど)。
- Target branch: 変更を取り込みたい先のブランチ(
mainやdevelopなど、通常は保護されているブランチ)。デフォルトでプロジェクトのデフォルトブランチが選択されていることが多いです。 - Title: マージリクエストの目的を簡潔に示すタイトル(例:
feat: Add user profile page,fix: Resolve database connection issue,refactor: Improve performance of login endpoint)。タイトルの命名規則をチームで定めておくと、MR一覧が見やすくなります。 - Description: マージリクエストの詳細な説明。どのような変更を行ったか、なぜその変更が必要か、関連するイシューへのリンク、考慮事項、テスト方法、スクリーンショットなどを記述します。Markdown形式で記述でき、チェックリストやタスクリストを含めることもよくあります(例:
- [x] Added user profile view,- [ ] Wrote unit tests)。イシュー番号を記述することで、関連するイシューとして自動的にリンクされます(例:Closes #123と記述すると、MRマージ時にイシュー123が自動でクローズされます)。 - Assignees: このMRを担当する開発者(通常はMRを作成した本人)を割り当てます。これにより、誰がそのMRの責任者であるかが明確になります。
- Reviewers: このMRのコードレビューを依頼したいチームメンバーを割り当てます。レビュー担当者は、MRの変更内容を確認し、フィードバックを提供します。設定により、レビュー担当者を必須にしたり、特定のユーザーやグループから選ばれるようにしたりできます。
- Labels: プロジェクト内で定義されたラベル(例:
backend,frontend,bug,enhancement,documentation,work in progressなど)を付けて分類します。これにより、MR一覧をラベルで絞り込んだり、イシューボード上でMRを管理したりできます。 - Milestone: 関連するマイルストーン(開発期間やリリースの目標)を設定します。
- Due date: このMRを完了させたい期日を設定します。
- CI/CD: パイプラインが自動的にトリガーされるように設定されている場合、MR作成と同時にCI/CDパイプラインが実行されます。実行中のパイプラインや最新のパイプライン結果がMRページに表示されます。
- Options: マージに関するオプションを設定できます。
Delete source branch when merge request is accepted: マージが完了した際に、ソースブランチ(フィーチャーブランチなど)を自動的に削除するかどうか。通常はチェックを入れておきます。Squash commits when merge request is accepted: ソースブランチ上の複数のコミットを一つにまとめてマージするかどうか。フィーチャーブランチの履歴を細かく分けて作業した場合などに、マージ先のブランチの履歴をシンプルに保ちたい場合に利用します。Merge options: マージ方法に関する詳細な設定(例: Fast-forwardマージを許可するかなど、保護ブランチ設定によって制御されることもあります)。
これらの情報を入力し、「Create merge request」ボタンをクリックすると、マージリクエストが作成され、ターゲットブランチのメンバーやレビュー担当者に通知されます(設定による)。
マージリクエストのレビューと承認:
作成されたMRは、チームメンバーによるレビュー対象となります。MRページでは、チームメンバーは「Changes」タブでコードの差分を確認し、「Overview」タブや「Changes」タブの特定の行に対してコメントを残すことで、コードに関するフィードバックや質問を行います。作者は寄せられたコメントに対応し、必要に応じてローカルでコードを修正し、追加のコミットをソースブランチにプッシュしてMRを更新します。プッシュされた新しいコミットは自動的にMRに取り込まれ、CI/CDパイプラインも再度実行されます。
レビュー担当者は、コードが要件を満たしているか、設計原則に従っているか、コード規約に沿っているか、潜在的な問題がないかなどを確認します。議論や修正を経てコードが良好な状態になったと判断したら、承認 (Approve) を行います。保護されたブランチ設定によっては、マージに特定人数以上の承認が必要となるように設定されている場合があります。これにより、複数の目でコードをチェックし、品質を担保できます。
CI/CDパイプライン:
MRが作成または更新されると、GitLab CI/CDパイプラインが自動的に実行されるように設定されていることが多いです。.gitlab-ci.ymlファイルで定義されたジョブ(ビルド、テスト、静的解析など)が、MRに含まれる変更内容に対して実行されます。パイプラインの結果はMRページに表示され、成功(緑のチェックマーク)していることがマージの条件となるのが一般的です。例えば、全ての自動テストにパスしなければマージできない、といったルールを設けることができます。これは、変更がコードベース全体の品質を損なわないことを保証する上で非常に重要です。
マージの実行:
全てのレビューが完了し、必要な承認が得られ、CI/CDパイプラインが成功したら、マージの準備が整います。ターゲットブランチにマージする権限を持つユーザー(通常はメンテナーや、マージリクエストの担当者自身であり、かつAllowed to merge権限を持つユーザー)が、MRページにある「Merge」ボタンをクリックしてマージを実行します。
マージ方法にはいくつかのオプションがありますが、GitLabのWeb UIでデフォルトで提供されるのは以下のいずれかです。
- Merge commit: ソースブランチの全てのコミットをターゲットブランチに取り込み、新しいマージコミットを作成します。これがデフォルトの動作です。履歴はブランチが分岐・合流した様子を忠実に表します。いつ、どのブランチから、どのブランチにマージが行われたかという事実が履歴に明示的に残ります。
- Squash and merge: ソースブランチ上の複数のコミット(MRに含まれる全てのコミット)を一つにまとめて(スカッシュ)、それをターゲットブランチに新しい単一のコミットとして追加します。この際、スカッシュされたコミットの内容を統合したマージコミットも同時に作成されます。フィーチャーブランチの履歴が「WIP」のような細かいコミットで多数含まれている場合などに、マージ先のメインブランチの履歴をシンプルで分かりやすく保つために使われます。スカッシュされたコミットの詳細な履歴は、MRのページで確認できます。
- Fast-forward merge (when possible): ソースブランチがターゲットブランチからのみ進んでおり、ターゲットブランチに新しいコミットがない場合に、ターゲットブランチのポインタをソースブランチの先端に移動させるだけ(早送り)でマージコミットを作成しません。これにより、履歴が直線的になります。GitLabのMRでは、通常、マージコミットを作成するオプションがデフォルトで推奨されます(特に保護ブランチに対して)。
マージ実行後、通常はソースブランチ(フィーチャーブランチ)は役目を終え、不要になります。「Delete source branch when merge request is accepted」というオプションにチェックを入れておけば、マージと同時にGitLabが自動的にリモートのソースブランチを削除してくれます。リモートブランチが削除されたら、ローカルブランチも手動で削除して整理しましょう(git branch -d <ローカルブランチ名>)。これにより、ブランチ一覧がクリーンに保たれます。
マージ競合の解決:
マージリクエストを作成した際や、ターゲットブランチ(例: main)が更新された際にマージ競合が発生することがあります。GitLabはMRページで競合が発生していることを通知し、マージがブロックされた状態になります。競合が発生しているファイルを確認できます。
対処法:
* GitLab Web UIでの解決: GitLabは簡単な競合であればWeb UI上で解決できるエディタ機能を提供します。MRページの競合通知から「Resolve conflicts」ボタンをクリックすると、競合ファイルが表示され、エディタ上で<<<<<<<, =======, >>>>>>>マーカーを見ながら手動で修正できます。変更内容を決定し、マーカーを削除した後、「Commit to source branch」ボタンをクリックすることで、競合を解決する新しいコミットがソースブランチに追加され、MRが更新されます。
* ローカルでの解決: 複雑な競合の場合や、使い慣れたエディタで作業したい場合は、ローカルリポジトリで競合を解決します。
1. ターゲットブランチ(例: main)を最新の状態にプルします。まずターゲットブランチに切り替え (git switch main)、最新の状態を取得・反映します (git pull origin main)。
2. 競合を解決したいソースブランチに切り替えます。git switch feature/my-feature
3. ターゲットブランチをマージしようとします。git merge main
4. ここで競合が発生し、Gitがマージを中断します。「CONFLICT」というメッセージが表示され、git statusコマンドで競合しているファイル(「Unmerged paths」として表示されます)を確認できます。
5. 競合しているファイルをエディタで開き、<<<<<<< (あなたのブランチの変更), ======= (区切り), >>>>>>> (マージしたい相手のブランチの変更) マーカーに挟まれた部分を手動で編集して競合を解決します。最終的に残したい内容だけを残し、競合マーカーは全て削除します。
6. 競合を解決したファイルをステージングします。git add <競合を解決したファイル>
7. 全ての競合ファイルを解決し、ステージングしたら、マージコミットを完了させます。git commit(Gitが自動生成したマージコミットメッセージをそのまま使うことが多いですが、必要であれば編集します)。これにより、競合解決済みのマージコミットがローカルのソースブランチの先端に追加されます。
8. 解決済みのソースブランチ(新しいマージコミットを含む)をリモートにプッシュします。git push origin feature/my-feature
9. GitLabのMRページに戻ると、競合が解決されていることが表示され、マージ可能になります。
マージ競合の解決は最初は難しく感じるかもしれませんが、これは並行開発において避けられない作業です。慌てずに、Gitのメッセージやgit statusの表示をよく確認し、手順に従って一つずつ解決していくことが重要です。
8. 開発ワークフローの例とブランチ戦略
チームで開発を行う際には、どのようなブランチ運用ルールで進めるかという「ブランチ戦略(Branching Strategy)」を定めることが重要です。明確なブランチ戦略は、開発プロセスを標準化し、チームメンバー間の連携を円滑にし、コードの整合性を保つ上で役立ちます。様々な戦略がありますが、ここではシンプルで一般的なものをいくつか紹介し、GitLabでの実装の考え方を述べます。
-
フィーチャーブランチワークフロー (Feature Branch Workflow):
これがGitLabを使った開発で最も一般的で推奨されるワークフローです。中心となるのは、安定版またはメインの開発ラインを表すメインブランチ(慣習的にmainまたはmaster、あるいはdevelop)です。新しい機能開発や比較的大きな改修、バグ修正を行う際には、必ずこのメインブランチから分岐させて専用のフィーチャーブランチを作成します。- メインブランチ:
main(またはmaster/develop)。常にデプロイ可能(mainの場合)または開発進行中の最も安定したコードを保持するブランチです。このブランチへの直接プッシュは禁止し(GitLabの保護されたブランチ機能で設定)、必ずマージリクエスト経由で行います。 - フィーチャーブランチ:
feature/<機能名>またはbugfix/<イシュー番号/説明>。新しい機能開発やバグ修正を行う際に、メインブランチから分岐させて作成するブランチです。開発者は自分の担当するタスクごとにこのブランチを作成し、この上で作業、コミットを行います。作業中は適宜リモートの同名ブランチにプッシュしてバックアップや進捗共有を行います。開発完了後、メインブランチに対してマージリクエストを作成します。 - サポートブランチ(オプション): リリース準備用の
release/*ブランチや、本番環境の緊急修正用のhotfix/*ブランチなどを設けることもありますが、フィーチャーブランチワークフロー単体ではこれらのブランチは必須ではありません。Git FlowをよりシンプルにしたGitLab Flowでは、これらの役割もフィーチャーブランチやmainブランチへのタグ付けで管理することが多いです。
ワークフローの流れ:
1. 作業開始: 新しい機能やバグ修正の作業を開始する前に、ベースとなるメインブランチ(例:main)の最新の状態をローカルに取り込みます (git switch main->git pull origin main)。これは、常に最新の安定版コードから作業を開始するためです。
2. フィーチャーブランチの作成と切り替え: 最新のメインブランチから、作業内容を表す名前のフィーチャーブランチを作成し、そこに切り替えます (git switch -c feature/new-feature-name)。
3. 開発とコミット: 新しいブランチで開発作業を行います。コードを編集し、git addでステージング、git commitでコミットを繰り返します。小さな単位でこまめにコミットするのが良いプラクティスです。
4. リモートへのプッシュ: 作業の区切りや一日の終わりなど、適宜リモートの同名フィーチャーブランチにプッシュします (git push origin feature/new-feature-name)。これはコードのバックアップになり、チームメンバーに進捗を共有できます。初回のプッシュでは-uオプションを忘れずに (git push -u origin feature/new-feature-name)。
5. 最新のメインブランチの取り込み(必要に応じて): 開発中にメインブランチが進んだ場合、自分のフィーチャーブランチにも最新の変更を取り込む必要があります。これは、git merge main(フィーチャーブランチにいる状態で)またはgit rebase mainといった操作で行います。これにより、マージ時の競合を早期に発見・解決できます。
6. マージリクエストの作成: 開発が完了し、テストが済んだら、GitLabでfeature/new-feature-nameブランチからターゲットブランチ(例:main)に対してマージリクエストを作成します。MRの説明欄には、変更内容、関連イシュー、自己レビューで気付いた点などを詳細に記述します。
7. レビュー、議論、CI/CD、承認: チームメンバーはMRページでコードレビューを行い、コメントでフィードバックや質問を行います。CI/CDパイプラインが実行され、自動テスト結果などが表示されます。レビュー担当者が承認(Approve)を行います。必要に応じて、コードの修正や追加コミットを行います。
8. マージ: 必要なレビューと承認が得られ、CI/CDパイプラインが成功したら、マージ権限を持つユーザー(またはMRの作者自身)がMRをターゲットブランチにマージします。通常は「Delete source branch when merge request is accepted」オプションにチェックを入れておきます。
9. クリーンアップ: マージ後、リモートのフィーチャーブランチは自動的に削除されるため、ローカルの同名フィーチャーブランチも削除して整理します (git branch -d feature/new-feature-name)。このワークフローはシンプルで理解しやすく、コードレビューと並行開発を促進するのに非常に適しています。多くの小~中規模プロジェクトで採用されています。GitLabの機能(特にマージリクエストと保護ブランチ)と非常に親和性が高いです。
- メインブランチ:
-
Git Flow:
フィーチャーブランチワークフローをより厳密にし、特定の役割を持つ複数の長期ブランチを定義した戦略です。Vincent Driessenによって提唱され、広く知られています。- 永続ブランチ:
master(またはmain): 常にリリースされた本番コードを反映します。タグ付けによってバージョン管理を行います。このブランチへのコミットは、releaseブランチやhotfixブランチからのマージのみです。develop: 次期リリースの開発コードを反映します。フィーチャーブランチは通常このブランチから分岐し、マージされます。
- サポートブランチ:
feature/*: 新機能開発用。developから分岐し、developにマージ。release/*: リリース準備用。developから分岐し、リリースタグを付けてmasterとdevelopにマージ。hotfix/*: 本番環境の緊急バグ修正用。masterから分岐し、修正後masterとdevelopにマージ。
Git Flowは複雑さが増しますが、複数の開発ライン(本番リリース、次期開発)を同時に管理し、リリースプロセスを明確に定義するのに適しています。大規模プロジェクトや、厳密なリリース管理が必要な場合に採用されることがあります。GitLabはGit Flowを直接サポートする特別な機能はありませんが、これらのブランチ命名規則やワークフローをチーム内で合意して運用することは可能です。Git Flowを支援するGitコマンドラインツール(git-flow)も存在します。ただし、Git Flowはマージが多いため履歴が複雑になりがちで、入門者にとっては学習コストが高い側面もあります。
- 永続ブランチ:
-
GitLab Flow:
GitLabが推奨するブランチ戦略で、Git Flowよりもシンプルです。GitLab Flowは、Git Flowの複雑さを避けつつ、CI/CDとの連携を重視します。中心となるのはmainブランチであり、全ての変更はこのmainブランチにマージリクエスト経由で統合されます。環境(ステージング、本番など)へのデプロイは、mainブランチまたは特定のタグから行われます。環境ごとのブランチ(例:production)を持つ場合もありますが、その場合もmainからのみ変更を取り込むようにします。- 永続ブランチ:
main(またはmaster)。これが全ての変更の統合点となります。安定版であり、デプロイ可能な状態を保ちます。 - フィーチャーブランチ:
feature/*やbugfix/*。mainから分岐し、作業完了後mainにマージリクエスト。 - 環境ブランチ(オプション):
staging,productionなど。mainブランチがこれらの環境ブランチにマージされることで、それぞれの環境へのデプロイをトリガーします。これにより、ブランチの状態とデプロイされたコードの状態を一致させやすくなります。ただし、全ての環境にブランチを用意する必要はなく、CI/CDパイプラインでmainブランチから直接デプロイを制御することも可能です。
GitLab Flowは履歴がシンプルになりやすく、マージリクエストとCI/CDとの連携が容易です。フィーチャーブランチワークフローに環境ブランチを追加したようなイメージで、フィーチャーブランチワークフローに慣れたチームが次に検討しやすい戦略と言えます。
- 永続ブランチ:
どのブランチ戦略を採用するかは、プロジェクトの規模、チームの人数、開発プロセス、組織文化などによって異なります。重要なのは、チーム全体でどの戦略を採用するか合意し、そのルールをドキュメント化して共有し、それを守って運用することです。GitLabの保護されたブランチやマージリクエストの承認ルールなどの機能を活用することで、これらの戦略を技術的に強制し、ワークフローをスムーズに進めることができます。チームの状況に合わせて、最初はシンプルなフィーチャーブランチワークフローから始め、必要に応じてGitLab Flowなどを検討するのがおすすめです。
9. より高度なブランチ操作 (入門レベル+)
ブランチを使った開発をさらに効率的に行うために役立つ、いくつかの応用的なGitコマンドを紹介します。これらは必須ではありませんが、知っておくと非常に便利で、複雑な状況に対応する際に役立ちます。使用にはそれぞれのコマンドが履歴に与える影響を理解しておく必要があります。
-
スタッシュ (Stash):
現在作業しているブランチで変更を加えているが、その変更はまだコミットできる状態ではない(作業途中である)、あるいは一時的にその変更を退避させて、別のブランチに切り替えて少し別の作業をしたい、といった場合に利用します。git stashコマンドは、現在のワーキングツリーとステージングエリア(インデックス)の変更を一時的な「スタッシュ」として保存し、ワーキングツリーを最後にコミットした状態(クリーンな状態)に戻します。“`bash
現在の変更を一時退避する。メッセージをつけると何の変更か分かりやすい。
git stash save “WIP: partial feature implementation”
メッセージなしでも可: git stash
退避した変更一覧を見る。スタッシュはスタックのように管理され、stash@{0}, stash@{1}, … のように番号が振られる。
git stash list
最新(stash@{0})の退避した変更を現在のブランチのワーキングツリーに元に戻す(スタッシュリストには残る)
git stash apply
最新(stash@{0})の退避した変更を現在のブランチのワーキングツリーに元に戻し、スタッシュリストから削除する
git stash pop
特定のスタッシュ(例: stash@{1})を元に戻す(スタッシュリストには残る)
git stash apply stash@{1}
特定のスタッシュ(例: stash@{1})を元に戻し、スタッシュリストから削除する
git stash pop stash@{1}
スタッシュリストから特定のスタッシュ(例: stash@{2})を削除する(元に戻さずに)
git stash drop stash@{2}
スタッシュを全て削除する
git stash clear
“`スタッシュは非常に便利ですが、あくまでローカルな一時退避手段です。リモートにプッシュされることはありません。複数のスタッシュを積み重ねることもできますが、管理が煩雑になりがちなので、あまり多くなりすぎないように注意しましょう。
-
リベース (Rebase):
ブランチの履歴を整理するための強力なコマンドです。git rebase <ベースとなるブランチ>を実行すると、現在のブランチが、指定したベースブランチの先端から分岐したかのように、自身のコミット履歴を「書き換え」ます。具体的には、現在のブランチがベースブランチから分岐した地点以降のコミットを一時的に退避し、現在のブランチの先端をベースブランチの先端に移動させ、その後、退避していたコミットを一つずつその上に再適用していきます。この再適用される各コミットは、元々とは異なる親を持つため、新しいコミットとして記録され、ハッシュ値も変わります。例えば、
featureブランチをmainブランチから分岐して開発している最中に、mainブランチに新しいコミットが追加されたとします。featureブランチを最新のmainの状態に追従させる方法は二つあります。
1. マージ (git merge main):featureブランチにmainを取り込む。もしfeatureブランチとmainブランチの両方で新しいコミットが追加されていれば、新しいマージコミットが作成され、履歴はブランチが分岐・合流した様子を表す非直線的な形になります。
2. リベース (git rebase main):featureブランチのコミットを一時退避し、featureブランチの分岐点をmainの先端に移動させ、退避していたコミットをその上に再適用します。これにより、featureブランチはあたかも最新のmainから分岐して開発されたかのように見え、履歴は直線的になります。マージコミットは作成されません(Fast-forwardマージのように見えますが、実際には既存コミットの再適用です)。“`bash
リベースしたいフィーチャーブランチに切り替える
git switch feature/my-feature
ベースとなるブランチ(例: main)の最新を取得しておく
git fetch origin main # リモートの main を取得
git pull origin main # ローカルの main も更新
feature ブランチを main の先端にリベースする
git rebase origin/main # リモートの main にリベースする場合
git rebase main # ローカルの main にリベースする場合
“`リベースの実行中、もしリベースしようとしているコミットとベースブランチの間に競合が発生した場合、Gitはリベースを中断します。開発者は競合を手動で解決し、
git add <解決したファイル>でステージングした後、git rebase --continueを実行してリベースを続行する必要があります。中断したい場合はgit rebase --abortです。リベースは履歴を綺麗に(直線的に)保つことができるというメリットがある反面、いくつかの重要な注意点があります。
- リモートにプッシュ済みのコミットをリベースしない: リベースは既存のコミットのハッシュ値を変更します。もしリベース対象のコミットが既にリモートにプッシュされていて、他の開発者がそのリモートの履歴を元に作業している場合、リベースによってリモートとローカルの履歴に互換性がなくなります。この状態でリモートにプッシュしようとすると、
non-fast-forwardエラーが発生し、プッシュが拒否されます。このエラーを解消するためにgit push --force(または--force-with-lease)を使うことも可能ですが、これはリモートの履歴を強制的にあなたのローカル履歴に上書きしてしまうため、他の開発者のローカルリポジトリとの整合性を壊し、彼らの作業を複雑にする可能性が非常に高く、チーム開発では極めて避けるべき操作です。したがって、基本的には、まだ自分一人だけが作業しており、リモートにプッシュしていないローカルブランチでのみリベースを使用する、あるいはチームでリベースの使用について明確なルールと高度な理解を持っている場合に限り、そのルールに従って慎重に使用すべきです。マージリクエストのレビュー中に、レビュアーからのフィードバックを取り込んだり、最新のターゲットブランチを取り込んだりするために、一時的にリモートにプッシュ済みのフィーチャーブランチでリベースを行うことがありますが、これは関係者全員がそのルールを理解・合意している場合に限られます。 - 競合解決が複数回発生する可能性: リベースはコミットを一つずつ再適用するため、ベースブランチが進んでいる量が多い場合、再適用する各コミットで競合が発生し、その都度解決を繰り返す必要があるかもしれません。これはマージよりも競合解決の手間が増える可能性があります。
初心者の方は、まずはマージで履歴を追従させる方法(
git pull)から慣れるのが良いでしょう。リベースは、履歴を整理したい場合に、その危険性を理解した上で慎重に利用するコマンドです。 - リモートにプッシュ済みのコミットをリベースしない: リベースは既存のコミットのハッシュ値を変更します。もしリベース対象のコミットが既にリモートにプッシュされていて、他の開発者がそのリモートの履歴を元に作業している場合、リベースによってリモートとローカルの履歴に互換性がなくなります。この状態でリモートにプッシュしようとすると、
-
チェリーピック (Cherry-pick):
あるブランチにある特定のコミットだけを、別のブランチに取り込みたい場合に利用します。git cherry-pick <コミットハッシュ>コマンドを実行すると、指定したコミットで行われた変更内容を、現在のブランチの先端に新しいコミットとして適用します。これは、特定のバグ修正だけを緊急で別のブランチに取り込みたい場合や、あるフィーチャーブランチで行われた一部の変更だけを別のフィーチャーブランチに流用したい場合などに役立ちます。“`bash
変更を取り込みたいターゲットブランチに切り替える
git switch <ターゲットブランチ>
取り込みたいコミットのハッシュ値を指定してチェリーピック
git cherry-pick <コミットハッシュ>
“`コミットハッシュは
git logコマンドやGitLabのWeb UIなどで確認できます。チェリーピックもリベースと同様、競合が発生する可能性があり、その場合は手動で解決してからgit cherry-pick --continueで続行します。中断したい場合はgit cherry-pick --abortです。チェリーピックは履歴を直線的に保ちますが、元々のコミットとは異なる新しいコミットが作成されるため、履歴上は重複した内容のコミットが存在することになります。また、対象のコミットの親コミットは引き継がれません。 -
タグ (Tag):
特定のコミットに永続的で分かりやすい名前を付けるための仕組みです。通常、ソフトウェアのリリースバージョン(例:v1.0.0,v2.0.1)を示すために使用されます。ブランチとは異なり、タグは一度付けられると通常は移動しません(削除・再作成は可能ですが推奨されません)。特定のリリース時点のコードを参照したい場合に便利です。“`bash
最新コミットにタグを付ける
git tag <タグ名>
git tag -a <タグ名> -m “タグメッセージ” # 軽量タグではなく、付加情報付きのタグを作成過去の特定のコミットにタグを付ける
git tag <タグ名> <コミットハッシュ>
タグ一覧を表示
git tag
リモートにタグをプッシュ
git push origin <タグ名> # 特定のタグをプッシュ
git push origin –tags # 全てのタグをプッシュ
“`GitLabでは、タグをリリース管理と連携させることができます。タグを作成することで、GitLabの「Deployments」>「Releases」セクションに新しいリリースエントリが自動的に作成されるように設定できます。
10. トラブルシューティング
Git/GitLabを使ったブランチ操作で遭遇しがちな問題と、その原因、そして対処法を紹介します。
-
non-fast-forwardエラーでプッシュできない:
git pushを実行した際に「! [rejected] <ローカルブランチ> -> <リモートブランチ> (non-fast-forward)」のようなエラーが表示され、プッシュが拒否されることがあります。これは、あなたがローカルでプッシュしようとしているブランチ(例:main)のリモート上の同じブランチ(例:origin/main)が、あなたが最後にプルまたはフェッチした時点から更新されている(他の開発者が先にプッシュした、またはGitLab Web UIで変更が加えられたなど)場合に発生します。あなたのローカルブランチの履歴が、リモートブランチの履歴に対して「早送り」(Fast-forward)できない状態になっているためです。つまり、あなたのローカルにあるリモートトラッキングブランチorigin/<ブランチ名>が指すコミットよりも、リモート自体のブランチが進んでしまっています。原因: あなたがローカルで作業・コミットしている間に、他の誰かが同じリモートブランチに新しいコミットをプッシュした。
対処法: まずリモートの最新の変更をローカルに取り込み、あなたの変更と統合(マージまたはリベース)してからプッシュし直す必要があります。“`bash
1. リモートの最新を取得する
まずローカルの現在のブランチが、リモートのどのブランチをトラッキングしているか確認(省略可)
git status # “Your branch is behind ‘origin/main’ by X commits, and can be fast-forwarded.” のような表示があれば、ローカルが遅れている
2. リモートの変更をローカルに取り込み、統合する
方法A: マージする (推奨、履歴にマージコミットが残る)
これは最も一般的で安全な方法です。他の開発者の履歴に干渉しません。
git pull origin <現在のブランチ名>
例: git pull origin main
git pullは内部的にgit fetchとgit mergeを実行します。リモートから最新を取得し(fetch)、ローカルの現在のブランチにマージします。
この際にマージ競合が発生する可能性があり、その場合は手動で解決が必要です。
方法B: リベースする (履歴が直線的になるが、注意が必要)
これは、ローカルのコミットをリモートの最新コミットの「上」に再適用する操作です。
git fetch origin # まずリモートの最新をフェッチ
git rebase origin/<現在のブランチ名> # リモートトラッキングブランチに対してリベース
例: git rebase origin/main
リベースは履歴を書き換えるため、「リモートにプッシュ済みのコミットをリベースしない」という注意点を強く意識してください。
マージ競合が発生する可能性があり、その場合はコミットごとに解決が必要です。
3. マージ/リベース中に競合が発生したら解決する (上記セクション参照)
4. 変更が統合できたら、再度プッシュする
git push origin <現在のブランチ名>
例: git push origin main
“`
通常は
git pullでマージするのがシンプルで安全です。リベースを選択する場合は、その影響を十分に理解し、チームのルールに従ってください。 -
マージ競合が発生した:
マージ(git merge)やリベース(git rebase)、チェリーピック(git cherry-pick)、あるいはgit pull(内部でマージを行うため)の際に発生します。これは、二つのブランチで同じファイルの同じ箇所が異なる内容に変更されており、Gitが自動的に統合できない状況です。原因: 複数の開発者が同じファイルの同じ行を異なる方法で変更し、それらを統合しようとした。
対処法: 上記セクション「7. GitLabでのマージリクエスト (Merge Request) を活用する」のマージ競合の解決方法を参照してください。ローカルまたはGitLab Web UIで、競合マーカー(<<<<<<<,=======,>>>>>>>)が表示されたファイルを編集し、最終的に残したい内容を手動で決定します。その後、変更をステージングし、マージ/リベース/チェリーピック操作を完了させます。 -
間違ったブランチにコミットしてしまった:
本来コミットするべきではなかったブランチ(例:mainブランチや、間違ったフィーチャーブランチ)でコミットを作成してしまった場合。原因: コミットする前に正しいブランチに切り替えるのを忘れた。
対処法:
1. まだプッシュしていない場合:
* 最新のコミットだけをやり直す: もし間違ったコミットが最新のものであり、まだリモートにプッシュしていない場合、git reset HEAD~1コマンドで直前のコミットを取り消し、変更をワーキングツリーに戻します。その後、正しいブランチに切り替えてから (git switch <正しいブランチ名>)、改めてgit addとgit commitを実行します。これは最も簡単で推奨される方法です。
* コミットはそのままにして、コミットを正しいブランチに移動させる:git cherry-pick <間違ったコミットハッシュ>で正しいブランチにそのコミットを適用し、その後元のブランチに戻ってgit reset --hard HEAD~1で間違ったコミットを削除する、といった方法もありますが、少し複雑です。まずはgit reset HEAD~1の方法が簡単です。
2. 既にプッシュしてしまった場合:
* 間違ったコミットを打ち消す新しいコミットを作成する:git revert <間違ったコミットハッシュ>コマンドで、間違ったコミットで行われた変更を元に戻す新しいコミットを作成します。これは既存の履歴を壊さず、安全です。その後、正しいブランチに切り替えてから、手動で変更を反映させるか、元のコミット内容をチェリーピックし直すなどの対応を検討します。
* プッシュ済みの履歴の書き換え(git reset --hardからの強制プッシュなど)は、チーム開発では他の開発者に深刻な影響を与える可能性があるため、極めて避けるべきです。どうしても必要な場合は、必ずチームメンバーと相談し、全員が影響を理解・対処できる状態で行う必要があります。 -
ブランチを間違えて削除してしまった:
git branch -dやgit branch -Dでローカルブランチを削除してしまった場合。原因: 誤って削除コマンドを実行した。
対処法:
* リモートにそのブランチがまだ存在する場合:git fetch originでリモートの情報を取得し(リモートトラッキングブランチが更新される)、git switch <削除してしまったブランチ名>またはgit checkout <削除してしまったブランチ名>を実行すると、リモートトラッキングブランチを元にローカルブランチを再作成できます。
* リモートにも存在しない場合(ローカルで作成してプッシュしていなかったなど): 幸いにも、Gitは通常、コミットやブランチの参照をすぐに完全に削除しません。git reflogコマンドを使うと、ローカルリポジトリで行った操作の履歴(HEADが過去に指していた場所の履歴)を見ることができます。そこに、削除してしまったブランチがかつて指していたコミットハッシュが含まれている可能性があります。git reflogの出力から目的のコミットハッシュ(例:abcdefg)を見つけたら、そのコミットから新しいブランチを再作成できます。git switch -c <元のブランチ名> abcdefgまたはgit checkout -b <元のブランチ名> abcdefgを実行します。これは、特定のコミットハッシュを元に新しいブランチを作成し、そこに切り替えるコマンドです。git reflogは非常に強力なリカバリツールなので、覚えておくと良いでしょう。
これらのトラブルシューティングは、Gitを使った開発においてよく遭遇するものです。慌てずにgit statusやgit log、git reflogなどのコマンドで現在の状況を確認し、落ち着いて原因と対処法を判断することが重要です。必要であれば、チームメンバーに助けを求めることもためらわないでください。
11. まとめと次のステップ
この記事では、GitLabを使った開発におけるブランチの作成と管理に焦点を当てて、Gitの基本的な概念から、GitLabの連携機能、マージリクエストの活用、一般的なワークフロー、そして応用的な操作やトラブルシューティングまで、幅広く詳細に解説しました。
ブランチは、GitおよびGitLabにおける並行開発とコード管理の核となる仕組みです。その重要性と基本的な使い方を理解し、適切に運用することで、開発の効率性、安全性、そしてチームメンバー間のコラボレーションを大きく向上させることができます。
- ブランチを使うことの重要性: 複数の開発者が互いの作業に影響を与えることなく並行して開発を進められること、機能や実験を分離できること、安定版のコードを保護できること、そしてコードレビューやマージリクエストといったコラボレーションの基盤となること。これらが、ブランチが現代の開発において不可欠である理由です。
- Gitの基本コマンド:
git branchでの一覧表示・作成・削除、git switch/git checkoutでの切り替えなど、ローカルでのブランチ操作の基本的なコマンドを習得することが、GitLabとの連携の第一歩です。 - GitLabとの連携: ローカルで作成したブランチを
git pushでリモート(GitLab)に共有し、GitLabのWeb UIからもブランチを作成・管理できることを理解しました。 - 保護されたブランチ: GitLabの保護されたブランチ機能を使って、重要なブランチへの直接プッシュを禁止し、マージリクエストによるワークフローを強制することの重要性を学びました。
- マージリクエストの活用: マージリクエスト(MR)が、コードレビュー、議論、CI/CD結果表示、承認といった開発プロセス全体を集約するGitLabの中核機能であることを理解し、その作成からマージまでの流れを詳細に解説しました。
- ブランチ戦略: フィーチャーブランチワークフロー、Git Flow、GitLab Flowといった代表的なブランチ戦略の概要を知り、チームの状況に合わせて適切な戦略を選択・運用することの重要性を認識しました。
- 応用操作とトラブルシューティング: スタッシュ、リベース、チェリーピックといった応用的なGitコマンドと、よくあるトラブル(
non-fast-forward、マージ競合、間違ったコミット/削除など)の対処法を知ることで、より複雑な状況に対応できるようになります。
GitやGitLabは奥が深く、ここで紹介した以外にも多くの機能やコマンドが存在します。しかし、ブランチの概念とその基本的な操作、GitLabでのマージリクエストを使ったワークフローをしっかり理解し、実践できるようになれば、多くの開発プロジェクトに自信を持って参加し、チーム開発の一員として貢献できる確固たる基礎が築けたと言えるでしょう。
次のステップとして:
- 実践を積む: この記事で学んだコマンドや概念を、実際に手を動かして試してみましょう。小さな練習用プロジェクト(個人プロジェクトでも、チームのテストプロジェクトでも良い)を作成し、ブランチを作成・切り替え・変更・コミット・プッシュ・マージ(ローカルで)といった一連の操作を繰り返し行うことが、理解を定着させる一番の近道です。意図的に競合を発生させて解決する練習も有効です。
- チームのワークフローを理解する: もしあなたがチームで開発に参加している場合は、チームが採用しているブランチ戦略やマージリクエストに関する具体的なルール(ブランチ名の命名規則、必須レビュー担当者、承認数、マージの方法など)を確認し、それに従って作業を進めましょう。疑問点があれば遠慮なくチームメンバーやメンテナーに質問してください。チーム内での共通理解は、スムーズな開発に不可欠です。
- GitLabの他の機能を学ぶ: GitLabはブランチ管理以外にも、イシューボードでのタスク管理、CI/CDによる自動テスト・デプロイ、Wikiでのドキュメント管理など、多くの強力な機能を提供しています。これらの機能を学ぶことで、開発プロセス全体をさらに効率化し、品質を向上させることができます。特に、CI/CDパイプラインをブランチやマージリクエストと連携させることは、現代の開発ワークフローにおいて非常に重要です。
- 公式ドキュメントを参照する: Gitの公式ドキュメント (git-scm.com/doc) や、GitLabの公式ドキュメント (docs.gitlab.com) は非常に詳細かつ正確な情報源です。特定のコマンドや機能についてさらに詳しく知りたい場合、あるいは最新の情報を確認したい場合は、これらの公式リソースを参照することをお勧めします。
- 継続的に学ぶ: GitやGitLabは常に進化しています。新しいバージョンで追加される機能や改善点を学び続けることで、より効率的かつ効果的にツールを活用できるようになります。
GitとGitLabの習熟は、現代のソフトウェア開発者にとって非常に価値のあるスキルです。この記事が、あなたのGitLab入門の第一歩として、そしてブランチを使いこなすための確かな基礎となることを願っています。並行開発のパワーを活用し、効率的なコード管理を実現してください。
Happy Coding!