2017年06月29日

git 変更を一時的に退避 stash

git でチェックアウトすると作業ツリーが変更される。

機能追加を行うために、ブランチを切って、チェックアウトして作業していたら、
作業優先度が高いバグ修正を依頼された、という状況はよくある。
機能追加を行っていた作業は、まだ中途半端。一旦、コミットしても良いが、確実に不要となるコミットになってしまう。

このような場合どうするか?

力技でいくなら、機能追加で使っている作業ツリーとは別に、新たなリポジトリを作って別の作業ツリーを用意して、その場所でバグ修正を行うという手もある。
が、簡単な作業ですぐに割り込み作業が終わるなら大丈夫だろう。しかし、もし、いろいろと作業があり過ぎて、頭が朦朧とした状態になり、間違った作業ツリーを更新してしまうかもしれない。そうなると元に戻すのに無駄な時間と労力を使うことになるかもしれない。ヒューマンエラーの温床になるかもしれない。

せっかく git を使っているので、git の能力をもっと活用してスマートに対応したい。





現在の作業を一時的に退避


"new_branch" ブランチで作業していて、別の作業が発生した。
現在の作業(作業ツリーも、ステージングエリアも)を退避する。

$ git stash save

または、"save" を省略して

$ git stash

stashの目印としてメッセージを付与することも可能。

$ git stash save "message"

メッセージをつけておくことで作業を再開するときにわかりやすい。



statusを確認してみる。
$ git status
On branch new_branch
nothing to commit, working directory clean

作業ツリー上には、更新状態の差分が無い状態になった。

git_stash01.png





退避した内容を確認する


$ git stash list

stash@{0}: WIP on new_branch: 44470bb new_branch 追加2
stash@{1}: On new_branch: stash確認2
stash@{2}: On new_branch: stash確認

この場合、stash には3つの変更が保存されていることがわかる(上が新しい保存)。

stash操作時に、メッセージを付与しなかった場合は、
: WIP on <stashしたブランチ>: <親コミットのハッシュ> <コミットコメント> となり、
メッセージを付与した場合は、
: On <stashしたブランチ>: <メッセージ> となる。

変更が保存されていれば安心。他のブランチをチェックアウトして作業できる。




退避した作業を復元する


最新のstash(stash@{0})を復元するには、

$ git stash pop

$ git status
On branch new_branch
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)

modified: index.html

no changes added to commit (use "git add" and/or "git commit -a")

変更内容が復元できた。

stash のリストを確認すると、
$ git stash list
stash@{0}: On new_branch: stash確認2
stash@{1}: On new_branch: stash確認

3つあったリストが2つに減っている。


"git stash pop" を行うと、復元したstashは削除されることに注意。
git_stash02.png


最新(stash@{0})以外の内容を復元するには、stash名を指定する。

$ git stash pop stash@{1}




stashした中身を確認したいときなど、復元するが stash からは削除したくない(残しておきたい)ときには、"pop" の代わりに "apply" を使う。

$ git stash apply

最新(stash@{0})以外の場合は、同様にstash名を指定すればよい。

$ git stash apply stash@{1}







退避した内容を削除する


"git stash apply" は復元後に、stashに残ったままになる。
個別にstash内容を削除するには、"drop" を使う。

$ git stash drop stash@{1}

stash名を指定しなければ、最新(stash@{0})が削除される。

$ git stash drop



stashを全削除する場合は、

$ git stash clear



不要なstashを残したままにすると、どれが必要なものなのかわからなくなり、無駄な労力が発生するのでこまめに整理すること。






ステージングエリアの内容の復元について


ステージングエリアの内容を退避し、復元する場合、
"--index" オプションを指定しないとステージングエリアに復元されないことに注意。

$ git stash pop stash@{0} --index

※"pop" でも "apply" でも同じ。




ファイルを追加した場合の退避について


作業ツリー上でファイルを追加した状態の場合、このままstash しても追加ファイルはgit管理下ではなってないので、退避されないことに注意。
中途半端な状態でファイルが残ったままとなるので、以降の作業で邪魔になったり、退避したものだと勘違いし削除してしまうと復元ができない。

ファイルを追加した場合は、stash する前に、ステージングエリアに移動させて、git管理下に置いてから、stash すること。



または、"-u" オプションをつけると追跡していないファイルも退避してくれるので、
ステージエリアに移動させなくても、追加ファイルを stash できる。

$ git stash -u








違うブランチで間違って作業をしていたとき


作業をしていてコミットしようとしたら、違うブランチで作業していたことに気づいてしまったようなシチュエーションでも、stash は使える。
一旦、stash して、目的とするブランチへ切り替えてから復元する。
stash にはこのような使い方もできる。






まとめ


割り込み的な作業を行わず、集中して作業できると良いが、うまくいかないこともあるので、切り替えながら進めないといけないこともしばしば。そのような場合に、目の前の作業をきれいに切り替えることで、すっぱりと頭の切り替えにもなる stash は便利。git の便利な機能をうまく使って、ヒューマンエラーを起こさないように、効率よく作業を進めたい。


gitをインストール
gitサーバーのセットアップ
git ブランチについて
git ブランチを合流するマージ
git ブランチを付け替える
git コミット履歴を変更する
git コミットを取り消す
git 変更をリセットする
git リモートでの操作
git ファイルの追跡
git リリース準備
git リモートブランチを追加
git チェックアウトをもっと便利に使う
git プロジェクトの構成
git 変更をpatchファイルにする
git コンフリクトに対処する
git 失敗したときの復元
posted by Zorinos at 20:00| Comment(0) | Linux | 更新情報をチェックする
この記事へのコメント
コメントを書く
コチラをクリックしてください