これはすでに回答されているようですが、もう少し追加させてください。警告: にバグレットがありgit stash
ます。
git stash
を使用せずにor git stash save
(デフォルトではsave
これらは同じものです) を実行する-p
と、stash
スクリプトはgit-core
ディレクトリに存在し、その場所は git のインストールによって異なり/usr/libexec/git-core
ます/usr/local/libexec/git-core
。または場合によっては 3) 親コミット。順番に、これらのコミットは次のとおりです。
- 現在のインデックス
-u
または、追跡されて-a
いないファイル、さらには無視されたファイル(およびgit clean
作業ディレクトリからそれらを捨てるためにも使用されます)
- 現在の作業ディレクトリと
HEAD
コミットの間の差分に基づく作業ディレクトリ (これがバグレットのソースです。以下を参照してください)。
refs/stash
次に、これらのコミットの最後の作業ディレクトリ コミットを指すように設定します。このコミットの親は次のとおりです。
stash^
(最初の親)としての HEAD コミット
stash^2
(2 番目の親)としてのインデックス コミット
- 未追跡/無視されたコミット
stash^3
(存在する場合) (3 番目の親)。
このスタッシュには、実際には、スタッシュ時に配置されていたすべてが含まれていますが、「スタッシュ前の状態」を使用git stash pop --index
または復元する場合に、バグレットが最もよく表示されます。git stash apply --index
(git stash apply
以下でpop
は のみを使用しますが、apply
その後に . が続きdrop
ます。)
さて、あなたが指摘したように、実行する前にいくつかのことを慎重にステージングしたとしても、git stash apply
実行すると多くのファイルが得られます。これは、別のブランチなどをチェックアウトした場合や、実行前にいくつかのファイルをステージングした場合など、作業ディレクトリの状態に関係なく、このようにこれらの変更をマージする方がはるかに簡単だからです。(実際には、git のマージ コードを使用して作業ディレクトリの変更を取り込みます。)changes not staged for commit
git stash save
git stash apply
git stash apply
git stash apply --index
ただし、を実行するとstash
、スクリプトは最初に、元の. (まだ何もステージングされていない場合は、元の状態に戻ります。) それができると仮定して、同様に (再びマージ メカニズムを使用して) 作業ディレクトリを設定しようとします。インデックスを適切に設定できない場合は、インデックスに対して何もせず、 なしで再試行することを提案します。save
--index
ここで、バグレットの出番です。たとえば、basefile
何も変更していない というファイルから始めるとします。変更を加えて、これをステージングします。
$ cat basefile
base
$ git status --short
$ echo add to basefile >> basefile; git add basefile
しかし、作業ディレクトリのコピーにHEAD
リビジョンからの変更を加えないようにすることにしました。
$ ed basefile
21
2d
w
5
q
$ git status --short
MM basefile
ここで注意が必要な点は、インデックスで変更され、次に work-dir で再度変更されることですが、2 回目の変更でコミットbasefile
の内容に戻ります。HEAD
を実行するgit stash save
と、stash スクリプトは誤ってインデックスバージョンを進行中のバージョンであるかのように記録します。
ここで agit stash apply --index
を実行すると、次のようになりますgit status --short
。
$ git stash save
Saved working directory and index state WIP on master: 94824e1 initial
HEAD is now at 94824e1 initial
stash created
$ git stash apply --index
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: basefile
#
$ git status --short
M basefile
ここで、git はインデックスのバージョンをインデックスに復元し、作業ディレクトリのバージョンをインデックスのバージョンと同じものに設定しています。
$ cat basefile
base
add to basefile
stash スクリプトの修正は一言だけの変更ですが、今のところ誰も気に入っていないようです。おそらく問題は、stashを なし --index
で適用すると、インデックスの変更 (余分な行add to basefile
) が何もないものと効果的に結合されるため、work-directory バージョンに余分な行が含まれることです。ただし、インデックスと作業ディレクトリの両方のバージョンが異なる場合の動作とは一致しません。
$ git stash drop
Dropped refs/stash@{0} (61c83c866bc522c58df62320b77e647ffd28aa95)
$ echo base > basefile
$ git status --short
$ echo add to basefile >> basefile
$ git add basefile
$ ed basefile
21
2c
different change
w
22
q
$ git status --short
MM basefile
$ git stash save
Saved working directory and index state WIP on master: 94824e1 initial
HEAD is now at 94824e1 initial
$ git stash apply
# 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: basefile
#
no changes added to commit (use "git add" and/or "git commit -a")
$ cat basefile
base
different change
ここでは、インデックスとワーク ツリーの変更を「一緒につぶす」ことによって変更しますが、適用せずに適用すると、ワーク ツリーの変更のみ--index
が回復されます。
(幸いなことに、apply
代わりにpop
を使用しているので、ここで考えを変えることができます:
$ git reset --hard HEAD
HEAD is now at 94824e1 initial
$ git stash apply -q --index
$ git status --short
MM basefile
index と work-dir のバージョンを見ると、 の両方のバージョンが表示されますbasefile
。)
(stash スクリプトの修正は、次の行を次のように変更HEAD
することです。$i_tree
git diff --name-only -z HEAD -- >"$TMP-stagenames" &&
118 行目あたり。これを git メーリング リストに投稿したところ、... コオロギが出てきました。:-) )