2016/07/27更新

[Git] Stashコマンドを使って、ローカルの変更を一次的に退避する

このエントリーをはてなブックマークに追加      

こんにちは、Gitと毎日格闘中の@yoheiMuneです。
今日はgit stashコマンドを使って、コミット前の変更内容を一旦退避する方法をブログに書きたいと思います。Gitって色々な機能があって便利だなぁと思う今日この頃です。

画像

目次




git stashの使いどころ

git stashコマンドではコミット前の変更内容を一旦退避することができる便利な機能です(前々から知っていたんですが、なかなか使うまでに踏み出せなかった)。そんなコマンドの使用例としては、

  • 新機能をとあるブランチで誠意開発中のところ、既存機能のバグが報告され緊急で治さねばならぬ。そんな時に一旦変更をスタッシュで退避して、別ブランチに移動してバグフィックスをする。
  • ノリノリで開発していてコミットしようとしたら実は別ブランチで開発していたことに気づく。ブランチ移動しようと思っても変更内容がぶつかるようで移動できない。そんな時は一旦スタッシュに保存してブランチを移動して、移動先のブランチでスタッシュ内容を復元する。

と、割り込み系の作業があった場合や、勘違いしてた時などに便利です。



stashコマンドの使い方

スタッシュを保存する

スタッシュの使い方は非常にシンプルで覚えやすいです。例えば以下のようなコミット前の変更がある状態で、
$ git st
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   main.js
#   modified:   sub.js
#
no changes added to commit (use "git add" and/or "git commit -a")
コマンドを実行すると、変更内容を一時的に退避して、ブランチ上は変更前のまっさらな状態に戻すことができます。
$ git stash
Saved working directory and index state WIP on master: 752c714 add js files
HEAD is now at 752c714 add js files
上記の場合、HEADブランチは752c714が最終コミットであることを示しています。

また、以下のようにすることで、メッセージ付きでスタッシュすることもできます。
# メッセージ付きでスタッシュ
$ git stash save "ユーザー情報更新APIの作成中だよー"
Saved working directory and index state On master: ユーザー情報更新APIの作成中だよー
HEAD is now at 752c714 add js files
メッセージ付きにすると後でスタッシュを見た時にわかりやすいので、何かコメントをつけることをお勧めします。

ちなみに(裏技的ですが)スタッシュに付けたメッセージを変更したい場合には、以下のファイルを変更することでメッセージを変えることができます。
# スタッシュのメッセージの内容を変更する
vim .git/logs/refs/stash


スタッシュ内容を確認する(一覧/詳細)


そしてスタッシュした一覧を見るには、listコマンドを実行します。
$ git stash list
stash@{0}: WIP on master: 752c714 add js files
stash@{1}: WIP on master: 752c714 add js files
stash@{2}: WIP on develop: 752c714 add js files
上記の場合には3つのスタッシュが存在することがわかります(上から順に新しい順です)。また、具体的なスタッシュの中身は、showコマンドで確認することができます。
$ git stash show
 main.js | 1 +
 sub.js  | 1 +
 2 files changed, 2 insertions(+)
または、-pオプションをつけることで、変更内容の詳細も確認することができます。
$ git stash show -p
diff --git a/main.js b/main.js
index e69de29..5aa87c5 100644
--- a/main.js
+++ b/main.js
@@ -0,0 +1 @@
+console.log("main.js");
\ No newline at end of file
diff --git a/sub.js b/sub.js
index e69de29..382e985 100644
--- a/sub.js
+++ b/sub.js
@@ -0,0 +1 @@
+console.log("sub.js");
\ No newline at end of file
また、最新以外のスタッシュの中身を確認する場合には、以下のように指定します。
$ git stash show stash@{2}

スタッシュ内容を復元する

スタッシュ内容を復元するためにはapplyコマンドを発行します。
$ git stash apply
# On branch master
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#   modified:   main.js
#   modified:   sub.js
#
no changes added to commit (use "git add" and/or "git commit -a")
変更が反映されました。もしスタッシュが複数存在する場合には、以下のように指定して戻すこともできます。
# スタッシュが複数存在する場合は、
$ git stash list
stash@{0}: WIP on master: 752c714 add js files
stash@{1}: WIP on master: 752c714 add js files
stash@{2}: WIP on develop: 752c714 add js files

# 指定して戻すこともできる(指定しない場合は、最上位のスタッシュが適用される)
$ git stash apply stash@{2}
こんな感じで、スタッシュから復元することができます。


stashを削除する

stashの内容を削除するにはdropコマンドを利用します。
$ git stash list
stash@{0}: WIP on master: 752c714 add js files
stash@{1}: WIP on master: 752c714 add js files
stash@{2}: WIP on develop: 752c714 add js files

$ git stash drop
Dropped refs/stash@{0} (fedf61c085d055bce4122e2b7127caab3a397414)
これで削除することができました。ちなみにapplydropを同時に行う方法として、git stash popというコマンドも存在します(しかし個人的にはpopは使いません。applyした後にひどいコンフリクトが発生した場合に、もうスタッシュは消え去っているので、戻すのが非常に大変だからです)。


ちなみに、スタッシュを別ブランチでも復元できる

冒頭で書いたユースケース2番目のように、スタッシュを別ブランチで復元することもできます。例えば以下のように間違ってmasterブランチで実装してしまっていた場合に、
$ git st
# On branch master
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#   modified:   main.js
#   modified:   sub.js
#
no changes added to commit (use "git add" and/or "git commit -a")
一度スタッシュに退避して、
$ git stash
Saved working directory and index state WIP on master: 752c714 add js files
HEAD is now at 752c714 add js files
ブランチを移動して、その変更を復元することで、ブランチをまたいでスタッシュを利用することができます。
# ブランチを移動して、
$ git checkout develop
Switched to branch 'develop'

# スタッシュを復元する
$ git stash apply
ちなみに復元した場合にもしかしたらコンフリクトするかもしれませんが、その場合にはマージの時と同じく落ち着いて対処すればOKです。



参考資料

git stashを学ぶために以下の記事を参考にしました。ありがとうございます。

Git - 作業を隠す

色々な git stash - Qiita

Git - git-stash Documentation

Change Git stash message - Stack Overflow



最後に

Gitには本当に色々と便利なコマンドが盛りだくさんですね。これだけ様々なユースケースで使えるツールだからこそ多くの人に愛されているのかと、サービスを作っている人としてサービス面でも色々と勉強させられます。

最後になりますが本ブログでは、開発関連・Swift・Linux・フロントエンド・Python・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSTwitterをフォローして頂けると幸いです ^ ^。

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。