少し追加の説明として、git stash2つのコミットまたは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 merge2を呼び出し(結果を通常のマージとしてコミットまたは処理することを許可せずに)、スタッシュが作成された元のコミット(iの親、およびw最初の親)をマージベースwとして使用します。--theirscommit、および現在の(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