git stash blunder:git stash popとマージの競合が発生しました


200

私はやったgit stash popし、マージの競合に終わった。ファイルシステムからファイルを削除し、git checkout以下のように実行しましたが、ファイルはまだマージされていないと考えています。次に、ファイルを置き換えてgit checkout、同じ結果をもう一度試しました。イベントを-fフラグで強制してみました。何か助けていただければ幸いです!

chirag-patels-macbook-pro:haloror patelc75$ git status
app/views/layouts/_choose_patient.html.erb: needs merge
app/views/layouts/_links.html.erb: needs merge
# On branch prod-temp
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   db/schema.rb
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       unmerged:   app/views/layouts/_choose_patient.html.erb
#       unmerged:   app/views/layouts/_links.html.erb

chirag-patels-macbook-pro:haloror patelc75$ git checkout app/views/layouts/_choose_patient.html.erb
error: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
chirag-patels-macbook-pro:haloror patelc75$ git checkout -f app/views/layouts/_choose_patient.html.erb
warning: path 'app/views/layouts/_choose_patient.html.erb' is unmerged

注:作業ツリーをクリーンするgit stash apply/pop必要があるため、Git 2.5(2015年第2四半期)を使用すると、の状態簡単戻すことができます。以下の私の回答を
VonC

回答:


219

man git merge競合を解決する方法)を参照してください:

競合が発生した後、次の2つのことができます。

  • マージしないことを決定します。必要なクリーンアップは、インデックスファイルをHEADコミットにリセットして2を元に戻し、2と3によって行われた作業ツリーの変更をクリーンアップすることだけです。これにはgit-reset --hardを使用できます。

  • 競合を解決します。Gitは作業ツリーで競合をマークします。ファイルを整形してgitをインデックスに追加します。git commitを使用して契約を締結します。

そして、TRUE MERGEの下で(2.と3.が何を参照しているかを確認するため):

変更を調整する方法が明らかでない場合、次のことが起こります。

  1. HEADポインターは同じままです。

  2. MERGE_HEAD refは、他のブランチヘッドを指すように設定されています。

  3. きれいにマージされたパスは、インデックスファイルと作業ツリーの両方で更新されます。

  4. ...

そのgit reset --hardため、作業ツリーからstashの変更を削除するgit reset場合、またはインデックスをクリーンアップして競合を作業ツリーに残して手動でマージする場合に使用します。

man git stashOPTIONS、pop)の下でさらに読むことができます:

状態の適用は競合で失敗する可能性があります。この場合、スタッシュリストからは削除されません。競合を手動で解決し、後で手動でgit stash dropを呼び出す必要があります。


9
実際、スタッシュをドロップした後でも、変更セットがリポジトリにまだ存在しているため、スタッシュを再度取得することは可能です(ただし困難です)。stackoverflow.com/search?q=git+recover+dropped+stash
phils

3
@nalply:それは良いですか悪いですか?あなたは私の答えを改善することを歓迎しますが、最初はそれを理解していませんでした...
tanascius

1
ソースコードの改訂は複雑な問題領域だと思います。混乱するのは簡単です。それでも私のアプローチを再確認したので、あなたの答えは良いと思います。
nalply

1
スタッシュが思ったように取り外されていないことに気づくだけでなく、物を取り出すのを忘れていないのに確信していてもスタッシュが成長し続けたのはこのためです。
Thor84no

11
「状態の適用は競合で失敗する可能性があります。この場合、状態はスタッシュリストから削除されません。」私の意見では、これは投稿の最も重要な部分です。回答を編集して、大きくて親しみやすい文字の「DO N'T PANIC」という言葉とともに前に置くことを検討してください。(ただし、+ 1です。)ありがとうございます。
Patrick M

42

似たようなことが起こりました。まだファイルをステージングしたくなかったので、それらを追加してgit addから追加しましたgit reset。これは基本的に変更を追加してステージングを解除しましたが、マージされていないパスをクリアしました。


4
これはreset --hardファイルを上書きしないため、使用するよりも優れているようです(マージの問題があるファイルを除く)。ありがとう!
sinelaw

ファイルをまだステージングしたくなかったので、追加しました。addコンテンツを作業ツリーからインデックスにステージングしませんか?説明からあなたの答えが機能する理由が理解できないと思います。
Drew Noakes 2013

2
git addそれらをステージングしますがgit reset、私はすぐに行いますが、ステージングを解除します。基本的には、マージされていないパスをクリアし、gitを偽装することで通常の作業ツリーに戻ります。
アーロン

3
あなたgit addが行くつもりなら、あなたはする必要はありませんgit reset。はをgit reset効果的に「取り消し」ますgit addgit reset--mixed<-デフォルト)は実際には作業ディレクトリに影響を与えないので、作業ディレクトリにあったもの、マージの競合などすべてがそのまま残ります。インデックス(および技術的にはブランチヘッド)はリセットされます(参照がにリセットされHEADないため、ブランチヘッドに変更がないことを意味git addし、インデックスへの実行をすべて取り消し、マージされていないパスの状態をクリアします)。 。
バンバム2014

3
シーケンス編集/決意git resetそしてgit stash dropうまく動作します。それはgit stash pop衝突なしで何をしたかをします。git add必要ないようです。おそらく便利かもしれませんが、競合するファイルがたくさんあります。それぞれが解決されると、それらを追加しgit statusて追跡できます。
アートレスノイズ2014

13

私のように、通常は作業ディレクトリの内容をstashされたファイルの内容で上書きし、それでも競合が発生する場合git checkout --theirs -- .は、ルートから使用して競合を解決する必要があります。

その後git reset、明らかに競合が発生した場合に、競合していないファイルへの変更がインデックスに残るため、すべての変更をインデックスから作業ディレクトリに移動できます。

競合が発生した場合にgit stash drop [<stash name>]スタッシュをgit stash pop削除しないため、スタッシュを取り除くために、後で実行することもできます。


2

ご了承ください Git 2.5(2015年第2四半期) 将来のGitはそのシナリオを不可能にしようとするかもしれません。

参照ed178efをコミットすることにより、ジェフ・キングpeff)、4月22日2015年
(で合併Junio C浜野 - gitster中- 05c3967をコミット 2015年5月19、)

注:これは元に戻されました。以下を参照してください

stash:適用/ポップするにはクリーンなインデックスが必要です

問題

インデックスにコンテンツをステージングして「stash apply/pop」を実行すると、競合が発生し、新しいエントリがインデックスに挿入される場合があります。
「git reset --keep」などのツールはステージングされたものをすべて吹き飛ばすため、その時点では元の状態に復元することは困難です。

言い換えると:

" git stash pop/apply"作業ツリーだけでなく、インデックスもクリーンであることを確認するのを忘れていました。
stashアプリケーションは競合する可能性があり、インデックスは競合解決に使用されるため、後者は重要です。

解決

段階的な変更がある場合に適用を拒否することで、これをより安全にすることができます。

つまり、変更されたファイル(追加されたがコミットされていない)にstashを適用したために以前にマージがあった場合、stashの適用/ポップは次のようにすぐに停止するため、マージされません。

Cannot apply stash: Your index contains uncommitted changes.

変更をコミットすることを強制するということは、マージの場合、を使用して簡単に初期状態(before git stash apply/pop)を復元できることを意味しますgit reset --hard


コミット1937610(2015年6月15日)と、Jeff King()によるed178ef(2015年4月22日)のコミットを参照してください。(合併によりJunio C浜野- -コミットbfb539b、2015年6月24日)peff
gitster

アプリケーションプロセスは競合するインデックスエントリを作成する可能性があるため、元のインデックスの状態を復元するのが難しいため、そのコミットはstashの適用の安全性を向上させる試みでした。

残念ながら、これは " git stash -k"に関連するいくつかの一般的なワークフローに悪影響を及ぼします。

git add -p       ;# (1) stage set of proposed changes
git stash -k     ;# (2) get rid of everything else
make test        ;# (3) make sure proposal is reasonable
git stash apply  ;# (4) restore original working tree

手順(3)と(4)の間に「git commit」を実行すると、これは機能します。ただし、これらの手順がコミット前フックの一部である場合、その機会はありません(テストが成功したか失敗したかに関係なく、元の状態を復元する必要があります)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.