情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

Gitのブランチを使用する

ブランチとは

ブランチとはバージョンの分岐のことです。

分岐を行うと(ブランチを作成すると)リポジトリにおいて複数の作業を同時並行的に進めることができます。

リポジトリを最初に作成した時点ではリポジトリには1つもブランチは存在しません。

そして、リポジトリに最初のコミットを行うと、masterという名称のブランチが自動的に作成され、このブランチにコミットが行われます。

masterブランチはリポジトリにおけるデフォルトのブランチであり、何もしないでコミットを行った場合にはこのブランチにコミットが行われます。

ブランチ一覧の表示

リポジトリのブランチ一覧を表示するにはリポジトリのフォルダにおいてgit branchコマンドを実行します。

ブランチの作成

リポジトリにブランチを作成するにはリポジトリのフォルダにおいてgit branchコマンドを実行します。

第1引数にブランチの名称を指定します。

実演

まず、リポジトリを作成します。

C:\work\git\project1git initコマンドを実行します。

C:\work\git\project1>git init
Initialized empty Git repository in C:/work/git/project1/.git/

git branchコマンドを実行してブランチ一覧を表示してみます。

C:\work\git\project1>git branch

何も表示されません。つまり、リポジトリにはまだ1つもブランチが存在しません。

次に、コミットを試してみます。

textfile.txtという名称のテキストファイルを作成します。

C:\work\git\project1>echo this is text file. > textfile.txt

git addコマンドを実行してtextfile.txtをコミット対象に追加します。

C:\work\git\project1>git add textfile.txt

git commitコマンドを実行してコミットを行います。

C:\work\git\project1>git commit --message "one text file create."
[master (root-commit) 5b2fd0d] one text file create.
 1 file changed, 1 insertion(+)
 create mode 100644 textfile.txt

git logコマンドを実行してコミット履歴をチェックしてみます。コミットが行われていることが分かります。

C:\work\git\project1>git log
commit 5b2fd0d7fdbba2a0325301643b6eaafde8d0431d
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 16:12:36 2016 +0900

    one text file create.

git branchコマンドを実行してブランチ一覧を表示してみます。

C:\work\git\project1>git branch
* master

リポジトリへの最初のコミットにより、masterという名称のブランチが自動的に作成されたことが分かります。

次に、git branchコマンドを実行してfeature1という名称のブランチを作成してみます。

C:\work\git\project1>git branch feature1

git branchコマンドを実行してブランチ一覧を表示してみます。

C:\work\git\project1>git branch
  feature1
* master

feature1という名称のブランチが作成されていることが分かります。

また、現在のブランチ(コミットが行われるブランチ)には*で印が付けられます。

別のブランチへの移動

別のブランチに移動する、すなわち、コミットが行われるブランチを変更するにはリポジトリのフォルダにおいてgit checkoutコマンドを実行します。

第1引数にブランチの名称を指定します。

別のブランチに移動する際に元のブランチにコミットされていない変更がある場合にはその変更は消去されますので注意してください。

ブランチ間の差分の表示

ブランチ間の差分を表示するにはリポジトリのフォルダにおいてgit diffコマンドを実行します。

第1引数に差分を表示したい2つのブランチの名称を..で繋げたものを指定します。

ブランチ間のコミットの差分の表示

ブランチ間のコミットの差分を表示するにはリポジトリのフォルダにおいてgit logコマンドかgit shortlogコマンドを実行します。

第1引数に差分を表示したい2つのブランチの名称を..で繋げたものを指定します。

実演

上で作成したリポジトリのfeature1ブランチにコミットを行い、masterブランチとの間の差分を表示してみます。

まず、git checkoutコマンドを実行してfeature1ブランチに移動します。

C:\work\git\project1>git checkout feature1
Switched to branch 'feature1'

git branchコマンドを実行してブランチ一覧を表示してみるとfeature1ブランチに移動していることが分かります。

C:\work\git\project1>git branch
* feature1
  master

次に、コミットを行うためにリポジトリのファイルを変更してみます。

textfile.txtの内容を変更してみます。

C:\work\git\project1>echo this is modified text file. > textfile.txt

textfile2.txtを作成してみます。

C:\work\git\project1>echo this is new text file > textfile2.txt

git statusコマンドを実行してリポジトリの状態をチェックしてみるとファイルの変更や新規作成が認識されていることが分かります。

C:\work\git\project1>git status
On branch feature1
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   textfile.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        textfile2.txt

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

git addコマンドを実行してコミット対象を追加します。

C:\work\git\project1>git add .

git statusコマンドを実行してリポジトリの状態をチェックしてみるとコミット対象が追加されていることが分かります。

C:\work\git\project1>git status
On branch feature1
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   textfile.txt
        new file:   textfile2.txt

git commitコマンドを実行してコミットを行います。

C:\work\git\project1>git commit --message "commit from feature1 branch."
[feature1 3741f86] commit from feature1 branch.
 2 files changed, 2 insertions(+), 1 deletion(-)
 create mode 100644 textfile2.txt

git logコマンドを実行してコミット履歴をチェックしてみるとコミットが行われていることが分かります。

C:\work\git\project1>git log
commit 3741f86328e4a2ad36b52b230c1bbf4c72d27230
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 16:56:57 2016 +0900

    commit from feature1 branch.

commit 5b2fd0d7fdbba2a0325301643b6eaafde8d0431d
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 16:12:36 2016 +0900

    one text file create.

git diffコマンドを実行してmasterブランチとfeature1ブランチとの間の差分を表示してみます。

C:\work\git\project1>git diff master..feature1
diff --git a/textfile.txt b/textfile.txt
index a2dfe55..650b758 100644
--- a/textfile.txt
+++ b/textfile.txt
@@ -1 +1 @@
-this is text file.
+this is modified text file.
diff --git a/textfile2.txt b/textfile2.txt
new file mode 100644
index 0000000..c03d607
--- /dev/null
+++ b/textfile2.txt
@@ -0,0 +1 @@
+this is new text file

git logコマンドを実行してmasterブランチとfeature1ブランチとの間のコミットの差分を表示してみます。

C:\work\git\project1>git log master..feature1
commit 3741f86328e4a2ad36b52b230c1bbf4c72d27230
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 16:56:57 2016 +0900

    commit from feature1 branch.

ブランチのマージ

ブランチを統合することをマージと言います。

ブランチをマージするにはリポジトリのフォルダにおいて分岐元のブランチに移動した状態でgit mergeコマンドを実行します。

第1引数に分岐先のブランチの名称を指定します。

実演

上で作成したリポジトリのmasterブランチ(分岐元のブランチ)とfeature1ブランチ(分岐先のブランチ)をマージしてみます。

まず、git checkoutコマンドを実行して分岐元のブランチであるmasterブランチに移動します。

C:\work\git\project1>git checkout master
Switched to branch 'master'

git branchコマンドを実行してブランチ一覧を表示してみるとmasterブランチに移動していることが分かります。

C:\work\git\project1>git branch
  feature1
* master

dirコマンドを実行してファイルやフォルダの一覧を表示してみるとtextfile.txtは存在するもののtextfile2.txtは存在しないことが分かります。

C:\work\git\project1>dir
 Volume in drive C is TI31035600A
 Volume Serial Number is 1CBD-3C48

 Directory of C:\work\git\project1

2016/09/12  17:06    <DIR>          .
2016/09/12  17:06    <DIR>          ..
2016/09/12  17:06                21 textfile.txt
               1 File(s)             21 bytes
               2 Dir(s)  31,909,552,128 bytes free

また、typeコマンドを実行してtextfile.txtの内容を表示してみると下のようになっています。

C:\work\git\project1>type textfile.txt
this is text file.

git margeコマンドを実行してmasterブランチとfeature1ブランチをマージしてみます。

C:\work\git\project1>git merge feature1
Updating 5b2fd0d..3741f86
Fast-forward
 textfile.txt  | 2 +-
 textfile2.txt | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)
 create mode 100644 textfile2.txt

dirコマンドを実行してファイルやフォルダの一覧を表示してみるとtextfile.txttextfile2.txtの両方が存在していることが分かります。

C:\work\git\project1>dir
 Volume in drive C is TI31035600A
 Volume Serial Number is 1CBD-3C48

 Directory of C:\work\git\project1

2016/09/12  17:11    <DIR>          .
2016/09/12  17:11    <DIR>          ..
2016/09/12  17:11                30 textfile.txt
2016/09/12  17:11                24 textfile2.txt
               2 File(s)             54 bytes
               2 Dir(s)  31,909,523,456 bytes free

また、typeコマンドを実行してtextfile.txttextfile2.txtの内容を表示してみると下のようになっています。feature1ブランチがmasterブランチに正しくマージされていることが分かります。

C:\work\git\project1>type textfile.txt
this is modified text file.

C:\work\git\project1>type textfile2.txt
this is new text file

競合の解決

ブランチをマージした際には競合(2つのブランチの内容が自動的に統合できない状態)が発生することがあります。具体的には下のような場合に競合が発生します。

  • 両方のブランチで同じファイルの同じ部分が別々の内容に変更された。
  • 一方のブランチでファイルが変更され、他方のブランチで同じファイルが削除された。

前者の場合には競合が発生したファイルの競合が発生した部分が<<<<<<<>>>>>>>で囲まれ、両方のブランチにおける内容が=======で区切られて格納されます。

このような場合には競合が発生したファイルを手動で正しい内容に変更し、git addコマンドとgit commitコマンドを使用してコミットを行います。

これにより、競合が解決します。

後者の場合には競合が発生したファイルを削除しない場合にはgit addコマンドとgit commitコマンドを使用してコミットを行います。ファイルを削除する場合にはgit rmコマンドとgit commitコマンドを使用してコミットを行います。

これにより、競合が解決します。

実演

上で作成したリポジトリのmasterブランチとfeature1ブランチとの間で競合を発生させ、解決してみます。

まず、git checkoutコマンドを実行してfeature1ブランチに移動します。

C:\work\git\project1>git checkout feature1
Switched to branch 'feature1'

textfile.txtの内容を変更してみます。

C:\work\git\project1>echo this is twice-modified text file. > textfile.txt

textfile2.txtを削除してみます。

C:\work\git\project1>del textfile2.txt

git addコマンドとgit commitコマンドを使用してコミットを行います。

C:\work\git\project1>git add .

C:\work\git\project1>git commit -m "change in feature1"
[feature1 8ac0e6d] change in feature1
 2 files changed, 1 insertion(+), 2 deletions(-)
 delete mode 100644 textfile2.txt

次に、git checkoutコマンドを実行してmasterブランチに移動します。

C:\work\git\project1>git checkout master
Switched to branch 'master'

textfile.txttextfile2.txtの内容を変更してみます。

C:\work\git\project1>echo originally, this is text file. > textfile.txt

C:\work\git\project1>echo this is text file modified in master branch. > textfile2.txt

git addコマンドとgit commitコマンドを使用してコミットを行います。

C:\work\git\project1>git add .

C:\work\git\project1>git commit -m "change in master"
[master 09eead5] change in master
 2 files changed, 2 insertions(+), 2 deletions(-)

次に、git mergeコマンドを実行してmasterブランチとfeature1ブランチのマージを試みます。

C:\work\git\project1>git merge feature1
CONFLICT (modify/delete): textfile2.txt deleted in feature1 and modified in HEAD. Version HEAD of textf
ile2.txt left in tree.
Auto-merging textfile.txt
CONFLICT (content): Merge conflict in textfile.txt
Automatic merge failed; fix conflicts and then commit the result.

競合が発生しました。

git statusコマンドを実行してリポジトリの状態をチェックしてみるとどのファイルでどのような競合が発生しているのかが分かります。textfile.txtは両方のブランチで同じ部分が別々の内容に変更されており、textfile2.txtは一方のブランチで変更され、他方のブランチで削除されています。

C:\work\git\project1>git status
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

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

        both modified:   textfile.txt
        deleted by them: textfile2.txt

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

typeコマンドを実行してtextfile.txtの内容を表示してみると下のようになっています。

C:\work\git\project1>type textfile.txt
<<<<<<< HEAD
originally, this is text file.
=======
this is twice-modified text file.
>>>>>>> feature1

=======の上側がHEADブランチ(この場合はmasterブランチと同じ)の内容となっており、下側がfeature1ブランチの内容となっています。

手動で競合の解決を行います。

C:\work\git\project1>echo this is text file modified twice in feature1 branch. > textfile.txt

また、textfile2.txtは削除しないことにしましょう(feature1ブランチでの削除をなかったことにしましょう)。

その場合、特に何もする必要はありません。

git addコマンドとgit commitコマンドを使用して競合を解決した結果のコミットを行います。

C:\work\git\project1>git add .

C:\work\git\project1>git commit -m "resolve conflict."
[master bfa1786] resolve conflict.

git statusコマンドを実行してリポジトリの状態をチェックしてみると競合が解決されたことが分かります。

C:\work\git\project1>git status
On branch master
nothing to commit, working tree clean

なお、コミット履歴は下のようになっています。

C:\work\git\project1>git log
commit bfa178625a8b15a7c7a3c95254e54577722b2f49
Merge: 09eead5 8ac0e6d
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 18:06:02 2016 +0900

    resolve conflict.

commit 09eead50dae3a5af26ad944cb02fb1ebeb58220a
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 17:53:26 2016 +0900

    change in master

commit 8ac0e6d43dc42a9b51c259422f7d13c3d975c109
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 17:49:57 2016 +0900

    change in feature1

commit 3741f86328e4a2ad36b52b230c1bbf4c72d27230
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 16:56:57 2016 +0900

    commit from feature1 branch.

commit 5b2fd0d7fdbba2a0325301643b6eaafde8d0431d
Author: pizyumi <aih@hotmail.com>
Date:   Mon Sep 12 16:12:36 2016 +0900

    one text file create.

また、textfile.txttextfile2.txtの内容は下のようになっています。

C:\work\git\project1>type textfile.txt
this is text file modified twice in feature1 branch.

C:\work\git\project1>type textfile2.txt
this is text file modified in master branch.
pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-Git