ブランチを Git のマスターにマージする

Sharad Dixit 2023年1月30日
  1. 前提条件
  2. Git でマージする準備
  3. Git の merge メソッドを使用してブランチをマスターにマージする
  4. rebase メソッドを使用してブランチをマスターにマージする
  5. まとめ
ブランチを Git のマスターにマージする

git の最も強力な機能の 1つは、ブランチの作成とマージ操作です。Git を使用すると、ユーザーは新しいブランチを作成して、開発コードにマージできます。この機能は、より具体的で、より小さく、よりきめ細かいタスクを奨励することにより、複数のプロジェクトの開発プロセスワークフローを改善します。

このチュートリアル記事では、git の feature ブランチをマスターにマージするためのさまざまなアプローチについて説明します。

git の主な利点は、その分岐システムです。GIT のすべての魔法がかかっているのはこれらのブランチです!マスターブランチは、行われたすべての変更を実行します。したがって、目標は、このブランチに直接変更を加えるのではなく、他のブランチに変更を加え、さまざまなテストを行った後、マスターブランチに統合することです。

簡単にするためのチュートリアルでは、master ブランチと feature-1 として知られる機能ブランチの 2つのブランチがあると考えてみましょう。メインブランチは本番コードを含むマスターブランチであり、2 番目のブランチは変更が実行される場所または新しい機能が実装される場所です。最終的に、機能またはバグが承認されると、マスターにマージされます。

Initial_Repository

実際の例を使用して、2つのブランチのマージのデモンストレーションを開始しましょう。まず、以下が必要です。

前提条件

GitHub にリポジトリを作成する

Github で紹介されているように、初期リポジトリを作成できます。

次に、リポジトリページの[ファイルの追加]ボタンを使用して、マスターブランチに 2つのファイルを追加します。ファイル名は以下のとおりです。

  • file1.txt
  • file2.txt

この例では、次のテキストコンテンツがそれぞれ file1.txtfile2.txt に追加されています。

$ cat file1.txt
This is dummy text line 1
This is dummy text line 2
$ cat file2.txt
This is dummy test in 2nd file

クローンリポジトリ

次に、新しく作成したリポジトリを GitHub からシステムに複製して、コードのローカルコピーを作成します。クローン URL は、以下のようにコードボタンから取得できます。

Clone_Repository

次のコマンドを使用してクローンを作成します。

$ git clone git@github.com:project/demorepo.git

正常に複製されたら、次のコマンドを使用して、マスターブランチファイルの内容を表示および確認します。

$ cat file1.txt
This is dummy text line 1
This is dummy text line 2
$ cat file2.txt
This is dummy test in 2nd file

フィーチャーブランチの作成

$ git branch feature-1

このコマンドは新しいブランチを作成し、git で新しいコミットを作成しません。

チェックアウト機能ブランチ

以前は、git branch feature-1 を使用して新しいブランチを作成しました。ただし、アクティブなブランチは master ブランチです。新しいブランチをアクティブにするには、ターミナルで次のコマンドを使用します。

$ git checkout feature-1
Switched to branch 'feature-1'

上記のコマンドは、アクティブなブランチを master から feature-1 に切り替えます。これで、このブランチは個別に開発する準備が整いました。

機能ブランチのファイルを変更する

feature-1 ブランチにいくつかのコミットを追加するか、新しい行を追加します。この場合、file2.txt はローカルで変更され、後でマスターブランチにマージされます。

これまでの変更については、コミット図は次のようになります。A と E はどちらも、masterfeature-1 のブランチ状態を表します。現在、コミット AE は、チェックアウト中にファイルが変更されないのと同じです。

A  ← master
   \
     E  ← feature-1

現在、file1.txt が新しいテキストで更新されています。このコマンドを使用して、コンテンツを更新します。

$ echo "file update in feature branch" > file1.txt

現在、file2.txt には以下の内容が含まれています。

$ cat file2.txt
This is dummy test in 2nd file

file1.txt の古いコンテンツと新しいコンテンツの違いは、以下のコマンドを使用して確認できます。

$ git diff
diff --git a/file1.txt b/file1.txt
index 11d66d4..48c9378 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1,2 +1 @@
-This is dummy text line 1
-This is dummy text line 2
+file update in feature branch

次に、このファイルをステージングし、以下のコマンドを使用してローカルコミットを作成します。

$ git add file1.txt
$ git commit -am "update file via feature-1"
[feature-1 22b60b8] update file via feature-1
 1 file changed, 1 insertion(+), 2 d

コミットツリーの現在のスナップショットは次のようになります。ここで、F は前のステップで作成された新しいコミットです。

A  ← master
  \
    E --- F ← feature-1

実際の例を示すために、リモートの master も他の開発者によって同時に変更され、これらの変更はコミット C およびコミット D としてマスターにプッシュされます。

A --- B --- C --- D ← master
   \
      E --- F ← feature-1

以下は、マスターブランチの Github リポジトリにある file1.txt の更新されたコンテンツです。2 行目が更新され、3 行目と 4 行目が新しく作成されていることに注意してください。

File1_Content

これは、以下のコマンドを使用してコマンドシェルでブランチ履歴をリアルタイムで視覚化することにより、ローカルで検証することもできます。

$ git fetch
$ git log --all --decorate --oneline --graph

Commit_Graph

Git でマージする準備

Git を使用すると、機能ブランチの変更をリモートの master ブランチとマージする 2つの可能性があります。

  1. merge メソッド
    Git merge は、変更を別のブランチにコミットするコマンドです。これにより、開発者は機能ブランチから独立したコード行を取得し、git マージツールを介してマスター上の単一のブランチに統合できます。

  2. rebase メソッド
    Git rebase は、それが非常に異なることを除いて、本質的に同じ目的で使用されるさらに別のコマンドです。

両方の方法を詳細に理解しましょう:

Git の merge メソッドを使用してブランチをマスターにマージする

merge は、feature ブランチと master ブランチを、関連するすべてのブランチのコンテンツを保持するコミットに統合することを目的としています。Git は、これを merge commit と呼ばれる方法で実現します。これは、merge が複数のブランチを操作することも意味します。

ブランチが分岐した場合、つまり、一方が他方の祖先ではない場合。Git は、複数の親を持つ新しい追加のコミットを行うことでマージを実現できます。次の図では、異なるブランチにコミット D とコミット F があり、ブランチを(git merge を介して)混合すると、結果は、親が BE であるコミット G になります。

A --- B --- C --- D ---	
  \				         \  
    \					  G  ← master
      E --- F --------- /	

上の図では、G は新しく作成されたコミットであり、完全に git によって作成されています。このコミットには 2 人の親がいます!そして彼らには命令があります:

  • 最初の親は D で、以前は master でした。
  • 2 番目の親は F で、以前は feature-1 でした。

このタイプのコミットは、マージコミットと呼ばれます。

次に、リポジトリの例に戻り、新しく作成された feature-1 ブランチを master にマージします。

まず、マスターブランチをチェックしてください。

$ git checkout master

次に、リモートマスターの変更をローカルの master にプルします。

$ git pull origin master

From github.com:repo/demorepo

 * branch            master     -> FETCH_HEAD
   Updating 17cc6b4..a802b6b
   Fast-forward
    file1.txt | 5 ++++-
    1 file changed, 4 insertions(+), 1 deletion(-)

その後、以下のコマンドを使用して、機能ブランチ、つまり feature-1 を現在アクティブなブランチにマージします。

$ git merge feature-1

このステップが正常に完了すると、feature-1 ブランチは master ブランチと完全にマージされます。ただし、git がこれらのマージの競合を自動的に解決できない場合、マージの競合エラーで失敗します。

これは非常に典型的なシナリオです。2つのブランチがファイルの同じ部分を変更し、git がどちらの部分を使用するかを解決できない場合に発生する可能性があります。それはまさに私たちの例で起こることです。このケースは、git を介して以下に示されています。

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

git で競合が発生するたびに、<<<<<<<======= が追加され、競合の原因となったセクションが強調表示されます。これは手動で解決する必要があります。

File1_MergeConflict

ファイルの最終マスターバージョンに保持する部分が決定したら、個人は無関係なコード(競合インジケーターを含む)を削除する必要があります。最終的に、以下のように変更をリモートブランチにプッシュします。

$ git add .
$ git commit -am "resolving the mergeconflict"
[master 1acce69] resolving the mergeconflict
$ git push

このようにして、feature-1 ブランチはリモートの master に正常にマージされます。

次に、以下のコマンドでブランチ履歴を再度確認します。

git log --all --decorate --oneline --graph

Merge_Graph

git merge が commit-id を 1acce69 として Merge Commit を作成し、feature-1 ブランチを origin/master とマージしたことを確認できます。

rebase メソッドを使用してブランチをマスターにマージする

もう一度、機能ブランチとマスターブランチが同期しておらず、マージする必要がある状況を考えてみましょう。以前にこの状況を示した図も思い出してみましょう。

A --- B --- C --- D ← master
   \
      E --- F ← feature-1

マージする別の方法として、リベースオプションを使用してブランチ feature-1 をブランチ master にマージできます。rebase は、機能ブランチからのコミットをマスターブランチの前に置くだけで、関連するブランチを統合します。

これは、以下のコマンドを介して実現されます。

git checkout master
git pull
git checkout feature-1
git rebase master

リベースを実行すると、次のような図になります。

A --- B --- C --- D----(operation rebase)----- E--------F   ← master

上の図から、rebase が行う優れた点は、線形でクリーンで読みやすいコミット履歴を生成することであることがわかります。マージすることにより、追加の奇妙なマージコミットも生成されません。

このアプローチの欠点は、リベースによって、これらのブランチのコミット履歴の書き換えを含む、関連するブランチの構造全体が変更されることです。rebasemerge commit を作成しないため、rebase はプロセスの最後に線形ブランチを生成するため、2つのブランチがマージされたときのトレーサビリティは得られません。

まとめ

どちらのコマンドも非常に便利です。ただし、さまざまな状況で、それぞれの側に次のような利点があります。

Git rebase

  • 複雑な履歴を合理化します。
  • 忙しいブランチを持つリポジトリでコミットノイズをマージすることは避けてください。
  • 履歴が保存されないため、適切に使用しないと危険です。

Git merge

  • 使いやすい。
  • 毎回追加のマージコミットが作成されるため、コミット履歴が混乱して汚いように見えます。
  • 完全な履歴と時系列を保持します。

関連記事 - Git Merge