[解決済み] git stash pop で stash エントリから未追跡のファイルを復元できなかったと表示されるのはなぜですか?
質問
ステージングとアンステージの変更が大量にあり、素早く別のブランチに切り替えてから戻したいと思っていました。
というわけで、私の変更をステージングしてみました。
$ git stash push -a
(今にして思えば、おそらく
--include-untracked
の代わりに
--all
)
そして、スタッシュをポップしようとすると、以下のようなエラーが大量に発生します。
$ git stash pop
foo.txt already exists, no checkout
bar.txt already exists, no checkout
...
Could not restore untracked files from stash entry
隠し場所から復元された変更点はないようです。
また、試しに
$ git stash branch temp
が、同じエラーが表示されます。
私はこれを回避する方法を考え出しました。
$ git stash show -p | git apply
とりあえず災害は回避されましたが、これにはいくつかの疑問が残ります。
なぜこのようなエラーが発生したのか、次回からどのように回避すればよいのか。
解決方法は?
少し補足説明として、以下のことに注意してください。
git stash
は、2つのコミット、または3つのコミットを作成します。 デフォルトは2回で、3回になるのは
--all
または
--include-untracked
オプションを使用します。
この2つ、あるいは3つのコミットは、ある重要な点において特別です。
いいえ
ブランチです。 Git はこれらのブランチを、特別な名前
stash
.
1
しかし、最も重要なことは、Git があなたに何をさせるかということです。
作る
この2~3回のコミットで、あなたは何をするのでしょうか。 これを理解するためには、これらのコミットの中身を見る必要があります。
スタッシュの中身
すべてのコミットには、1つまたは複数の
親
コミットです。 これらはグラフを形成し、後のコミットが前のコミットを指し示すことになります。 通常、隠し場所には二つのコミットがあります。
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
's
サード
の親がこの
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
コミットします。
stashに2つのコミットしかない場合。
git stash apply
を適用できるようになりました。
w
コミットします。 これを行うには
git merge
2
(をコミットしたり通常のマージと同じように扱ったりすることなく)、スタッシュが作成された元のコミット (
i
の親であり
w
の最初の親)をマージベースとする。
w
を
--theirs
コミット、そして現在の (HEAD) コミットをマージのターゲットとします。 マージが成功すれば万事解決です。まあ、少なくとも
ギット
はそう考えており
git stash apply
は成功します。 もしあなたが
git stash pop
を適用すると、今のコードは
ドロップ
を表示します。
3
マージに失敗した場合、Git は適用に失敗したことを宣言します。 もし
git stash pop
の場合と同じように、コードは隠し場所を保持し、失敗のステータスを提供します。
git stash apply
.
しかし、もしあなたがその
サード
コミット - もし
u
を適用すると、状況が一変します。
を無視するオプションはありません。
u
コミットは存在しません。
4
Git はすべてのファイルの抽出を主張する
から
その
u
を現在のワークツリーにコミットします。 これは、ファイルがまったく存在しないか、あるいは
u
コミットします。
それを実現するために
git clean
しかし、追跡されていないファイル (無視されているかどうかに関わらず) は Git リポジトリ内では他に存在しないので、これらのファイルがすべて破棄されることを確認してください! あるいは、一時ディレクトリを作ってそこにファイルを移動し、安全に保管することもできます。
git stash save -u
または
git stash save -a
を実行することになるので
git clean
を使用します。 しかし、これではもう1つの
u
-スタイルの隠し場所を後で処理する必要があります。
1
これは、実際には
refs/stash
. という名前のブランチを作成する場合、これは重要です。
stash
というブランチの場合、ブランチのフルネームは
refs/heads/stash
ということで、これらは矛盾しません。 でも、そんなことはしないでください。
ギット
は気にしないでしょうが、自分自身を混乱させることになります :-)
2
は
git 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 pop の取り消し
-
[解決済み】Gitのエラー。リモートリポジトリへの接続時に「Host Key Verification Failed」。
-
[解決済み] SourceTree error:1407742E:SSLルーチン:SSL23_GET_SERVER_HELLO:tlsv1警告プロトコルバージョン
-
[解決済み] GitBash | origin master - rejected (fetch first) | GitHub リポジトリにファイルがない。
-
[解決済み] Gitのフォルダ構造で変更・追加されたファイルのみをエクスポートする機能
-
[解決済み] 現在のGit作業ツリーからローカル(未追跡)ファイルを削除する方法
-
[解決済み] Gitで変更された複数のファイルのうち、1つのファイルだけを隠す?
-
[解決済み] 既にディスクから削除された複数のファイルを Git リポジトリから削除する
-
[解決済み] ローカルのGitの変更を削除するさまざまな方法
-
[解決済み] 現在のブランチにコミットされていない変更がある場合、別のブランチをチェックアウトする
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 現在のブランチのトラッキング情報がありません。
-
[解決済み】gitがローカルバージョンをリモートバージョンに置き換える
-
[解決済み】git rev-parseは何をするのですか?
-
git commit リモートエラー [rejected] master -> master (フェッチファースト)
-
[解決済み] GitHubに空のブランチを作成する
-
[解決済み] git stashを元に戻す
-
[解決済み] fatal: EOF が早い fatal: インデックスパックが失敗した
-
[解決済み] Gitのフォルダ構造で変更・追加されたファイルのみをエクスポートする機能
-
[解決済み】git stashで追加されたファイルを強制的に上書きする方法
-
[解決済み】3ウェイマージの方が2ウェイマージより有利なのはなぜですか?