stash とは、「隠す」という意味。
作業中、まだコミットしていない状態で他のブランチで作業したいことがある。そういうとき、stash
を使えば変更内容を一時的に退避させることができる。
コマンド | 動作など |
---|---|
git stash | 作業ツリーとインデックスをスタックに隠す(Untracked filesは含まれない) |
git stash -u | Untracked filesも含め、スタックに隠す |
git stash apply (stash@{数字}) | スタックに格納したものを取り出す |
git stash pop (stash@{数字}) | スタックに格納したものを取り出してスタックから削除 |
git stash list | スタックのリストを表示 |
git stash drop (stash@{数字}) | スタックの中の一つを削除 |
git stash clear | スタックを空にする |
git stash branch ブランチ名 (stash@{数字}) | スタックに格納したものを取り出して新しいブランチを作る |
Untracked files とは、作成してから一度も add されていないファイル。(stash@{数字})は、省略すると一番新しいものが選択されたことになる。
実際にやってみる。Gitリポジトリを作って、hello.txt というファイルを作り、'A' と書き込む。
$ git init Initialized empty Git repository in /Users/略/stash/.git/ $ touch hello.txt $ echo 'A' > hello.txt
add して、 commit。
$ git add hello.txt $ git commit -m 'Initial commit' [master (root-commit) 72b74fb] Initial commit 1 file changed, 1 insertion(+) create mode 100644 hello.txt
新しく develop ブランチを切り、hello.txt に 'B' を追記。
$ git checkout -b develop Switched to a new branch 'develop' $ echo 'B' >> hello.txt
新しいファイル new.txt を作成。
$ touch new.txt $ git status On branch develop 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: hello.txt Untracked files: (use "git add <file>..." to include in what will be committed) new.txt no changes added to commit (use "git add" and/or "git commit -a")
変更が add されていない hello.txt と、Untracked files の new.txt がある状態。ここで、stash を実行。
$ git stash Saved working directory and index state WIP on develop: 72b74fb Initial commit $ git status On branch develop Untracked files: (use "git add <file>..." to include in what will be committed) new.txt nothing added to commit but untracked files present (use "git add" to track)
$ git stash
では Untracked files は隠されないので、new.txt は残ったままになった。これも隠したいので、-u
オプションをつけて実行。
$ git stash -u Saved working directory and index state WIP on develop: 72b74fb Initial commit $ git status On branch develop nothing to commit, working tree clean
作業ツリーがきれいになった。stash を2回やったので、リストはこうなっている。
$ git stash list stash@{0}: WIP on develop: 72b74fb Initial commit stash@{1}: WIP on develop: 72b74fb Initial commit
これをまた取り出すことは簡単だが、あえて違うブランチで取り出してみる。
新しく topic ブランチを切って、apply
で取り出す。
$ git checkout -b topic Switched to a new branch 'topic' $ git stash apply Already up to date! On branch topic Untracked files: (use "git add <file>..." to include in what will be committed) new.txt nothing added to commit but untracked files present (use "git add" to track)
これで、new.txt が戻ってきた。次に、最初に隠した hello.txt への追記の方を取り出す。
$ git stash apply stash@{1} On branch topic 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: hello.txt Untracked files: (use "git add <file>..." to include in what will be committed) new.txt no changes added to commit (use "git add" and/or "git commit -a")
これで元通りになった。
このように、スタックに格納したものは違うブランチから取り出すこともできる。ただしコンフリクトが発生すると取り出すことができない。コンフリクトが起きそうなときは、stash したものを別ブランチに切り出すとよいだろう。
stash はたくさんやるとわかりにくくなるため、できれば stash したら忘れないうちに pop して、リストがあまり増えないようにしたい。
(参考)