少し追加の説明として、git stash
2つのコミットまたは3つのコミットのいずれかを行うことに注意してください。デフォルトは2です。--all
または--include-untracked
オプションのスペルを使用すると、3つになります。
これらの2つまたは3つのコミットは、1つの重要な点で特別です。つまり、ブランチ上にありません。Gitは特別な名前でそれらを見つけますstash
。1 最も重要なことは、しかし、Gitはあなたを-とすることができます何になり、これらの二、三コミットしてあなたが-行います。これを理解するには、これらのコミットの内容を確認する必要があります。
隠し場所の中身
すべてのコミットは、1つ以上の親コミットをリストできます。これらはグラフを形成し、後のコミットは前のコミットを指し示します。スタッシュは通常2つのコミットを保持します。これi
は、インデックス/ステージング領域のコンテンツとw
ワークツリーのコンテンツに対して呼び出すのが好きです。各コミットはスナップショットを保持することにも注意してください。通常のコミットでは、このスナップショットはインデックス/ステージング領域のコンテンツから作成されます。したがって、i
コミットは実際には完全に正常なコミットです。それはどのブランチにもありません:
...--o--o--o <-- branch (HEAD)
|
i
通常の隠し場所を作成している場合、git stash
コードはw
追跡されたすべての作業ツリーファイルを(一時的な補助インデックスに)コピーすることで作成します。Gitは、このw
コミットの最初の親がコミットを指すHEAD
ように設定し、2番目の親がコミットを指すように設定しi
ます。最後に、stash
このw
コミットを指すように設定します。
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
--include-untracked
またはを追加すると--all
、Gitはu
作成i
とw
。の間に追加のコミットを作成します。のスナップショットの内容u
は、追跡されていないが無視されていない--include-untracked
ファイル()、または無視されても追跡されていないファイル(--all
)です。これは、余分なu
コミットがありません何の親を、その後、ときgit stash
になりw
、それはセットw
の第三これに親をu
あなたが得るように、コミット:
...--o--o--o <-- branch (HEAD)
|\
i-w <-- stash
/
u
また、Gitは、この時点で、コミットで終了したすべてのワークツリーファイルを削除しますu
(これを使用git clean
して)。
隠し場所の復元
隠し場所を復元するときは、--index
使用するか使用しないかを選択できます。これは、現在のインデックスの変更を試みるためにコミットを使用する必要があることをgit stash apply
(または内部で使用するコマンドapply
などpop
)に通知します。この変更は次の方法で行われます。i
git diff <hash-of-i> <hash-of-i's-parent> | git apply --index
(多かれ少なかれ、ここでは基本的な考え方の邪魔になる細かい詳細がたくさんあります)。
を省略する--index
とgit stash apply
、i
コミットは完全に無視されます。
スタッシュにコミットが2つしかない場合はgit stash apply
、w
コミットを適用できるようになりました。これを行うには、git merge
2を呼び出し(結果を通常のマージとしてコミットまたは処理することを許可せずに)、スタッシュが作成された元のコミット(i
の親、およびw
最初の親)をマージベースw
として使用します。--theirs
commit、および現在の(HEAD)コミットをマージのターゲットとして使用します。マージが成功した場合、すべてが良好であり(少なくとも、Gitはそう考えていgit stash apply
ます)、それ自体が成功します。以前git stash pop
はスタッシュを適用していた場合、コードはスタッシュを削除するようになりました。3 マージが失敗した場合、Gitは適用が失敗したと宣言します。使用した場合git stash pop
、コードはスタッシュを保持し、と同じ障害ステータスを提供しgit stash apply
ます。
しかし、その3番目のコミットがある場合(u
適用しているスタッシュにコミットがある場合)、状況は変わります。 コミットが存在しないふりをするオプションはありu
ません。4 Gitは、そのu
コミットから現在のワークツリーにすべてのファイルを抽出することを主張します。つまり、ファイルはまったく存在しないか、u
コミットと同じ内容である必要があります。
これを実現するには、git clean
自分で使用できますが、追跡されていないファイル(無視されているかどうかに関係なく)はGitリポジトリ内に他に存在しないため、これらのファイルをすべて破棄できることを確認してください。または、一時ディレクトリを作成し、そこにファイルを移動して保管することも、別のgit stash save -u
またはgit stash save -a
を実行git clean
することもできます。しかし、それu
は後で対処するための別のスタイルの隠し場所をあなたに残すだけです。
1これは実際refs/stash
です。これstash
はrefs/heads/stash
、:という名前のブランチを作成する場合に重要です。ブランチのフルネームは、であるため、これらは競合しません。しかし、そうしないでください。Gitは気にしませんが、混乱するでしょう。:-)
2git stash
のコードは、実際に使用していますgit merge-recursive
直接ここに。これは複数の理由で必要であり、競合を解決してコミットするときにGitがマージとして扱わないようにするという副作用もあります。
3これがgit stash pop
、を優先して、を回避することをお勧めする理由ですgit stash apply
。適用されたものを確認し、実際に正しく適用されたかどうかを判断する機会があります。そうでない場合でも、あなたはまだあなたの隠し場所を持っています、それはあなたがgit stash branch
すべてを完全に回復するために使うことができることを意味します。まあ、その厄介なu
コミットの欠如を想定しています。
4本当にあるべきです:git stash apply --skip-untracked
または何か。また、これらすべてのu
コミットファイルを新しいディレクトリにドロップすることを意味するバリアントもあるはずgit stash apply --untracked-into <dir>
です。
git stash show -p | git apply --3