gitコマンドの使い方 ~ git merge ~

2020年4月5日git-command

git merge コマンド概要

git merge コマンドはcheckout中のブランチに対して、指定したブランチの内容を取り込み新しいcommitを作成します。

以下は、masterブランチにdevelopブランチのcommit(B)とcommit(D)の変更内容を取り込んで新しいcommit(E)を作成するイメージです。

git merge コマンドの使い方

git merge [branch | remote-tracking-branch]

取り込み対象に指定するブランチは通常のbrachもしくはremote-trachking-branchを指定することができます。

ポイント

branch-Aにbranch-Bの内容を取り込みたい場合は、branch-Aでgit mergeコマンドを実行する必要があります。

具体的なコマンド例で操作の流れを確認しましょう。

masterブランチにdevelopブランチの変更内容を取り込む

以下の内容を実際のgitコマンドで操作しました。

(master)
$ echo 'aaa' > file-A.txt

(master)
$ git add .

(master)
$ git commit -m 'commit-A'
[master (root-commit) e708da0] commit-A
 1 file changed, 1 insertion(+)
 create mode 100644 file-A.txt

(master)
$ git checkout -b develop
Switched to a new branch 'develop'

(develop)
$ echo 'bbb' > file-B.txt

(develop)
$ git add .

(develop)
$ git commit -m 'commit-B'
[develop 56ed527] commit-B
 1 file changed, 1 insertion(+)
 create mode 100644 file-B.txt

(develop)
$ echo 'ddd' > file-D.txt

(develop)
$ git add .

(develop)
$ git commit -m 'commit-D'
[develop 97fc8ae] commit-D
 1 file changed, 1 insertion(+)
 create mode 100644 file-D.txt

(develop)
$ git checkout master
Switched to branch 'master'

(master)
$ echo 'ccc' > file-C.txt

(master)
$ git add .

(master)
$ git commit -m 'commit-C'
[master f04350f] commit-C
 1 file changed, 1 insertion(+)
 create mode 100644 file-C.txt

(master)
$ git merge develop
Merge made by the 'recursive' strategy.
 file-B.txt | 1 +
 file-D.txt | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 file-B.txt
 create mode 100644 file-D.txt

(master)
$ git log --oneline --all --graph
*   7acc226 (HEAD -> master) Merge branch 'develop'
|\
| * 97fc8ae (develop) commit-D
| * 56ed527 commit-B
* | f04350f commit-C
|/
* e708da0 commit-A

(master)
$ ll
total 4
-rw-r--r-- 1 snow 197609 4  4月  5 16:27 file-A.txt
-rw-r--r-- 1 snow 197609 5  4月  5 16:30 file-B.txt
-rw-r--r-- 1 snow 197609 4  4月  5 16:29 file-C.txt
-rw-r--r-- 1 snow 197609 5  4月  5 16:30 file-D.txt

(master)
$ git ls-files
file-A.txt
file-B.txt
file-C.txt
file-D.txt

conflict(コンクリフト)の解決方法

以下の内容を例に実際のgitコマンドで操作してみました。

masterブランチとdevelopブランチでfile-B.txtの同じ行を変更した場合

$ git chekcout master

(master)
$ echo 'bbb master upd' > file-B.txt

(master)
$ cat file-B.txt
bbb master upd

(master)
$ git commit -am 'conflict test master'
[master bd71826] conflict test master
 1 file changed, 1 insertion(+), 1 deletion(-)

(master)
$ git checkout develop
Switched to branch 'develop'

(develop)
$ echo 'bbb develop upd' > file-B.txt

(develop)
$ cat file-B.txt
bbb develop upd

(develop)
$ git commit -am 'conflict test develop'
[develop d089509] conflict test develop
 1 file changed, 1 insertion(+), 1 deletion(-)

(develop)
$ git checkout master
Switched to branch 'master'

(master)
$ git log --oneline --all
d089509 (develop) conflict test develop
bd71826 (HEAD -> master) conflict test master

(master)
$ git merge develop
Auto-merging file-B.txt
CONFLICT (content): Merge conflict in file-B.txt
Automatic merge failed; fix conflicts and then commit the result.

(master)
$ cat file-B.txt
<<<<<<< HEAD
bbb master upd
=======
bbb develop upd
>>>>>>> develop

// develop側を採用
// Visual Studio Codeなどで編集すると視覚的でわかりやすい
// 今回はdevelop側の修正を採用しファイルの状態を以下の内容にする
bbb develop upd

// コンクリフト解消したファイルをステージング
(master)
$ git add file-B.txt

// コンクリフト解消後のcommit作成
(master)
$ git commit -m 'no conflict'

ポイントを整理すると

git mergeコマンドでconflict(コンフリクト)が発生すると以下のようなメッセージが表示されます。

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

 

conflict(コンフリクト)が発生したファイルの内容は以下のようになっています。

上側がHEADつまり操作中のブランチなのでmasterの内容になります。

下側がdevelopブランチの内容になります。

何かのエディタ(VimでもVS Codeでも何でもOK)で修正します。

<<<<<<< HEAD
bbb master upd
=======
bbb develop upd
>>>>>>> develop

fast-forwardマージ

git mergeやgit push、git rebaseを実行する場合にfast-forwardマージについて覚えておくことでより理解が深まります。

fast-forwardマージとは、分岐元のブランチからconflict(コンフリクト)が発生する可能性のないマージで、マージ元のbranch(ブランチ)の HEAD をマージするブランチの最新のcommitに移動させるマージを指します。

図で示すと以下のような場合にgit mergeするとfast-forwardマージになります。

ポイントは、commit(B)の後にmasterブランチで変更がないことです。

masterとHEADの示すcommitの位置が変更しているだけになりますね。

 

実際にgitコマンドで確認するとこのようになります。

(master)
$ echo 'aaa' > file-A.txt

(master)
$ git add .

(master)
$ git commit -m 'commit-A'
[master (root-commit) 2959319] commit-A
 1 file changed, 1 insertion(+)
 create mode 100644 file-A.txt

(master)
$ echo 'bbb' > file-B.txt

(master)
$ git add .

(master)
$ git commit -m 'commit-B'
[master db4b456] commit-B
 1 file changed, 1 insertion(+)
 create mode 100644 file-B.txt

(master)
$ git checkout -b develop
Switched to a new branch 'develop'

(develop)
$ echo 'ccc' > file-C.txt

(develop)
$ git add .

(develop)
$ git commit -m 'commit-C'
[develop aa6cae4] commit-C
 1 file changed, 1 insertion(+)
 create mode 100644 file-C.txt

(develop)
$ echo 'ddd' > file-D.txt

(develop)
$ git add .

(develop)
$ git commit -m 'commit-D'
[develop 78b8fb7] commit-D
 1 file changed, 1 insertion(+)
 create mode 100644 file-D.txt

(develop)
$ git checkout master
Switched to branch 'master'

(master)
$ git log --oneline --all --graph
* 78b8fb7 (develop) commit-D
* aa6cae4 commit-C
* db4b456 (HEAD -> master) commit-B
* 2959319 commit-A

(master)
$ git merge develop
Updating db4b456..78b8fb7
Fast-forward
 file-C.txt | 1 +
 file-D.txt | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 file-C.txt
 create mode 100644 file-D.txt

(master)
$ git log --oneline --all --graph
* 78b8fb7 (HEAD -> master, develop) commit-D
* aa6cae4 commit-C
* db4b456 commit-B
* 2959319 commit-A

git mergeコマンドの実行結果に「Fast-forward」と表示されていますね。

git merge の全てのオプションを確認する方法

以下のコマンドを実行するとブラウザでgit mergeのヘルプページが表示される

git merge --help

Gitコマンドの使い方一覧

git-command

Posted by snow