ブランチを Git のマスターにマージする
git の最も強力な機能の 1つは、ブランチの作成とマージ操作です。Git を使用すると、ユーザーは新しいブランチを作成して、開発コードにマージできます。この機能は、より具体的で、より小さく、よりきめ細かいタスクを奨励することにより、複数のプロジェクトの開発プロセスワークフローを改善します。
このチュートリアル記事では、git の feature ブランチをマスターにマージするためのさまざまなアプローチについて説明します。
git の主な利点は、その分岐システムです。GIT のすべての魔法がかかっているのはこれらのブランチです!マスターブランチは、行われたすべての変更を実行します。したがって、目標は、このブランチに直接変更を加えるのではなく、他のブランチに変更を加え、さまざまなテストを行った後、マスターブランチに統合することです。
簡単にするためのチュートリアルでは、master
ブランチと feature-1
として知られる機能ブランチの 2つのブランチがあると考えてみましょう。メインブランチは本番コードを含むマスターブランチであり、2 番目のブランチは変更が実行される場所または新しい機能が実装される場所です。最終的に、機能またはバグが承認されると、マスターにマージされます。
実際の例を使用して、2つのブランチのマージのデモンストレーションを開始しましょう。まず、以下が必要です。
前提条件
GitHub にリポジトリを作成する
Github で紹介されているように、初期リポジトリを作成できます。
次に、リポジトリページの[ファイルの追加]ボタンを使用して、マスターブランチに 2つのファイルを追加します。ファイル名は以下のとおりです。
file1.txt
file2.txt
この例では、次のテキストコンテンツがそれぞれ file1.txt
と file2.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 は、以下のようにコード
ボタンから取得できます。
次のコマンドを使用してクローンを作成します。
$ 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 はどちらも、master
と feature-1
のブランチ状態を表します。現在、コミット A
と E
は、チェックアウト中にファイルが変更されないのと同じです。
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 行目が新しく作成されていることに注意してください。
これは、以下のコマンドを使用してコマンドシェルでブランチ履歴をリアルタイムで視覚化することにより、ローカルで検証することもできます。
$ git fetch
$ git log --all --decorate --oneline --graph
Git でマージする準備
Git を使用すると、機能ブランチの変更をリモートの master
ブランチとマージする 2つの可能性があります。
-
merge
メソッド
Gitmerge
は、変更を別のブランチにコミットするコマンドです。これにより、開発者は機能ブランチから独立したコード行を取得し、git マージツールを介してマスター上の単一のブランチに統合できます。 -
rebase
メソッド
Gitrebase
は、それが非常に異なることを除いて、本質的に同じ目的で使用されるさらに別のコマンドです。
両方の方法を詳細に理解しましょう:
Git の merge
メソッドを使用してブランチをマスターにマージする
merge
は、feature
ブランチと master
ブランチを、関連するすべてのブランチのコンテンツを保持するコミットに統合することを目的としています。Git は、これを merge commit
と呼ばれる方法で実現します。これは、merge
が複数のブランチを操作することも意味します。
ブランチが分岐した場合、つまり、一方が他方の祖先ではない場合。Git は、複数の親を持つ新しい追加のコミットを行うことでマージを実現できます。次の図では、異なるブランチにコミット D
とコミット F
があり、ブランチを(git merge
を介して)混合すると、結果は、親が B
と E であるコミット
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 で競合が発生するたびに、<<<<<<<
と =======
が追加され、競合の原因となったセクションが強調表示されます。これは手動で解決する必要があります。
ファイルの最終マスターバージョンに保持する部分が決定したら、個人は無関係なコード(競合インジケーターを含む)を削除する必要があります。最終的に、以下のように変更をリモートブランチにプッシュします。
$ git add .
$ git commit -am "resolving the mergeconflict"
[master 1acce69] resolving the mergeconflict
$ git push
このようにして、feature-1
ブランチはリモートの master
に正常にマージされます。
次に、以下のコマンドでブランチ履歴を再度確認します。
git log --all --decorate --oneline --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
が行う優れた点は、線形でクリーンで読みやすいコミット履歴を生成することであることがわかります。マージすることにより、追加の奇妙なマージコミット
も生成されません。
このアプローチの欠点は、リベースによって、これらのブランチのコミット履歴の書き換えを含む、関連するブランチの構造全体が変更されることです。rebase
は merge commit
を作成しないため、rebase はプロセスの最後に線形ブランチを生成するため、2つのブランチがマージされたときのトレーサビリティは得られません。
まとめ
どちらのコマンドも非常に便利です。ただし、さまざまな状況で、それぞれの側に次のような利点があります。
Git rebase
- 複雑な履歴を合理化します。
- 忙しいブランチを持つリポジトリでコミットノイズをマージすることは避けてください。
- 履歴が保存されないため、適切に使用しないと危険です。
Git merge
- 使いやすい。
- 毎回追加のマージコミットが作成されるため、コミット履歴が混乱して汚いように見えます。
- 完全な履歴と時系列を保持します。