【Git】Gitの基礎を学習しよう!ブランチとマージの基本!

Gitはリポジトリ内に複数のブランチを持つことができます。
デフォルトではmasterというブランチが使用されていますが、masterブランチをコピーして派生した別のブランチを作ることが可能です。
この時、新しく作成したブランチはmasterブランチのファイルとコミット履歴を引き継ぎますが、以降に発生するコミット等は元のmasterブランチとは別の道を辿るものとなります。

分岐したブランチを作ることで、元のブランチへ変更を加えることなく新機能の追加バグ(不具合)の修正を行うことができるため、保守や運用がしやすくなるといったメリットがあります。

ブランチとマージのチュートリアル

ここではローカルリポジトリのmasterブランチから新しく別のブランチを作成し、最終的にmerge(マージ: 併合)を行うまでの簡単なチュートリアルを試してみたいと思います。

ブランチやマージなどGitの用語についてはGitで使用される用語についてをご覧ください。

チュートリアル用のリポジトリを作ろう

Gitの基礎を学習しよう!Gitでバージョン管理のチュートリアルを参考にローカルリポジトリを作成してください。

現在のブランチ名とファイルの変更を確認

git statusコマンドを実行して「現在のブランチ名を確認する」こととコミットするもの」があるかどうかの確認をすることができます。


test $ git status
On branch master
nothing to commit, working tree clean
    

masterブランチにはコミットするものがなく作業スペースはキレイな状態です。

もし、ファイルに変更があった場合は以下のように表示されます。


test $ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   demo.txt

no changes added to commit (use "git add" and/or "git commit -a")
    

masterブランチには変更されたステージングされていないファイルがあります。

このようなメッセージが表示された場合は、変更されているファイルをコミットするか、変更を取り消すことができます。

ファイルのコミットについては前回のチュートリアル「Gitの基礎を学習しよう!Gitでバージョン管理」をご覧ください。
また、変更の取り消しについてはGitのバージョン2.23.0以降と以前で使用できるコマンドが異なります。

変更の取り消し(Gitバージョン2.23.0以降)

このバージョンから新しく追加されたgit restore [ファイル]コマンドを使用できます。


test $ git restore demo.txt
    

もしファイルが複数あり、すべてのファイルの変更を取り消す場合は以下のように実行することができます。


test $ git restore .
    

変更の取り消し(Gitバージョン2.23.0以前)

git checkout [ファイル]コマンドを使用します。このコマンドは新しいバージョンでも使用することができます。


test $ git checkout demo.txt
    

すべてのファイルの変更を取り消す場合は以下のように実行することができます。


test $ git checkout .
    

ブランチ一覧を表示する

現在のブランチ一覧を表示してみましょう。
以下のコマンドを実行してください。


test $ git branch
* master
    

アスタリスク(*)は現在のブランチを示し、右のmasterがブランチ名です。
上記の結果は、現在masterブランチを使用していることを示しています。

ブランチを作成する

新しくtutorialブランチを作成して、masterブランチからtutorialブランチに切り替えてみましょう。

ブランチを作成して切り替え(Gitバージョン2.23.0以降)

このバージョンから追加されたgit switch -c [ブランチ名]コマンドを使用すれば、ブランチを作成すると同時にブランチを切り替えることができます。
-cオプションはcreate(作成)を表します。


test $ git switch -c tutorial
Switched to a new branch 'tutorial'
    

ブランチを作成して切り替え(Gitバージョン2.23.0以前)

次のコマンドでブランチを作成します。


test $ git branch tutorial
    

新しく作成したtutorialブランチに切り替えるために次のコマンドを実行します。


test $ git checkout tutorial
Switched to branch 'tutorial'
    

現在のブランチを確認する

tutorialブランチを作成して切り替えを行ったので、もう一度ブランチ一覧を表示してみましょう。


test $ git branch
  master
* tutorial
    

tutorialブランチに切り替わっていることが確認できたら成功です。

この後のコミットからtutorialブランチにバージョンが追加されていきます。

ブランチをマージする

Gitのマージとは、あるブランチと別のブランチを併合して差分をなくすことを言います。
別のブランチで作成していた機能が完成してmasterブランチに反映させる時などに使用します。

ここでは、前回のチュートリアルで作成したdemo.txtを更新し元のmasterブランチとマージを行います。

ファイルを更新する

まず、前回のチュートリアルでしたようにdemo.txt内に新しく「こんばんは」を追加してください。


test $ vi demo.txt
    

コミットする

ファイルが更新されたので、コミットを行います。-aオプションを使用することでステージングの追加を省略し変更のあったすべてのファイルをコミットすることができます


test $ git commit -a -m "新しいブランチで初めてのコミットです。"
[tutorial ec93957] 新しいブランチで初めてのコミットです。
 1 file changed, 1 insertion(+)
    

ブランチを切り替える

tutorialブランチをmasterブランチにマージする場合の操作はmasterブランチから実行します。
そのため現在使用しているtutorialブランチからmasterブランチに切り替えましょう。

ブランチを切り替え(Gitバージョン2.23.0以降)

git switch [ブランチ名]コマンドを使用して切り替えます。


test $ git switch master
Switched to branch 'master'
    

ブランチを切り替え(Gitバージョン2.23.0以前)

git checkout [ブランチ名]コマンドを使用して切り替えます。


test $ git checkout master
Switched to branch 'master'
    

マージする

git merge [マージするブランチ名]コマンドを実行して併合します。


test $ git merge tutorial
Updating 3b57de7..ec93957
Fast-forward
 demo.txt | 1 +
 1 file changed, 1 insertion(+)
    

これでマージが完了しました。

git logコマンドを実行して履歴を確認してみましょう。


test $ git log
commit ec939572393d10193b4f9ab0bc755058a672bc32 (HEAD -> master, tutorial)
Author: Hanako Yamada <h.yamada@prograbi.com>
Date:   Wed Dec 9 02:45:45 2020 +0900

    新しいブランチで初めてのコミットです。

...
    

いくつかの履歴は省略していますが、先ほどtutorialブランチでコミットしたバージョンがmasterブランチに併合されていることを確認できます。

ブランチを削除する

マージが完了したtutorialブランチは不要なので削除します。
ブランチの削除は次のように-dオプションを使用し削除するブランチ名を指定します。


$ git branch -d tutorial
Deleted branch tutorial (was ec93957).
    

Gitのチュートリアルを試してみましょう

マージでコンフリクト(衝突)が発生した場合

元のブランチとマージするブランチで同じ箇所を変更していた場合どちらを適用していいか判断できないためコンフリクト(衝突)が発生します

このコンフリクトが発生するとマージを行うことができないため、ファイルに手を加える必要があります。

以下はマージをしようとしてコンフリクトが発生した時の例です。


test $ git merge tutorial
Auto-merging demo.txt
CONFLICT (content): Merge conflict in demo.txt
Automatic merge failed; fix conflicts and then commit the result.
    

demo.txtのマージでコンフリクトが発生しています。
自動マージに失敗しました。コンフリクトを修正し結果をコミットしてください。

どのファイルでコンフリクトが発生しているか調べる

どのファイルでコンフリクトが発生しているかを調べる時は git status コマンドを実行します。


test $ git status
On branch master
You have unmerged paths.
    (fix conflicts and run "git commit")

Unmerged paths:
    (use "git add <file>..." to mark resolution)

    both modified:      demo.txt

no changes added to commit (use "git add" and/or "git commit -a")
    

masterブランチでマージできなかったパス(ファイル)があるため修正してコミットしてください

Unmerged paths: [コンフリクトが解決されていないファイル]

コミットのために追加(ステージング)された変更はありません。(修正したら) git addでステージングしてコミット(git commit)するか、git commit -a でステージング&コミットしてください。

demo.txtがコンフリクトしているファイルであることが確認できます。

コンフリクトを解決する

コンフリクトが発生しているファイルを開いて修正します。

ファイルを開いて以下のように表示されている箇所を探します。


<<<<<<< HEAD:demo.txt
Hello
=======
おはよう
>>>>>>> tutorial:demo.txt
    

======= より上がマージする前のmasterブランチで、下がマージするtutorialブランチのコードです。

どちらの内容を反映させるかを手動で修正します。

tutorialブランチのコードを反映させる場合は <<<<<<< から >>>>>>>までのコードを以下のように変更します。


おはよう
    

ステージングに追加する

修正後はgit add でステージングし、コンフリクトを解決したことをGitに通知します


$ git add demo.txt
    

コンフリクトが解決しているか確認する

ステージング後にもう一度 git statusを実行して、コンフリクトが解決しているかどうかを確認します。


$ git status
On branch master
All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

Changes to be committed:

    modified:   demo.txt
    

masterブランチのコンフリクトは修正されました。しかしまだマージしていません。(git commitを使用してマージを成立させます。)

コミットする

修正したコンフリクトのすべてがステージングされていることを確認したら、git commit を実行してマージを完了します。


$ git commit -m "tutorialブランチをマージしました。"
    

コンフリクトを再現してマージを完了させてみましょう

  1. masterブランチから新しくtutorialブランチを作成してください。
  2. masterおよびtutorial両方のdemo.txtファイルの同一箇所を変更し、それぞれコミットします。
  3. masterブランチでtutorialブランチをマージしするように試みてください。
  4. コンフリクトが発生しましたか?コンフリクトが発生した場合を試してマージを完了させてください!

Twitterでアウトプット

理解したことや分からないところはTwitterでつぶやいてみよう!

この学習ページで学んだことをTwitterでアウトプットしてください。

アウトプットするメリット

学習仲間が増える

同じ課題を持った仲間が増えるため、学習へのモチベーションが継続しやすくなります。

より深く理解する

頭では理解したと思っていても、文章化することで初めて気づくことがあります。