web-dev-qa-db-ja.com

git stash blunder:git stashポップしてマージの競合が発生しました

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
197
Chirag Patel

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. ...

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

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

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

218
tanascius

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

41
Aaron

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

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

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

12
Pedro Gimeno

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

commit ed178ef by Jeff Kingpeff)、2015年4月22日を参照してください。
C浜野順夫 -gitster- commit 05c3967 、2015年5月19日)

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

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

問題

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

言い換えると:

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

溶液

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

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

Cannot apply stash: Your index contains uncommitted changes.

変更をコミットすることを強制すると、マージの場合、git stash apply/popで初期状態(git reset --hardの前)を簡単に復元できます。


commit 193761 (2015年6月15日)、および commit ed178ef (2015年4月22日)by Jeff King(peff を参照してください。
C浜野順夫-gitster- in commit bfb539b 、2015年6月24日)

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

残念ながら、これは次のような「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」を実行すると、これは機能します。ただし、これらの手順が事前コミットフックの一部である場合、その機会はありません(テストが成功したか失敗したかに関係なく、元の状態を復元する必要があります)。

2
VonC