Git am Fehler: "Patch gilt nicht"

75

Ich versuche, mehrere Commits mit git von einem Projekt zum zweiten zu verschieben, ähnlich einem.

Also habe ich einen Patch erstellt, der 5 Commits enthält:

git format-patch 4af51 --stdout > changes.patch

Verschieben Sie dann den Patch in den Ordner des zweiten Projekts und möchten Sie den Patch anwenden:

git am changes.patch 

... aber es gibt mir Fehler:

Applying: Fixed products ordering in order summary.
error: patch failed: index.php:17
error: index.php: patch does not apply
Patch failed at 0001 Fixed products ordering in order summary.
The copy of the patch that failed is found in:
   c:/.../project2/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

Also habe ich die index.php geöffnet, aber dort hat sich nichts geändert. Ich gehe von einigen >>>>>>>Markierungen usw. aus, beispielsweise bei der Lösung von Zusammenführungskonflikten, aber es wurde kein Konflikt in der Datei markiert. git statusgab mir auch eine leere Liste der geänderten Dateien (war nur changes.patchda). Also laufe ich git am --continue, aber ein anderer Fehler erscheint:

Applying: Fixed products ordering in order summary.
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort". 

Ich verwende Windows 7 und die neueste Git-Version "1.9.4.msysgit.1".

PS Nach ein paar Stunden googeln habe ich nur wenige Lösungen gefunden, aber für mich funktioniert nichts:


git am -3 changes.patch 

gibt einen seltsamen "sha1 information" -Fehler:

Applying: Fixed products ordering in order summary.
fatal: sha1 information is lacking or useless (index.php).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.
Patch failed at 0001 Fixed products ordering in order summary.
The copy of the patch that failed is found in:
   c:/.../project2/.git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort". 

git am changes.patch --ignore-whitespace --no-scissors --ignore-space-change

gibt den ersten Fehler wie oben aus: "Fehler: Patch fehlgeschlagen: index.php: 17", aber es wurden keine Konfliktmarkierungen index.phphinzugefügt.

nanuqcz
quelle
5
Ich habe auch damit zu kämpfen. In einigen Fällen wurde dies jedoch durch Dateien (z. B. Windows-Quellen) verursacht, die festgeschrieben wurden, während sich CRLF in Zeilenenden befand. Es scheint, dass git CRLF-Zeilenenden trotz einer Konfigurationsfunktion wie eol.crlf nicht mag. Beispiellink zu cr / lf-Problemen: stackoverflow.com/questions/1510798/…
Rob
1
Toll. Ich musste nur die Zeilenenden eines Patches, den ich erhalten hatte, in den "Unix" -Stil konvertieren und danach funktionierte es. Das verdient eine positive Bewertung.
user2808624

Antworten:

103

Was ist ein Patch?

Ein Patch ist kaum mehr (siehe unten) als eine Reihe von Anweisungen: "Hier hinzufügen", "Dort entfernen", "Dieses dritte Ding in ein viertes ändern". Das ist , warum git sagt Ihnen:

The copy of the patch that failed is found in:
c:/.../project2/.git/rebase-apply/patch

Sie können diesen Patch in Ihrem bevorzugten Viewer oder Editor öffnen, die zu ändernden Dateien in Ihrem bevorzugten Editor öffnen und den Patch von Hand anwenden, indem Sie das verwenden, was Sie wissen (und Git nicht), um herauszufinden, wie "hinzufügen" Dies hier ist zu tun, wenn die zu ändernden Dateien jetzt wenig oder gar nicht mehr so ​​aussehen wie zu dem Zeitpunkt, als sie zuvor geändert wurden. Diese Änderungen werden Ihnen als Patch übermittelt.

Ein bisschen mehr

Eine Drei-Wege-Zusammenführung führt diese "wenig mehr" Informationen als die einfache "Reihe von Anweisungen" ein: Sie zeigt Ihnen auch, wie die Originalversion der Datei war. Wenn Ihr Repository die Originalversion hat, kann Ihr Git vergleichen, was Sie mit einer Datei gemacht haben und was der Patch mit der Datei zu tun hat.

Wie Sie oben gesehen haben, kann git die "Originalversion" im anderen Repository nicht finden, wenn Sie die Drei-Wege-Zusammenführung anfordern, sodass es nicht einmal die Drei-Wege-Zusammenführung versuchen kann . Als Ergebnis erhalten Sie keine Konfliktmarkierungen, und Sie müssen die Patch-Anwendung von Hand ausführen.

Verwenden von --reject

Wenn Sie den Patch von Hand anwenden müssen, ist es immer noch möglich, dass git den größten Teil des Patches automatisch für Sie anwendet und der Entität nur wenige Teile überlässt, die über den Code nachdenken können (oder was auch immer gepatcht werden muss). . Das Hinzufügen --rejectweist git an, dies zu tun, und belässt die "nicht anwendbaren" Teile des Patches in Ablehnungsdateien. Wenn Sie diese Option verwenden, müssen Sie dennoch jeden fehlerhaften Patch von Hand anwenden und herausfinden, was mit den abgelehnten Teilen zu tun ist.

Sobald Sie die erforderlichen Änderungen vorgenommen haben, können Sie git adddie geänderten Dateien verwenden und git am --continuegit anweisen, die Änderungen zu übernehmen und mit dem nächsten Patch fortzufahren.

Was ist, wenn nichts zu tun ist?

Da wir Ihren Code nicht haben, kann ich nicht sagen, ob dies der Fall ist, aber manchmal landen Sie bei einem der Patches, auf denen Dinge stehen, die z. B. "die Schreibweise eines Wortes in Zeile 42 korrigieren". als die Schreibweise dort schon behoben war.

In diesem speziellen Fall sollten Sie sich, nachdem Sie sich den Patch und den aktuellen Code angesehen haben, sagen: "Aha, dieser Patch sollte einfach komplett übersprungen werden!" Dann verwenden Sie den anderen bereits gedruckten Ratgeber:

If you prefer to skip this patch, run "git am --skip" instead.

Wenn Sie ausführen git am --skip, überspringt git diesen Patch. Wenn also fünf Patches in der Mailbox vorhanden sind, werden nur vier Commits anstelle von fünf hinzugefügt (oder drei anstelle von fünf, wenn Sie zweimal überspringen, und so weiter).

torek
quelle
10
Vielen Dank für die tolle Antwort. Das git am changes.patch --rejectist das Beste für mich, weil es eine Alternative zu "Konfliktmarken" bietet (in .rej-Dateien enthalten). Dann git add, git am --continueund alles funktioniert :-)
nanuqcz
2
ja Dankeschön. Es war überraschend für mich , dass git amnicht (wie patch) versuchen , die Änderungen zu übernehmen , die sie anwenden.
Steven R. Loomis
Es scheint bizarr, dass Git manchmal nicht in der Lage ist, selbst erstellte Patches anzuwenden. Ich benutzegit log --pretty=email --patch-with-stat --reverse -- filename
Ed Randall
3
@EdRandall: Wenn Sie git amoder verwenden git apply -3 und die Basisversion der Datei in Ihrem Repository haben, sollte Git in der Lage sein, eine Drei-Wege-Zusammenführung durchzuführen (natürlich mit potenziellen Zusammenführungskonflikten). Beachten Sie, dass Sie möglicherweise die Person benötigen, die den Patch sendet, um ihn --full-indexbeim Generieren des Patches zu verwenden.
Torek
1
@DrumM: merge und rebase immer die Basisdatei haben, so dass sie nicht wirklich brauchen , um das Äquivalent von --rejectda sie das Äquivalent von immer haben -3. Trotzdem bin ich an den patchBefehl im GNU-Stil gewöhnt, daher bevorzuge ich normalerweise auch den --rejectModus, aber ich kann Argumente so oder so sehen.
Torek
4

git format-patchhat auch die -BFlagge.

Die Beschreibung in der Manpage lässt zu wünschen übrig, aber in einfacher Sprache ist es der Schwellenwert-Format-Patch, der eingehalten wird, bevor die Datei vollständig neu geschrieben wird (durch einmaliges Löschen von allem Alten, gefolgt von einmaligem Einfügen von alles neu).

Dies erwies sich für mich als sehr nützlich, wenn die manuelle Bearbeitung zu umständlich war und die Quelle maßgeblicher war als mein Ziel.

Ein Beispiel:

git format-patch -B10% --stdout my_tag_name > big_patch.patch
git am -3 -i < big_patch.patch
wulfgarpro
quelle
2

Ich hatte das gleiche Problem. Ich hatte benutzt

git format-patch <commit_hash>

um den Patch zu erstellen. Mein Hauptproblem war, dass der Patch aufgrund einiger Konflikte fehlschlug, aber ich konnte keinen Zusammenführungskonflikt im Dateiinhalt feststellen. Ich hatte git am --3way <patch_file_path>den Patch angewendet .

Der richtige Befehl zum Anwenden des Patches sollte lauten:

git am --3way --ignore-space-change <patch_file_path>

Wenn Sie den obigen Befehl zum Patchen ausführen, wird ein Zusammenführungskonflikt erstellt, wenn das Anwenden des Patches fehlschlägt. Dann können Sie den Konflikt in Ihren Dateien beheben, genauso wie Zusammenführungskonflikte für Git-Zusammenführung gelöst werden

srs
quelle
Der Parameter -3Wayist falsch, entweder -3oder --3way. Und das beantwortet die Frage nicht.
DrumM
1
Es ist ein Tippfehler im Codeabschnitt. Vielen Dank für den Hinweis. Wenn Sie der vollständigen Antwort gefolgt wären, hätten Sie vielleicht bemerkt, dass im Textabschnitt --3Way in Bold erwähnt wurde. Der Frage zufolge wurden nach dem Anwenden des Patches keine Zusammenführungskonflikte angezeigt. Ich hatte das gleiche Problem und habe es nur mit diesem Befehl gelöst.
srs
1) Sie platzieren --nach ...should be:, dies sieht bereits wie ein Tippfehler aus, ich lese leicht über --und lese die Codezeile unten. 2) Nur ärgerlich, dass Code-Antworten nicht die richtigen Antworten enthalten ;-) Es ist besser, nur den richtigen Code zu präsentieren. 3) Der Tippfehler in der ursprünglichen Frage verursachte sein Problem nicht ...
DrumM
2
Ich weiß nicht genau warum, aber die --ignore-space-changeOption hat meine Patch-Datei zum Laufen gebracht.
Himmel
0

Hatten sich mehrere Module über Patch beschwert, gilt das nicht. Eine Sache, die ich verpasste, war, dass die Zweige abgestanden waren. Nach dem git merge masterGenerieren der Patch-Dateien mit git diff master BRANCH > file.patch. Wenn man zum Vanillezweig ging, konnte man das Pflaster mit anwendengit apply file.patch

Sandeep KV
quelle
0

Ich hatte den gleichen Fehler. Ich habe die Commit-Version beim Erstellen des Patches zurückgesetzt. Es funktionierte, da der frühere Patch umgekehrt war.

[mrdubey @ SNF] $ git log 65f1d63 commit 65f1d6396315853f2b7070e0e6d99b116ba2b018 Autor: Dubey Mritunjaykumar

Datum: Di 22 Jan 12:10:50 2019 +0530

Commit e377ab50081e3a8515a75a3f757d7c5c98a975c6 Autor: Dubey Mritunjaykumar Datum: Montag, 21. Januar 23:05:48 2019 +0530

Früher verwendetes Kommad: git diff new_commit_id..prev_commit_id> 1 diff

Fehler: Patch fehlgeschlagen: Dateiname: 40

Arbeitsweise: git diff prev_commit_id..latest_commit_id> 1.diff

Mritunjay Kumar Dubey
quelle
0

Diese Art von Fehler kann durch Fehlanpassungen zwischen LF- und CRLF-Zeilenende verursacht werden, z. B. wenn Sie sich die Patch-Datei ansehen und absolut sicher sind, dass sie angewendet werden kann, dies jedoch nicht.

Um dies zu testen: Wenn Sie einen Patch haben, der nur für eine Datei gilt, können Sie versuchen, 'unix2dos' oder 'dos2unix' nur für diese Datei auszuführen (versuchen Sie beide, um festzustellen, welche die Datei ändert; Sie können diese erhalten Dienstprogramme für Windows sowie Unix), schreiben Sie diese Änderung als Test-Commit fest und versuchen Sie dann erneut, den Patch anzuwenden. Wenn das funktioniert, war das das Problem.

NB git amgilt Patches als LF standardmäßig (auch wenn der Patch - Datei enthält CRLF), wenn Sie also CRLF Patches anwenden möchten CRLF Dateien Sie müssen verwenden git am --keep-cr, wie pro diese Antwort .

MikeBeaton
quelle