作業内容の一時保存

GitBeginner
オンラインで実践に進む

はじめに

Git エクスプローラーの皆さん、おかえりなさい!今日は、作業中の内容を管理するための Git の最も便利な機能の一つである「スタッシュ(stash)」について深く掘り下げていきましょう。機能を開発している途中で、突然別のタスクに切り替えなければならなくなったことはありませんか?そんな時、Git stash が救世主となります!

Git stash は、作りかけの作業を一時的に保管しておける「魔法の引き出し」のようなものだと考えてください。これを使えば、中途半端な状態のままコミットすることなく、素早くコンテキスト(作業環境)を切り替えることができます。ブランチを切り替えたり、最新の更新をプルしたり、緊急のバグ修正に対応したりする必要がある場合に、非常に役立ちます。

この実験では、作業中の内容を保存するための Git stash の使い方、スタッシュした変更の適用方法、スタッシュからのブランチ作成、複数のスタッシュの管理、そしてスタッシュのクリーンアップ方法について学習します。この実験を終える頃には、ワークフローをよりスムーズで柔軟にする強力な新しいツールが、あなたの Git ツールキットに加わっているはずです。

それでは、Git stash のパワーを解き放ちましょう!

ワークスペースのセットアップ

スタッシュを試す前に、実験用のワークスペースを準備しましょう。新しいディレクトリを作成し、Git リポジトリを初期化して、最初のコンテンツを追加します。

ターミナルを開き、以下のコマンドを入力してください。

cd ~/project
mkdir git-stash-lab
cd git-stash-lab
git init
echo "## Git Stash Lab" > README.md
git add README.md
git commit -m "Initial commit"

これらのコマンドの内容を解説します:

  1. cd ~/project: ホームディレクトリ内の "project" フォルダに移動します。
  2. mkdir git-stash-lab: "git-stash-lab" という名前の新しいディレクトリを作成します。
  3. cd git-stash-lab: 作成したディレクトリに移動します。
  4. git init: 現在のディレクトリに新しい Git リポジトリを初期化します。
  5. echo "## Git Stash Lab" > README.md: "## Git Stash Lab" という内容の "README.md" ファイルを作成します。
  6. git add README.md: 新しいファイルをコミット対象(ステージングエリア)に追加します。
  7. git commit -m "Initial commit": ステージングされた変更を最初のコミットとして記録します。

素晴らしい!これで 1 つのコミットを持つリポジトリができました。ステータスを確認してみましょう。

git status

ワーキングツリーがクリーンである(working tree clean)というメッセージが表示されるはずです。これで Git stash の実験を始める準備が整いました!

問題が発生した場合は、正しいディレクトリにいるか、システムに Git が正しくインストールされているかを確認してください。git --version を実行することで、Git のインストール状況を確認できます。

変更内容のスタッシュ

ワークスペースが整ったので、いくつか変更を加えて、それをスタッシュする方法を学びましょう。

まず、README.md ファイルに変更を加えます。

echo "This is a work in progress" >> README.md

このコマンドは、README.md ファイルに新しい行を追記します。次に、新しいファイルも作成してみましょう。

echo "Some important notes" > notes.txt

ここで git status を実行すると、変更されたファイルと追跡されていない(untracked)ファイルの両方があることがわかります。

git status

README.md が変更(modified)され、notes.txt が追跡対象外(untracked)であるという出力が表示されるはずです。

この時点で、急いで別のタスクに切り替える必要があるものの、これらの変更をまだコミットしたくないと想像してください。ここで git stash が役に立ちます!

変更をスタッシュするには、以下を実行します。

git stash

次のような出力が表示されるはずです。

Saved working directory and index state WIP on master: 1234567 Initial commit

ここで再び git status を実行すると、興味深いことがわかります。

git status

README.md は変更として表示されなくなりましたが、notes.txt は依然として追跡対象外のファイルとしてリストされています。これは git stash に関する非常に重要なポイントです。

重要: デフォルトでは、git stash は以下のものだけをスタッシュします:

  1. 追跡対象ファイル(Git がすでに管理しているファイル)への変更
  2. ステージング済みの変更

追跡対象外のファイル(今回の notes.txt など)は、デフォルトではスタッシュに含まれません。この挙動は、リポジトリに含めたくない新しいファイルを Git が誤って隠してしまわないようにするためのものです。

追跡対象外のファイルもスタッシュに含めたい場合は、-u(または --include-untracked)オプションを使用します。

git stash -u

このコマンドを実行すると、README.md への変更と新しい notes.txt ファイルの両方がスタッシュされます。

スタッシュの中に何が入っているかを確認するには、以下を使用します。

git stash list

-u オプションを使用したかどうかに応じて、1 つまたは 2 つのスタッシュエントリが表示されます。

q キーを押して、スタッシュリストの表示を終了します。

スタッシュは素早いコンテキストの切り替えには最適ですが、長期的なワークフローにおけるコミットの代わりにはならないことを覚えておいてください。スタッシュはあくまで一時的な保管場所として設計されています。

スタッシュした変更の適用

変更をスタッシュしたので、それらを元に戻す方法を学びましょう。これには主に git stash apply と git stash pop の 2 つのコマンドがあります。

まずは git stash apply から始めましょう。

git stash apply

このコマンドを実行した後、予想外のことが起こるかもしれません。ステータスを確認してみましょう。

git status

次のような出力が表示されるはずです。

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

nothing added to commit but untracked files present (use "git add" to track)

驚いたことに、notes.txt だけが追跡対象外のファイルとして表示され、README.md への変更は見当たりません。この挙動は以下の理由で発生します:

  1. ステップ 2 で、最初に -u オプションなしで git stash を実行しました。これにより README.md の変更だけがスタッシュされました。
  2. 次に git stash -u を実行しました。これにより追跡対象外だった notes.txt がスタッシュされました(README.md は前のスタッシュですでにクリーンになっていたため)。
  3. スタッシュを適用すると、Git は最新のスタッシュ(-u で作成されたもの)を適用します。これには notes.txt しか含まれていないため、README.md の変更は表示されません。

README.md への変更を含むすべての変更を確認するには、次のように指定します。

git stash apply stash@{1}

これで再びステータスを確認すると、README.md の変更と、追跡対象外のファイルとしての notes.txt の両方が確認できるはずです。

この状況は、スタッシュを扱う際の重要な側面を浮き彫りにしています。スタッシュを作成および適用する順序が結果に影響を与える可能性があるということです。特に複数のスタッシュを扱う場合は、適用する前にスタッシュの内容を確認するのが良い習慣です。

apply と pop の違いは、apply はスタッシュに変更を保持し続けるのに対し、pop は適用後にスタッシュリストからその変更を削除する点です。

git stash clear
git stash -u
git stash list

まず clear でスタッシュをすべて削除してリセットし、次に -u オプションを付けて追跡対象外のファイルも含めてスタッシュし直します。最後に list でスタッシュが作成されたことを確認します。

もう一度変更をスタッシュして、今度は pop を試してみましょう。

git stash pop

以前と同様の出力が表示されますが、今 git stash list を実行すると、スタッシュリストが空になっていることがわかります。

なぜ apply と pop の両方があるのでしょうか? apply は、同じスタッシュ内容を複数のブランチに適用したい場合に便利です。一方 pop は、同じブランチで作業を再開する際によく使われます。

スタッシュからのブランチ作成

スタッシュした変更を、実は別のブランチで進めるべきだったと気づくことがあります。Git では git stash branch コマンドを使ってこれを簡単に行えます。

まず、新しい変更を作成してスタッシュしましょう。

echo "Feature in progress" >> README.md
echo "More notes" >> notes.txt
git stash -u

では、これらの変更を使って新しいブランチを作成します。

git stash branch feature-branch

このコマンドは "feature-branch" という名前の新しいブランチを作成し、そこにチェックアウトして、スタッシュされていた変更を適用します。その後、スタッシュはリストから削除されます。

次のような出力が表示されるはずです。

Switched to a new branch 'feature-branch'
On branch feature-branch
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)
        notes.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1234567890abcdef1234567890abcdef12345678)

この機能は、実験的な変更をスタッシュした後に、それを独立したブランチとして本格的に開発することに決めた場合に非常に便利です。

スタッシュからブランチを作成した後、その変更を保持したい場合はコミットする必要があることを忘れないでください。

git add README.md notes.txt
git commit -m "Start new feature"

master ブランチに戻るには、以下を使用します。

git checkout master

複数のスタッシュの管理

Git を使って作業を進めていると、複数の変更セットをスタッシュすることがあります。Git では複数のスタッシュを簡単に管理できます。複数のスタッシュを作成、一覧表示、管理する方法を見ていきましょう。

まず、異なる変更を持つ 3 つのスタッシュを作成します。

## 1つ目のスタッシュ
echo "Change 1" >> README.md
git stash push -m "First change"

## 2つ目のスタッシュ(追跡対象外のファイルを含む)
echo "Change 2" >> README.md
echo "Note 2" >> notes.txt
git stash push -u -m "Second change"

## 3つ目のスタッシュ
echo "Change 3" >> README.md
git stash push -m "Third change"

注意: ここでは単なる git stash ではなく git stash push を使用しています。push サブコマンドは、特に -m フラグでカスタムメッセージを追加したい場合に推奨される現代的な方法です。git stash や git stash -u も引き続き機能しますが(これらは git stash push のショートカットです)、明示的に git stash push を使うことで、特に説明的なメッセージを付けて複数のスタッシュを管理する際に、より制御しやすく明確になります。

何を行ったか整理しましょう:

  1. README.md への変更を含む 1 つ目のスタッシュを作成。
  2. README.md への変更と新しい追跡対象外ファイルを含む 2 つ目のスタッシュを作成。
  3. README.md への別の変更を含む 3 つ目のスタッシュを作成。
  4. -m フラグを使用して説明的なメッセージを追加。
  5. 2 つ目のスタッシュでは -u フラグを使用して追跡対象外のファイルを含めた。

では、スタッシュを一覧表示してみましょう。

git stash list

次のような出力が表示されるはずです。

stash@{0}: On master: Third change
stash@{1}: On master: Second change
stash@{2}: On master: First change

適用することなく、スタッシュの内容を確認できます。

git stash show stash@{1}

さらに詳細を確認するには、-p フラグを付けて完全な差分(diff)を表示します。

git stash show -p stash@{1}

さらに 2 つのスタッシュを作成して、より多くのセットを管理する練習をしましょう。

## 4つ目のスタッシュ
echo "Change 4" >> README.md
git stash push -m "Fourth change"

## 5つ目のスタッシュ
echo "Change 5" >> README.md
git stash push -m "Fifth change"

もう一度スタッシュリストを確認します。

git stash list

リストに 5 つのスタッシュが表示されるはずです。

stash@{0}: On master: Fifth change
stash@{1}: On master: Fourth change
stash@{2}: On master: Third change
stash@{3}: On master: Second change
stash@{4}: On master: First change

複数のタスクを同時にこなしている場合、複数のスタッシュを管理できるのは便利です。ただし、スタッシュを溜め込みすぎると混乱を招くため、長期的な作業にはブランチの使用を検討してください。

覚えておいてください:スタッシュは一時的なものです。スタッシュを長期間保持していることに気づいたら、フィーチャーブランチ(機能開発用ブランチ)を作成するか、変更をコミットすることを検討しましょう。

スタッシュのクリーンアップ

ワークフローの中でスタッシュを使っていると、不要になったスタッシュが溜まっていくことがあります。整理整頓のために、定期的にスタッシュをクリーンアップするのが良い習慣です。

特定のスタッシュを 1 つだけ削除するには、以前に見た drop コマンドを使用します。

git stash drop stash@{2}

これにより、リストから 3 つ目のスタッシュ("Third change")が削除されます。

すべてのスタッシュを一度に削除したい場合は、以下を使用します。

git stash clear

このコマンドには細心の注意を払ってください!すべてのスタッシュが削除され、元に戻すことはできません。

もう一つの便利なコマンドは、先ほど学んだ git stash pop です。これは最新のスタッシュを適用し、同時にリストから削除します。

git stash pop

一般的に、スタッシュリストは短く保つのが良い習慣です。スタッシュは作業中の内容を一時的に保管するためのものです。もし多くのスタッシュが溜まっているなら、それはもっと頻繁にコミットするか、長期的な作業のためにブランチを作成すべきだというサインかもしれません。

まとめ

おめでとうございます、Git stash マスター!あなたの Git ツールキットに強力な新しいツールが加わりました。今回学んだ主要な概念を振り返ってみましょう:

  1. 変更内容のスタッシュ: git stash を使って作業中の内容を一時的に保存する方法を学びました。
  2. スタッシュした変更の適用: git stash apply と git stash pop を使って、スタッシュした変更を戻す方法を確認しました。
  3. スタッシュからのブランチ作成: git stash branch を使って、スタッシュした変更セットを新しいブランチに変換する方法を見ました。
  4. 複数のスタッシュの管理: 複数のスタッシュを扱い、必要に応じて特定のスタッシュを表示したり適用したりする方法を学びました。
  5. スタッシュのクリーンアップ: 個別のスタッシュの削除や全削除の方法を学び、スタッシュを整理する習慣を身につけました。

Git stash は、中途半端な作業をコミットすることなく素早くコンテキストを切り替えられる、非常に便利な機能です。タスクやブランチを急いで切り替える必要がある場面で真価を発揮します。

スタッシュは便利ですが、あくまで一時的なものであることを忘れないでください。長期的な作業の場合は、通常、変更をコミットするか新しいブランチを作成する方が適切です。スタッシュを賢く使いこなし、ワークフローをよりスムーズで柔軟なものにしていきましょう。