神戸学院大学 経営学部 林坂ゼミ

Git 入門トップページ

« 戻る 次へ »

Git によるバージョン管理入門

ブランチ操作

システム開発の規模が大きくなるとブランチ操作は必須になるでしょう.例えば,新たな機能を開発するときにはそのトピックブランチを作成して,そのブランチ上でソースコードを編集します.新たな機能が動作する事が確認できたら標準ブランチに戻って,変更点を標準ブランチに反映させます.

また大きな規模のシステムはチームで開発するので,チーム開発を効率的に進めるためのブランチ運用ルールがあります.代表的なものが Git-flowGitHub Flow です.

なお,このページで使用されているほとんどのコマンドは Windows と Mac/Linux で共通です.例外は Windows の type コマンドが Mac/Linux では cat になるだけです.

目次に戻る

ブランチの一覧表示

ブランチの一覧を表示するコマンドです.標準のブランチは main です.(2020年までは master が標準ブランチ名でした.)また,現時点で3つのコミットがあることを確認しておきます.

C:\Users\student\Documents\myReport>git branch ⏎ # ブランチ一覧
* main

C:\Users\student\Documents\myReport>git log --oneline ⏎ 
c779f65 (HEAD -> main) chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>

目次に戻る

ブランチの作成

例えば,new_func1 というブランチを作成します.その後ブランチの一覧を確認すると,新しいブランチが作成されていますが,まだ main ブランチにいることもわかります.現在いるブランチには * マークがついていることに注意してください.

C:\Users\student\Documents\myReport>git branch new_func1 ⏎ # ブランチの作成

C:\Users\student\Documents\myReport>git branch ⏎ # ブランチ一覧
* main
  new_func1

C:\Users\student\Documents\myReport>

目次に戻る

ブランチの移動

ブランチを移動するには git switch コマンドを使います.次の通り上で作成した new_func1 ブランチに入ります.さらに git branch コマンドで現在の作業ブランチを確認します.またコミットログを確認すると,main ブランチと同じ状態(つまりコピーが作成された状態)であることがわかります.

C:\Users\student\Documents\myReport>git switch new_func1 ⏎ # ブランチの移動
Switched to branch 'new_func1'

C:\Users\student\Documents\myReport>git branch ⏎ # ブランチ一覧
  main
* new_func1

C:\Users\student\Documents\myReport>git log --oneline ⏎ 
c779f65 (HEAD -> new_func1, main) chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>

なお git switch コマンドは2019年ごろに搭載された比較的新しいコマンドです.それ以前はgit checkout コマンドがブランチ移動のコマンドでしたが,今ではどちらも利用できます.main ブランチに戻って再び new_func1 ブランチに入ります.(checkout コマンドにはブランチ移動だけでなく様々な機能があり,すべてを覚えるのは難しいかもしれません.それぞれの機能のために追加されたコマンドの利用をお勧めします.)

C:\Users\student\Documents\myReport>git checkout main ⏎ # ブランチの移動
Switched to branch 'main'

C:\Users\student\Documents\myReport>git branch ⏎ # ブランチ一覧
* main
  new_func1

C:\Users\student\Documents\myReport>git checkout new_func1 ⏎ # ブランチの移動
Switched to branch 'new_func1'

C:\Users\student\Documents\myReport>git switch main ⏎ # ブランチの移動
Switched to branch 'main'

C:\Users\student\Documents\myReport>git switch new_func1 ⏎ # ブランチの移動
Switched to branch 'new_func1'

C:\Users\student\Documents\myReport>

目次に戻る

ブランチ上でのコミット

new_func1 ブランチ上でコミットを行います.まず,new_func1 ブランチにいることを確認します.(もし main ブランチにいる場合はブランチを移動してください.)

C:\Users\student\Documents\myReport>git branch ⏎
  main
* new_func1

C:\Users\student\Documents\myReport>

new_func1 ブランチ上で chapter2.txt を編集します.例として最後の行に1行追加することにします.

chapter2.txtWindows を使って Git を勉強しよう
その後 Python Django や React のバージョン管理をしたい
ブランチ操作を実験します

new_func1 ブランチ上でコミットします.この操作は標準ブランチでの操作と変わりありません.

C:\Users\student\Documents\myReport>git log --oneline ⏎ # コミットログを確認
c779f65 (HEAD -> new_func1, main) chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>git status ⏎ # new_func1ブランチ上にいて,chapter2.txtが変更されている
On branch new_func1
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:   chapter2.txt

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

C:\Users\student\Documents\myReport>git diff ⏎ # ファイルの変更点(差分)を確認
diff --git a/chapter2.txt b/chapter2.txt
index a2e81d8..4ddb3c9 100644
--- a/chapter2.txt
+++ b/chapter2.txt
@@ -1,2 +1,3 @@
 Windows を使って Git を勉強しよう
 その後 Python Django や React のバージョン管理をしたい
+ブランチ操作を実験します

C:\Users\student\Documents\myReport>git add . ⏎ # ステージングエリアにアップ

C:\Users\student\Documents\myReport>git commit -m"update chapter2" ⏎ # ブランチ上でコミット
[new_func1 bea88fe] update chapter2
 1 file changed, 1 insertion(+)

C:\Users\student\Documents\myReport>git log --oneline ⏎ # 新しいコミットができて,mainブランチよりも一歩進んだ状態になった
bea88fe (HEAD -> new_func1) update chapter2
c779f65 (main) chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>

目次に戻る

ブランチのマージ

new_func1 ブランチで作成した新たな機能についてテストし問題がないことが確認できたら,その変更を main ブランチに反映させます.このためには次の手順で main ブランチに入ったあと,merge コマンドを使います.main ブランチは new_func1 ブランチよりも遅れていましたが,merge コマンドによって2つのブランチが統合され同じ状態になりまます.なお,Windows ではファイルの内容を表示するために type コマンドを利用しますが,Mac や Linux では cat コマンドを利用してください.

C:\Users\student\Documents\myReport>git branch ⏎ # new_func1ブランチにいる
  main
* new_func1

C:\Users\student\Documents\myReport>git log --oneline ⏎ # new_func1 が進んでいる
bea88fe (HEAD -> new_func1) update chapter2
c779f65 (main) chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>git switch main ⏎ # main ブランチに移動
Switched to branch 'main'

C:\Users\student\Documents\myReport>git log --oneline ⏎ # mainブランチのログを確認
c779f65 (HEAD -> main) chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>type chapter2.txt ⏎ # mainブランチでのファイルの状態(new_func1より1行少ない)
Windows を使って Git を勉強しよう
その後 Python Django や React のバージョン管理をしたい

C:\Users\student\Documents\myReport>git diff new_func1 ⏎ # new_func1ブランチとの差分を確認(new_func1より1行少ない)
diff --git a/chapter2.txt b/chapter2.txt
index 4ddb3c9..a2e81d8 100644
--- a/chapter2.txt
+++ b/chapter2.txt
@@ -1,3 +1,2 @@
 Windows を使って Git を勉強しよう
 その後 Python Django や React のバージョン管理をしたい
-ブランチ操作を実験します

C:\Users\student\Documents\myReport>git merge new_func1 ⏎ # new_func1ブランチをmainブランチにマージ(統合)
Updating c779f65..bea88fe
Fast-forward
 chapter2.txt | 1 +
 1 file changed, 1 insertion(+)

C:\Users\student\Documents\myReport>git log --oneline ⏎ # ログを確認
bea88fe (HEAD -> main, new_func1) update chapter2
c779f65 chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>type chapter2.txt ⏎ # ファイルの内容を確認(1行増えた)
Windows を使って Git を勉強しよう
その後 Python Django や React のバージョン管理をしたい
ブランチ操作を実験します

C:\Users\student\Documents\myReport>

目次に戻る

ブランチの削除

トピックブランチを main ブランチに反映させるとそのトピックブランチは役割を終えたので削除しても良いでしょう.削除したいブランチから他のブランチ(今回は main ブランチ)に移動してから,git branch コマンドに-d オプションを指定して削除します.

C:\Users\student\Documents\myReport>git branch ⏎ # mainブランチにいることを確認
* main
  new_func1

C:\Users\student\Documents\myReport>git branch -d new_func1 ⏎ # ブランチを削除
Deleted branch new_func1 (was bea88fe).

C:\Users\student\Documents\myReport>git branch ⏎ # 削除できたことを確認
* main

C:\Users\student\Documents\myReport>

目次に戻る

ブランチの作成と移動

上の例ではブランチを作成したあと,作成したブランチ移動しました.しかしブランチを作成しただけで移動することなくそのまま main ブランチで作業をしてしまうというミスを起こしがちです.ブランチの作成と移動を一つのコマンドで行うと,そのようなミスを防ぐことができるでしょう.このためには git switch -cgit checkout -b コマンドを使います.次の例では new_func2new_func3 のそれぞれのブランチについて,ブランチ作成してそのブランチに移動するという操作を1つのコマンドで行います.

C:\Users\student\Documents\myReport>git branch ⏎ # mainブランチにいることを確認
* main

C:\Users\student\Documents\myReport>git switch -c new_func2 ⏎ # new_func2を作成して移動
Switched to a new branch 'new_func2'

C:\Users\student\Documents\myReport>git branch ⏎ # new_func2にいることを確認
  main
* new_func2

C:\Users\student\Documents\myReport>git switch main ⏎ # mainに一旦戻る
Switched to branch 'main'

C:\Users\student\Documents\myReport>git checkout -b new_func3 ⏎ # new_func3を作成して移動(ただし過去のやり方なので switch を推奨)
Switched to a new branch 'new_func3'

C:\Users\student\Documents\myReport>git branch ⏎ # new_func3にいることを確認
  main
  new_func2
* new_func3

C:\Users\student\Documents\myReport>

目次に戻る

ブランチの強制削除

トピックブランチを作成して変更をコミットしたものの,main ブランチなど他のブランチに反映(マージ)することなく削除したい場合には -D オプションを指定します.例えば,new_func3 ブランチでコミットしたものの,そのブランチは削除することにします.まず,new_func3 ブランチにいることを確認します.

C:\Users\student\Documents\myReport>git branch ⏎ 
  main
  new_func2
* new_func3

ファイル chapter2.txt に適当な編集を施します.例えば,最後に1行追加します.

chapter2.txtWindows を使って Git を勉強しよう
その後 Python Django や React のバージョン管理をしたい
ブランチ操作を実験します
コミットしたもののこのブランチでの編集はなかったことにしたい

new_func3 ブランチ上でコミットします.

C:\Users\student\Documents\myReport>git log --oneline ⏎ # ログを確認
bea88fe (HEAD -> new_func3, new_func2, main) update chapter2
c779f65 chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>git status ⏎ # new_func3にいてchapter2.txtが修正されている
On branch new_func3
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:   chapter2.txt

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

C:\Users\student\Documents\myReport>git diff ⏎ # ファイルの差分を確認
diff --git a/chapter2.txt b/chapter2.txt
index 4ddb3c9..2d04ad3 100644
--- a/chapter2.txt
+++ b/chapter2.txt
@@ -1,3 +1,4 @@
 Windows を使って Git を勉強しよう
 その後 Python Django や React のバージョン管理をしたい
 ブランチ操作を実験します
+コミットしたもののこのブランチでの編集はなかったことにしたい

C:\Users\student\Documents\myReport>git add . ⏎ # ステージングエリアにアップ

C:\Users\student\Documents\myReport>git commit -m"modify chapter2" ⏎ # コミット
[new_func3 20a5ae3] modify chapter2
 1 file changed, 1 insertion(+)

C:\Users\student\Documents\myReport>git log --oneline ⏎ # コミットログの確認
20a5ae3 (HEAD -> new_func3) modify chapter2
bea88fe (new_func2, main) update chapter2
c779f65 chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>

main ブランチに戻って new_func3 ブランチを削除します.マージしていないブランチについては -d オプションでは削除できず,-D オプションを付けなければならないことに注意してください.ここでもコマンドのヒントが表示されているので確認してください.

C:\Users\student\Documents\myReport>git switch main ⏎ # mainに戻る
Switched to branch 'main'

C:\Users\student\Documents\myReport>git branch -d new_func3 ⏎ # 削除できない
error: the branch 'new_func3' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D new_func3'
hint: Disable this message with "git config advice.forceDeleteBranch false"

C:\Users\student\Documents\myReport>git branch -D new_func3 ⏎ # ブランチの強制削除
Deleted branch new_func3 (was 20a5ae3).

C:\Users\student\Documents\myReport>git branch ⏎ # 削除されたことを確認
* main
  new_func2

C:\Users\student\Documents\myReport>

目次に戻る

マージのログを残す

ここで説明したブランチの標準的なマージは fast-forward 形式と呼ばれ,git merge コマンドを実行したときにマージ自体のコミットは記録されません.しかしながら,あるブランチを作成して別のブランチにマージしたこと自体をコミットログとして残したい場合もあります.そのような場合は git merge コマンドに --no-ff オプションを追加します.また,同時に --no-edit オプションも追加しておくと,コミットメッセージを自動生成してくれます.

ここでは,new_func2 ブランチ上で2つのコミットを重ね,main ブランチにマージしたコミットログも残してみます.まず,new_func2 ブランチに移動します.

C:\Users\student\Documents\myReport>git branch ⏎ # mainブランチにいる
* main
  new_func2

C:\Users\student\Documents\myReport>git switch new_func2 ⏎ # new_func2ブランチに移動する
Switched to branch 'new_func2'

C:\Users\student\Documents\myReport>

2つのファイルをそれぞれ適当に編集します.

chapter1.txtGitのお勉強
神戸学院大学経営学部
Python
React
ブランチをマージしたという記録も残したい
chapter2.txtWindows を使って Git を勉強しよう
その後 Python Django や React のバージョン管理をしたい
new_func2というブランチで操作の実験をしています

順番に2つのコミットを重ねます.

C:\Users\student\Documents\myReport>git status ⏎ # new_func2ブランチにいて,2つのファイルが更新されている
On branch new_func2
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:   chapter1.txt
        modified:   chapter2.txt

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

C:\Users\student\Documents\myReport>git diff ⏎ # ファイルの差分を確認
diff --git a/chapter1.txt b/chapter1.txt
index 82b3a40..4fc6b85 100644
--- a/chapter1.txt
+++ b/chapter1.txt
@@ -2,3 +2,4 @@ Gitのお勉強
 神戸学院大学経営学部
 Python
 React
+ブランチをマージしたという記録も残したい
diff --git a/chapter2.txt b/chapter2.txt
index 4ddb3c9..83ab4e0 100644
--- a/chapter2.txt
+++ b/chapter2.txt
@@ -1,3 +1,3 @@
 Windows を使って Git を勉強しよう
 その後 Python Django や React のバージョン管理をしたい
-ブランチ操作を実験します
+new_func2というブランチで操作の実験をしています

C:\Users\student\Documents\myReport>git add chapter1.txt ⏎ # chapter1.txt だけステージングエリアに

C:\Users\student\Documents\myReport>git commit -m"edit chapter1" ⏎ # コミット
[new_func2 5074a02] edit chapter1
 1 file changed, 1 insertion(+)

C:\Users\student\Documents\myReport>git add chapter2.txt ⏎ # chapter2.txt だけステージングエリアに

C:\Users\student\Documents\myReport>git commit -m"edit chapter2" ⏎ # コミット
[new_func2 2035fb1] edit chapter2
 1 file changed, 1 insertion(+), 1 deletion(-)

C:\Users\student\Documents\myReport>git log --oneline ⏎ # new_func2がmainよりも2コミット進んだ
2035fb1 (HEAD -> new_func2) edit chapter2
5074a02 edit chapter1
bea88fe (main) update chapter2
c779f65 chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>

mainブランチに移動してコミットログを確認します.なお,次の (3) では main ブランチのコミットログを確認していますが,main ブランチよりも進んだ状態にあるブランチのログを見ることはできません.(4) では --all オプションを追加しているので main ブランチにいながら,より進んだブランチのログまでも確認できます.

C:\Users\student\Documents\myReport>git branch ⏎ # (1) ブランチの確認
  main
* new_func2

C:\Users\student\Documents\myReport>git switch main ⏎ # (2) mainブランチへ移動
Switched to branch 'main'

C:\Users\student\Documents\myReport>git log --oneline ⏎ # (3) mainブランチのコミットログを確認
bea88fe (HEAD -> main) update chapter2
c779f65 chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>git log --oneline --all ⏎ # (4) すべてのブランチのコミットログを確認
2035fb1 (new_func2) edit chapter2
5074a02 edit chapter1
bea88fe (HEAD -> main) update chapter2
c779f65 chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>

new_func2 ブランチを main ブランチにマージさせます.このとき,--no-ff オプションを追加することで,ブランチをマージしたこと自体のコミットログを残します.また,--no-edit オプションも追加することでコミットメッセージを自動的に生成します.

C:\Users\student\Documents\myReport>git merge new_func2 --no-ff --no-edit ⏎
Merge made by the 'ort' strategy.
 chapter1.txt | 1 +
 chapter2.txt | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

C:\Users\student\Documents\myReport>

コミットログを確認します.マージ作業のコミットが作成され,「Merge branch 'new_func2'」というコミットメッセージが自動的に生成されたこともわかります.

C:\Users\student\Documents\myReport>git log --oneline ⏎
72f5e41 (HEAD -> main) Merge branch 'new_func2'
2035fb1 (new_func2) edit chapter2
5074a02 edit chapter1
bea88fe update chapter2
c779f65 chapter1修正とchapter2追加
804abdc 1行追加
ce2533a initial commit

C:\Users\student\Documents\myReport>

さらに,コミットログの表示でブランチの分岐と統合を視覚的に確認する方法もあります.具体的には --graph オプションを付けるとよいでしょう.次の通り,new_func2 ブランチ内で2つのコミットが作成されその後にマージされたことが確認できるようになりました.

C:\Users\student\Documents\myReport>git log --oneline --graph ⏎
*   72f5e41 (HEAD -> main) Merge branch 'new_func2'
|\
| * 2035fb1 (new_func2) edit chapter2
| * 5074a02 edit chapter1
|/
* bea88fe update chapter2
* c779f65 chapter1修正とchapter2追加
* 804abdc 1行追加
* ce2533a initial commit

C:\Users\student\Documents\myReport>

最後にマージによって不要になった new_func2 ブランチを削除します.

C:\Users\student\Documents\myReport>git branch ⏎ # mainブランチにいる
* main
  new_func2

C:\Users\student\Documents\myReport>git branch -d new_func2 ⏎ # ブランチの削除
Deleted branch new_func2 (was 2035fb1).

C:\Users\student\Documents\myReport>git branch ⏎ # 削除されたことを確認
* main

C:\Users\student\Documents\myReport>git log --oneline --graph ⏎ # コミットログの確認
*   72f5e41 (HEAD -> main) Merge branch 'new_func2'
|\
| * 2035fb1 edit chapter2
| * 5074a02 edit chapter1
|/
* bea88fe update chapter2
* c779f65 chapter1修正とchapter2追加
* 804abdc 1行追加
* ce2533a initial commit

C:\Users\student\Documents\myReport>

目次に戻る