web-dev-qa-db-ja.com

`git stash -p`が失敗することがあるのはなぜですか?

私♥git stash -p。しかし、時々、yn、およびsの満足のいくセッションの後、私はこれを取得します:

Saved working directory and index state WIP on foo: 9794c1a lorum ipsum
error: patch failed: spec/models/thing_spec.rb:65
error: spec/models/thing_spec.rb: patch does not apply
Cannot remove worktree changes

どうして?

73
John Bachir

_git stash -p_はGit 2.17(2018年第2四半期)で失敗が少なくなるはずです。
それ以前は、「_git add -p_」(_git stash_とロジックを共有)は、結果を基になる「_git apply_」に渡す前に、分割パッチの合体に怠惰でした。ケースバグ;ハンクの選択が厳しくなった後に適用されるパッチを準備するロジック。

commit 3a8522fcommit b3e0fcfcommit 2b8ea7f (05 Mar 2018)、 commit fecc6fcommit 23fea4ccommit 902f414 (01 Mar 2018)、および commit 11489a6commit e4d671ccommit 492e60c =(2018年2月19日)by Phillip Wood(phillipwood
(合併 濱野純雄--gitster- in commit 436d18f 、2018年3月14日)

_add -p_:スキップされたときの後続のハンクのオフセットを調整します

(追加しますが、ここでも、スタッシュに適用できます)

commit 8cbd431 ( "_git-add--interactive_:ハンクの再カウントをapply --recountに置き換える"、2008-7-2、Git v1.6.0-rc0)なので、ハンクがスキップされた場合は、後続のハンクを適切な場所に適用するためのコンテキスト行。

これはほとんどの場合機能しますが、ハンクが間違った場所に適用される可能性があります。

これを修正するには、後続のハンクのオフセットを調整して、スキップされたハンクによる挿入または削除の数の変化を修正します。挿入または削除の数が変更された編集済みハンクによるオフセットの変更は、ここでは無視され、次のコミットで修正されます。

あなたは見ることができます ここにいくつかのテスト


Git 2.19は_git add -p_を改善します:ユーザーが「_git add -p_」でパッチを編集し、ユーザーのエディターが末尾の空白を無差別に削除するように設定されている場合、パッチで変更されていない空の行は(代わりに)完全に空になりますソールがSP)の行。
Git 2.17のタイムフレームで導入されたコードは、そのようなパッチの解析に失敗しましたが、今では状況に気づき、それに対処することを学びました。

commit f4d35a6 (11 Jun 2018)by Phillip Wood(phillipwood を参照してください。
(合併 Junio C Hamano --gitster- in commit 5eb8da8 、28 Jun 2018)

_add -p_:編集されたパッチの空のコンテキスト行のカウントを修正

recount_edited_hunk()で導入 commit 2b8ea7f ( "add -p:編集されたパッチのオフセットデルタを計算する"、2018-03-05、Git v2.17.0)では、すべてのコンテキスト行がで始まる必要がありましたスペース、空の行はカウントされません。
これは、ユーザーがパッチの編集時に最後に空の行を導入した場合の再カウントの問題を回避することを目的としています。

ただし、パッチを編集するときに編集者が空のコンテキスト行から末尾の空白を削除して、カウントする必要のある空の行を導入するのが一般的であると思われるため、これにより '_git add -p_'に回帰が導入されました。
'git apply'はそのような空の行を処理する方法を知っており、POSIXは、空のコンテキスト行にスペースがあるかどうかは実装定義であると述べています( diffコマンド を参照)。

改行のみで構成される行と、スペースで始まる行をコンテキスト行としてカウントすることで回帰を修正し、将来の回帰を防ぐためのテストを追加します。


Git 2.23(Q3 2019)は、「_git add -p_」で使用される_git checkout -p_を改善します。これは、パッチを逆に選択的に適用する必要があります。以前はうまく機能しませんでした。

commit 2bd69b9 (12 Jun 2019)by Phillip Wood(phillipwood を参照してください。
(Merged by Junio C Hamano --gitster- in commit 1b074e1 、09 Jul 2019)

_add -p_:病理学的コンテキストで_checkout -p_を修正

コミット fecc6f ( "_add -p_:スキップされたときに後続のハンクのオフセットを調整する"、2018-03-01、Git v2.17.0-rc0)次の場合に正しい場所にハンクを追加する問題を修正以前のハンクはスキップされました。

ただし、逆に適用されるパッチには対応していません。

その場合、パッチを逆に適用したときにポストイメージオフセットが正しく調整されるように、プレイメージオフセットを調整する必要があります。
パッチが逆になっているため、デルタを加算するのではなく減算します(最も簡単な方法は、スキップされた削除の塊を検討することです。その場合、オフセットを減らしたいので、減算する必要があります) 。

6
VonC

これは、ハンクを互いに近すぎる(変更間の3行未満)小さなハンクに分割しようとするたびに発生します。簡単に説明すると、パッチには、ローカルの変更と競合するコンテキスト行が含まれています。以下のより完全な説明。


これらのコミットされていない変更を含むgitリポジトリがあるとします。

--- a/pangram
+++ b/pangram
@@ -1,8 +1,8 @@
 The
-quick
+relatively quick
 brown
 fox
-jumps
+walks
 over
 the
 lazy

最初の変更を隠しておくと、次のようになります。

--- a/pangram
+++ b/pangram
@@ -1,5 +1,5 @@
 The
-quick
+relatively quick
 brown
 fox
 jumps

git stashコマンドは実際にはパッチの保存に成功しますが(git stash listを確認)、gitはそのパッチを逆に使用して、隠された変更を作業ディレクトリから削除します。ハンクの後のコンテキストには「ジャンプ」がありますが、これはまだ私の作業ディレクトリにある「ウォーク」と一致しません。だからgitは

エラー:パッチが失敗しました:パングラム:1 
エラー:パングラム:パッチが適用されません
ワークツリーの変更を削除できません

そして、私の作業ディレクトリにすべての変更を残し、隠し場所はほとんど価値がなくなります。


私はこれをgitのハンク分割サポートのバグと呼んでいます。変更の分割が近すぎることがわかっている場合は、パッチから数行のコンテキストを削除するか、パッチをジミーして、元のコンテキスト行ではなく変更されたコンテキスト行を使用することができます。あるいは、このクローズのハンクの分割が公式にサポートされていない場合、実際には、このクローズのハンクの分割を拒否する必要があります。

27
Mu Mind

同じようにgit stash -pが失敗した後、この回避策(git 2.0.2)で運が良かった:

  • git add -p、まったく同じハンクを分割しますが、逆の答えを使用します( "y"からadd "は変更を保持し、" n "からstashは変更を保持します)。
  • git stash -kインデックスを保持し、他のすべてを隠します
  • git resetファイルの作業を続行するには

git add -pgit stash -pと同じように失敗しなかった理由がわかりません。追加はパッチファイルを作成するのではなく、インデックスで機能するためだと思いますか?

6
Johann

残念ながら、現時点で受け入れられている回答は、Git2.17でも失敗する可能性があります。

私のように、完璧な隠し場所を構築するために多くの努力を費やし、その努力を捨てたくない場合でも、ほとんどの場合、必要なものを手に入れることができます。

git stash show -p | patch -p1 -R

これは拒否で失敗しますが、ほとんどのハンクが正しく適用され、少なくともすべてのファイルを再度確認する時間を節約できる可能性があります。

4