Git によるバージョン管理入門
ブランチ操作
システム開発の規模が大きくなるとブランチ操作は必須になるでしょう.例えば,新たな機能を開発するときにはそのトピックブランチを作成して,そのブランチ上でソースコードを編集します.新たな機能が動作する事が確認できたら標準ブランチに戻って,変更点を標準ブランチに反映させます.
また大きな規模のシステムはチームで開発するので,チーム開発を効率的に進めるためのブランチ運用ルールがあります.代表的なものが Git-flow と GitHub 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.txt
Windows を使って 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 -c
や git checkout -b
コマンドを使います.次の例では new_func2
と new_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.txt
Windows を使って 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.txt
Gitのお勉強
神戸学院大学経営学部
Python
React
ブランチをマージしたという記録も残したい
chapter2.txt
Windows を使って 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>