1. 概要

Git は、今日非常に人気のあるバージョン管理システムです。

このクイックチュートリアルでは、既存のコミットされていない変更を新しいブランチに移動する方法について説明します。

2. 問題の紹介

まず、Git管理対象プロジェクトに新しい機能を追加する一般的なワークフローについて考えてみましょう。

  • feature などの新しい機能ブランチを作成してから、そのブランチに切り替えます
  • 機能を実装し、ローカルリポジトリにコミットします
  • リモートリポジトリの機能ブランチにプッシュし、プルリクエストを作成します
  • 他のチームメイトのレビューの後、新しい変更をマスターまたはリリースブランチにマージできます

ただし、変更を加え始めたものの、新しい機能ブランチを作成してそれに切り替えることを忘れてしまうことがあります。 その結果、変更をコミットしようとしているときに、間違ったブランチ(たとえば、 master ブランチ)にいることに気付く場合があります。

したがって、新しい機能ブランチを作成し、コミットされていない作業を新しいブランチに移動する必要があります。 さらに、masterブランチは変更しないでください。

例でこのシナリオを簡単に説明できます。 myRepoというGitリポジトリがあるとしましょう。

$ git branch
* master

$ git status
On branch master
nothing to commit, working tree clean

上記の出力からわかるように、現在masterブランチにいます。 また、作業ツリーはきれいです。

次に、いくつかの変更を加えましょう。

$ git status
On branch master
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:   Readme.md

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

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

上記の出力が示すように、新しいファイル a-new-file.txt を追加し、Readme.mdの内容を変更しました。 ここで、作業はmasterブランチではなく機能ブランチにコミットする必要があることがわかりました。

次に、変更を新しいブランチに移動し、masterを変更しないようにする方法を見てみましょう。

3. gitcheckoutコマンドの使用

The git checkout -b コマンドは新しいブランチを作成し、それに切り替えます。 さらに、このコマンドは現在のブランチをそのままにし、コミットされていないすべての変更を新しいブランチにもたらします。

次に、myRepoプロジェクトでgitcheckoutコマンドをテストしてみましょう。

$ git branch
* master

$ git co -b feature1
Switched to a new branch 'feature1'

$ git status
On branch feature1
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:   Readme.md

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

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

上記のコマンドが示すように、 feature1 ブランチを作成し、コミットされていないすべての変更をmasterからfeature1に移動しました。 次に、変更をステージングしてコミットしましょう。

$ git add . && git commit -m'implemented feature1'
[feature1 2ffc161] implemented feature1
 2 files changed, 2 insertions(+)
 create mode 100644 a-new-file.txt

$ git log --abbrev-commit feature1
commit 2ffc161 (HEAD -> feature1)
Author: ...
Date:   ...
    implemented feature1

commit b009ddf (master)
Author: ...
Date:   ...
    init commit

それでは、 master ブランチに戻って、変更されていないかどうかを確認しましょう。

$ git checkout master
Switched to branch 'master'
$ git status
On branch master
nothing to commit, working tree clean
$ git log --abbrev-commit master
commit b009ddf (HEAD -> master)
Author: ...
Date:   ...
    init commit

出力に示されているように、masterブランチにローカルな変更はありません。 さらに、masterにも新しいコミットはありません。

4. gitswitchコマンドの使用

ご存知のとおり、Gitの checkout コマンドは、スイスアーミーナイフのようなものです。 同じコマンドで、作業ツリーファイルの復元、ブランチの切り替え、ブランチの作成、ヘッドの移動など、さまざまな種類の操作を実行できます。 checkoutコマンドの使用法はかなり過負荷です。

そのため、Gitはバージョン2.23以降 git switch コマンドを導入して、checkoutコマンドの過負荷使用からの混乱を解消しています。 その名前が示すように、 git switch を使用すると、ブランチを切り替えることができます。 さらに、 -Cオプションを使用して、新しいブランチを作成し、ワンショットでそれに切り替えることができます git checkout-bコマンドとほとんど同じように機能します。

次に、myRepoプロジェクトでgitcheckout-bと同じテストを実行しましょう。

$ git branch
  feature1
* master

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm ...)
  (use "git restore ...)
	deleted:    Readme.md

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

...

上記の出力でわかるように、現在masterブランチにいます。 今回は、ファイル Readme.md を削除し、新しいReadmeNew.mdファイルを追加しました。

次に、 git switch コマンドを使用して、これらのコミットされていない変更をfeature2という新しいブランチに移動しましょう。

$ git switch -C feature2
Switched to a new branch 'feature2'

$ git status
On branch feature2
Changes not staged for commit:
  (use "git add/rm ...)
  (use "git restore ...)
        deleted: Readme.md
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        ReadmeNew.md
...
$ git add . && git commit -m 'feature2 is done'
[feature2 6cd5933] feature2 is done
1 file changed, 0 insertions(+), 0 deletions(-)
rename Readme.md => ReadmeNew.md (100%)
$ git log --abbrev-commit feature2
commit 6cd5933 (HEAD -> feature2)
Author: ...
Date:   ...
      feature2 is done
commit b009ddf (master)
Author: ...
Date:   ...
      init commit

上記の出力でわかるように、 git switch-Cは新しいブランチfeature2を作成し、feature2に移動します。 さらに、コミットされていないすべての変更は、masterからfeature2ブランチに移動されました。 次に、feature2ブランチへの変更をコミットしました。

次に、 master ブランチに戻って、変更されていないかどうかを確認します。

$ git switch master
Switched to branch 'master'

$ git status
On branch master
nothing to commit, working tree clean
$ ls -1 Readme.md 
Readme.md

$ git log --abbrev-commit master
commit b009ddf (HEAD -> master)
Author: ...
Date:   ...
    init commit

これまで見てきたように、 master ブランチでは、以前に行った作業ツリーファイルへのすべての変更が復元されています。 たとえば、削除されたファイルReadme.mdが戻ってきました。 さらに、 git log コマンドは、masterで新しいコミットを表示しません。

5. 結論

この記事では、コミットされていない変更を新しいGitブランチに移動するためのいくつかの簡単な方法について説明しました。 どちらのコマンドも非常に簡単に使用できます。

  • git checkout -b
  • gitスイッチ-C