NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

【Git】git stashで割り込みタスクにスマートに対応する

本記事は  【いまさら聞けない○○ウィーク~Git編~】  3日目の記事です。
🍦  2日目  ▶▶ 本記事 ▶▶  4日目  💻

こんにちは。 新卒2年目、駆け出しエンジニアの草野です。

今週のネットコムBlogのテーマが、「いまさら聞けない○○ウィーク~Git編~」ということで、
入社してからの1年間で何度も苦い経験をしたGitについて初執筆させていただきます。

今回はそんなGitの中で、私が大好きな機能のgit stashについて執筆したいと思います。

こういうことありませんか?

「ちょっと割り込みで、この対応見てくれない?」

業務の中で、いきなりこう言われることがよくあります。
ちょうど切りよくタスクが片付いたタイミングなら特に問題はありませんが、例えば何か重めの実装の最中。
割り込み対応のためにブランチを切り替えたいけど、こんな中途半端な実装をコミットしたくない……!
こういったことはよくあります。

また、Gitに慣れないうちにやりがちな、ブランチ間違え。
開発用のブランチを切って作業をしなくてはいけないのに、間違えてmasterブランチで開発を進めてしまった!

そんなときこそ、git stashの出番です!

git stashの使い方

git stashは、作業ブランチの内容を一時的に退避できるコマンドです。

作業を一時的に退避する

作業ブランチの中で、コミットしていないファイルを一時的に退避するには、下記コマンドを使用します。

$ git stash save

git stashは追跡しているファイルのみを退避対象とするため、新しく作成したファイルは退避対象から除外されます。
未追跡のファイルも退避対象としたい場合は、-uオプションを付けることで、退避対象に含めることができます。

$ git stash save -u

また、stashする内容にメッセージを付けることもできます。
作業内容などをメモしておくと、あとから見返したときにわかりやすくなります。

$ git stash save "メッセージ内容"


退避した作業の一覧を表示する

過去のgit stash saveした内容の一覧を表示するには、git stash listを使用します。

$ git stash list
stash@{0}: On master: stash test
stash@{1}: WIP on featureBranch: xxxxxxxxxx
stash@{2}: On featureBranch: xxxx作業中

git stash saveする際に、メッセージを付けなかった場合、stash@{1}のようにWIP on ブランチ名で表示され、
メッセージを付けた場合、stash@{0}stash@{2}のようにOn ブランチ名 メッセージで表示されます。
後述する一覧からの削除や、作業ブランチへの反映で各作業にアクセスする場合、stash@{n}でアクセス可能です。


退避した作業を一覧から削除する

git stash saveした内容はスタック形式で保存されていくため、不要な作業内容は削除が必要です。
特定の作業を削除する場合は、git stash dropを使用します。

$ git stash drop stash@{2}

git stash listの作業内容すべてを削除する場合は、git stash clearで全削除することができます。

$ git stash clear


退避した作業を反映する

退避した作業内容をブランチに反映する場合、git stash popを使用します。

$ git stash pop stash@{1}

git stash popを使用した場合、作業内容はブランチに反映後、stash listから削除されます。
作業内容をリストから削除したくない場合、git stash applyを使用します。

$ git stash apply stash@{1}


実際にgit stashを使ってみる

featureブランチで作業すべき内容を、誤ってmasterブランチで作業してしまったときを具体例として挙げてみます。

masterブランチにコミット前の未追跡ファイルtest.txtがある場合を想定します。

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

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

git stash save -uで作業内容を一時退避します。

$ git stash save -u "stash テスト"
Saved working directory and index state On master: stash テスト

git stash listで退避できたことを確認します。
また、git statusで未コミットのtest.txtが退避されたことを確認します。

$ git stash list
stash@{0}: On master: stash テスト
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working tree clean

featureブランチに切り替えます。

$ git checkout feature

git stash popもしくはgit stash applyfeatureブランチに作業内容を反映します。

$ git stash pop stash@{0}
Already up to date.
On branch feature/stash_test
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        test.txt

nothing added to commit but untracked files present (use "git add" to track)
Dropped stash@{0} (xxxxxxxxxxxxxxxxxxxxxxxxx)

これで、無事masterブランチで作業していたtest.txtを、featureブランチに反映することができました!

注意

git stashはとても便利な機能ですが、作業を制限なく退避できることから、リストの中身が煩雑になり、
目的の作業がどれかわからなくなるなどの問題が発生する可能性があります。
あくまで一時退避用の機能であることを念頭に置いて、コミットと使い分けるようにしましょう。

おわりに

git stashはpullやpushほどメジャーな機能ではないですが、使い勝手が良い機能だと思います。
学生時代はブランチを頻繁に切り替えることがなかったので知ることがなかった機能でしたが、社会人になってからは何度も助けられています。
これからも、git stashを上手く活用することで、快適なGit LIFEを過ごしたいと思います!

執筆者:草野理沙
Webアプリケーションエンジニア
緑が好き💚