git stash
git stash
を使用すると、作業コピーに加えた変更を一時的に棚上げし (または stash して)、他の作業をした後で戻って再適用できます。コード変更が完了しておらずまだコミットできない状態で、素早くコンテキストを切り替えて別の作業を行う場合には stash が便利です。
作業を隠す
git stash
コマンドは、コミットされていない変更 (ステージングされたものおよびされていないもの) を取り出し、後で使用するために保存してから、作業コピーから取り消します。例:
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
nothing to commit, working tree clean
関連資料
Git Branch コマンド
ソリューションを見る
Bitbucket Cloud での Git の使用方法についてのチュートリアルです。
この時点で、自由に変更を加えたり、新しいコミットを作成したり、ブランチを切り替えたり、その他の Git 操作を実行することができます。準備が整ったら、stash しておいた変更に戻って、再適用します。
stash は作業しているローカルの Git リポジトリにのみ適用されます。プッシュ時にサーバーには転送されません。
隠していた変更を再適用する
以前に stash した変更は、git stash pop
を使用して再適用できます。
$ git status
On branch main
nothing to commit, working tree clean
$ git stash pop
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Dropped refs/stash@{0} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)
stash をポップすると、stash から変更が削除され、作業コピーに再適用されます。
または、作業コピーに変更を再適用した上で、git stash apply
を使用してその変更を stash に維持することも可能です。
$ git stash apply
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
これは、stash した変更を複数のブランチに適用するのに便利です。
stash の基本を理解したところで、git stash
について注意することが1つあります。既定では、Git は未追跡ファイルや無視されたファイルに対する変更を stash しません。
未追跡または無視されたファイルを隠す
既定では、git stash
を実行すると以下の変更が stash されます。
- インデックスに追加された変更 (ステージングされた変更)
- Git によって現在追跡されているファイルに対する変更 (ステージングされていない変更)
ただし、以下は stash されません。
- まだステージングされていない作業コピー内の新しいファイル
- 無視された ファイル
したがって、上記の例に 3 番目のファイルを追加しても、それをステージングしないと (つまり、git add
を実行しない場合)、git stash
はそのファイルを stash しません。
$ script.js
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Untracked files:
script.js
$ git stash
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
Untracked files:
script.js
-u
オプション (または --include-untracked
) を追加すると、追跡対象外のファイルも git stash
で stash できます。
$ git status
On branch main
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Untracked files:
script.js
$ git stash -u
Saved working directory and index state WIP on main: 5002d47 our new homepage
HEAD is now at 5002d47 our new homepage
$ git status
On branch main
nothing to commit, working tree clean
無視された ファイルへの変更を含めることもできます。それには、-a
オプション (または --all
) を git stash
の実行時に渡します。
複数の stash の管理
使用できる stash は1つに限定されているわけではありません。git stash
を数回実行して複数の stash を作成し、git stash list
を使用して作成した stash を表示できます。既定では、stash は、stash の作成元のブランチやコミット上にある "WIP" (進行中の作業) として識別されます。しばらくすると、各 stash に含まれているものを覚えておくことが難しくなる場合があります。
$ git stash list
stash@{0}: WIP on main: 5002d47 our new homepage
stash@{1}: WIP on main: 5002d47 our new homepage
stash@{2}: WIP on main: 5002d47 our new homepage
もう少し事情がわかるように、git stash save "message"
を使用して stash に説明文を付けることをお勧めします。
$ git stash save "add style to our site"
Saved working directory and index state On main: add style to our site
HEAD is now at 5002d47 our new homepage
$ git stash list
stash@{0}: On main: add style to our site
stash@{1}: WIP on main: 5002d47 our new homepage
stash@{2}: WIP on main: 5002d47 our new homepage
既定では、git stash pop
は直近に作成された stash を再適用します。stash@{0}
最後の引数として識別子を渡すことで、再適用する stash を選択できます。たとえば、次のようになります。
$ git stash pop stash@{2}
stash diffs の表示
git stash show
を使用すると、stash の要約を表示できます。
$ git stash show
index.html | 1 +
style.css | 3 +++
2 files changed, 4 insertions(+)
stash のすべての差分を表示するには -p
オプション (または --patch
) を渡します。
$ git stash show -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* {
+ text-decoration: blink;
+}
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+<link rel="stylesheet" href="style.css"/>
部分的に隠す
また、単一のファイルや複数のファイル、ファイル内の個別の変更を選んで stash できます。git stash
に -p
オプション (または --patch
) を渡すと、作業コピーで変更された各「ハンク」で処理を反復して、その変更を stash するかを確認するメッセージが表示されます:
$ git stash -p
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..d92368b
--- /dev/null
+++ b/style.css
@@ -0,0 +1,3 @@
+* {
+ text-decoration: blink;
+}
Stash this hunk [y,n,q,a,d,/,e,?]? y
diff --git a/index.html b/index.html
index 9daeafb..ebdcbd2 100644
--- a/index.html
+++ b/index.html
@@ -1 +1,2 @@
+<link rel="stylesheet" href="style.css"/>
Stash this hunk [y,n,q,a,d,/,e,?]? n
? を入力すると、ハンクコマンドの全リストを取得できます。よく使用されるコマンドは次のとおりです。
コマンド | 説明 |
---|---|
/ | 説明 正規表現を使用してハンクを検索 |
? | 説明 サポート |
n | 説明 このハンクを隠さない |
q | 説明 終了 (既に選択されているハンクはすべて stash されます) |
s | 説明 この変更差分ブロックを小さなブロックに分割 |
これからは | 説明 この変更差分ブロックを stash |
明示的な「中止」コマンドはありませんが、キーボードで CTRL-C
(SIGINT) を押すと stash プロセスを中止します。
stash からのブランチの作成
ブランチでの変更が stash の変更と異なる場合、stash の変更を適用しようとすると競合が発生する可能性があります。代わりに、git stash branch
を使用して新しいブランチを作成し、そこに棚上げ (stash) しておいた変更を適用することができます。
$ git stash branch add-stylesheet stash@{1}
Switched to a new branch 'add-stylesheet'
On branch add-stylesheet
Changes to be committed:
new file: style.css
Changes not staged for commit:
modified: index.html
Dropped refs/stash@{1} (32b3aa1d185dfe6d57b3c3cc3b32cbf3e380cc6a)
これは、stash を作成したコミットをベースにした新しいブランチをチェックアウトし、stash しておいた変更をそのブランチに適用します。
stash のクリーンアップ
特定の stash が必要なくなった場合は、git stash drop
で削除できます。
$ git stash drop stash@{1}
Dropped stash@{1} (17e2697fd8251df6163117cb3d58c1f62a5e7cdb)
または、次の方法ですべての stash を削除できます。
$ git stash clear
git stash の使い方
git stash
の使用方法のみが必要な場合は、この先を読まなくてもかまいません。ただし、Git (と git stash
) の仕組みに関心がある場合は、このまま読み進めてください。
stash はコミットオブジェクトとしてご使用のリポジトリ内に実際にエンコードされます。.git/refs/stash
にある特別な ref は最近作成された最新の stash をポイントし、以前に作成された stash は stash
ref の reflog により参照されます。このため、stash@{n}:
で stash を参照すると、実際には stash
ref の nth reflog エントリーを参照していることになります。stash は単なるコミットにすぎないため、git log
で調べることができます。
単一の git stash
操作では、stash の内容に応じて 2 つまたは 3 つのコミットが新たに作成されます。上の図のコミットに関する説明は以下のとおりです。
stash@{0}
は、git stash
の実行時に作業コピー内の追跡対象ファイルを保存するための新しいコミットstash@ {0}
の最初の親、git stash
実行時に HEAD にあった既存のコミットstash@{0}
の 2 番目の親は、git stash
を実行した時のインデックスを表す新しいコミットです。stash@{0}
の 3 番目の親は、git stash
の実行時に作業コピー内にあった未追跡ファイルを表す新しいコミットです。この 3 番目の親は次の条件下でのみ作成されます。- 作業コピー内に実際に未追跡ファイルが含まれていた。
--include-untracked
または--all
オプションを指定してgit stash
を呼び出した。
git stash
でワークツリーとインデックスをコミットとしてエンコードする仕組み:
- stash する前に、作業ツリーに追跡済みファイル、未追跡ファイル、および無視されたファイルに対する変更が含まれている場合があります。これらの変更の一部は、インデックスにステージングされている場合もあります。
git stash
を呼び出すと、DAG の2つの新しいコミットとして、追跡済みファイルへの変更がエンコードされます。1つはステージングされていない変更で、もう1つはインデックスにステージングされた変更です。特別なrefs/stash
ref が更新され、これらのコミットをポイントします。
--include-untracked
オプションを使って追跡対象外ファイルへの変更を追加コミットとしてエンコードすることもできます。
--all
オプションでは、無視されたファイルと追跡対象外のファイルへの変更を同じコミットに含められます。
git stash pop
を実行すると、上記のコミットの変更が作業コピーとインデックスの更新に使用されます。stash reflog がシャッフルされて、ポップされたコミットは削除されます。ポップされたコミットはすぐには削除されませんが、将来のガベージコレクションの候補になります。
この記事を共有する
次のトピック
おすすめコンテンツ
次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。