Wie erstelle ich einen Git-Patch für ein bestimmtes Commit?

1232

Ich muss ein Skript schreiben, das Patches für eine Liste von SHA1-Commit-Nummern erstellt.

Ich habe versucht, zu verwenden git format-patch <the SHA1>, aber das erzeugte einen Patch für jedes Commit seit diesem SHA1. Nachdem ein paar hundert Patches generiert wurden, musste ich den Prozess abbrechen.

Gibt es eine Möglichkeit, einen Patch nur für den spezifischen SHA1 zu generieren?

elle
quelle

Antworten:

1989

Versuchen:

git format-patch -1 <sha>

oder

git format-patch -1 HEAD

Gemäß dem obigen Dokumentationslink -1teilt das Flag git mit, wie viele Commits im Patch enthalten sein sollen.

- <n>

     Bereiten Sie Patches aus den obersten Commits vor.


Wenden Sie den Patch mit dem folgenden Befehl an:

git am < file.patch
Manojlds
quelle
210
Anwenden des Patches: git apply --stat file.patch# show stats. git apply --check file.patch# Vor der Bewerbung auf Fehler prüfen. git am < file.patch# wende den Patch endlich an.
Adrian
3
Es scheint nicht zu funktionieren, wenn das letzte Commit eine Zusammenführung aus einem anderen Zweig ist.
Lex Li
2
So wenden Sie den Patch auf Dateien mit CRLF-Zeilenenden an:git am --keep-cr < mypatch.patch
Michael Schmeißer
40
Verwenden Sie git am -3 < file.patchanwenden mit einem Drei-Wege - Merge , die Sie Konflikte mit lösen lassen git mergetooldanach (oder Bearbeitung manuell) finden Sie hier .
Matt
6
Dieser Befehl funktioniert auch nur für eine bestimmte Datei aus dem Commit: git format-patch -1 <sha> path/to/file.jsDadurch wird ein Patch erstellt, der nur die Unterschiede für die Datei enthält. Js
Kristóf Dombi
281

Zum Generieren der Patches aus den obersten Commits aus einem bestimmten sha1-Hash:

git format-patch -<n> <SHA1>

Die letzten 10 Patches von head in einer einzelnen Patch-Datei:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch
Sriram Murali
quelle
2
Können
1
git format-patch -1 HEADwird Patch für das letzte Commit generieren
Sriram Murali
1
Verzeihen Sie mir, dass ich Sie darum gebeten habe. Wenn es also -2Patches für die letzten 2 Commits generiert, ist es das, und eine weitere Sache zur Verdeutlichung ist, dass der Befehl der got format-patch -2 HEADgleiche ist wie die Zeilegit format-patch HEAD~2
Kasun Siyambalapitiya
85

Angenommen, Sie haben Commit-ID 2 nach Commit 1, die Sie ausführen können:

git diff 2 1 > mypatch.diff

wobei 2 und 1 SHA-Hashes sind.

Brandon
quelle
Danke dookehster für die Antwort. Das heißt, ich brauche das Skript, um die Commits zu finden, die denen vorausgehen, an denen ich interessiert bin. Ich hatte gehofft, dass ich das vermeiden kann.
Elle
11
@elle, nein, du nicht - git diff hash^ hash. Das "Hash ^" gibt das vorhergehende Commit an. (aber natürlich ist die Antwort von manojlds besser)
J-16 SDiZ
2
git show HEAD > mypatch.diffwährend Sie auf dem Commit sind, sollten Sie das gleiche tun.
Andho
1
@dookehester ist es richtig oder ist es umgekehrt,git diff 1 2
Kasun Siyambalapitiya
1
Dadurch werden keine Binärdateien in das Diff aufgenommen.
Stuckj
55

Dieser Befehl (wie bereits von @ Naftuli Tzvi Kay vorgeschlagen ):

git format-patch -1 HEAD

Durch einen HEADbestimmten Hash oder Bereich ersetzen .

generiert die Patch-Datei für das neueste Commit, das so formatiert ist, dass es dem UNIX-Postfachformat ähnelt.

-<n> - Bereiten Sie Patches aus den obersten Commits vor.

Anschließend können Sie die Patch-Datei in einem Postfachformat erneut anwenden, indem Sie:

git am -3k 001*.patch

Siehe : man git-format-patch.

Kenorb
quelle
Vielen Dank! Ich denke, es ist erwähnenswert, dass durch das Anwenden des Patches ein Commit mit einer Commit-Nachricht mit dem Präfix [PATCH] erstellt wird. Das ist allerdings leicht zu beheben
Mike S
2
Phänomenal. OP, Sie haben das nicht akzeptiert, weil ...? @MikeS Nein, nicht mehr als jeder andere gitformatierte Patch, zumindest wenn der Benutzer ihn richtig anwendet.
underscore_d
2
@MikeS Ich habe nicht wirklich untersucht, warum, aber das Weglassen der -kFlagge ( git am -3) hat dieses Formular für mich behoben (keine PATCH[0/10]Festschreibungsnachrichten). Git Version 2.20.1.windows.1
jannis
30
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

Schnelle und einfache Lösung.

zdrsoft
quelle
5
Vergessen Sie auch nicht anzurufen, git apply --check patch-file-namebevor Sie einen Patch anwenden. Dies hilft, Probleme zu vermeiden.
iamantony
16

Wenn Sie sicherstellen möchten, dass der Patch (Single Commit) zusätzlich zu einem bestimmten Commit angewendet wird, können Sie die neue Option git 2.9 (Juni 2016) verwenden git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

Siehe Commit bb52995 , Commit 3de6651 , Commit fa2ab86 , Commit ded2c09 (26. April 2016) von Xiaolong Ye (``) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 72ce3ff , 23. Mai 2016)

format-patch: --baseOption ' ' hinzufügen, um Basisbauminformationen aufzuzeichnen

Maintainer oder Tester von Drittanbietern möchten möglicherweise den genauen Basisbaum kennen, für den die Patch-Serie gilt. Bringen Sie git format-patch eine ' --base' Option bei, um die Basisbauminformationen aufzuzeichnen und am Ende der ersten Nachricht anzuhängen (entweder das Anschreiben oder den ersten Patch in der Serie).

Die Basisbauminformationen bestehen aus dem "Basis-Commit", einem bekannten Commit, das Teil des stabilen Teils der Projekthistorie ist, an dem alle anderen arbeiten, und null oder mehr "vorausgesetzten Patches", die bekannt sind Patches im Flug, die noch nicht Teil des "Basis-Commits" sind und in topologischer Reihenfolge auf "Basis-Commit" angewendet werden müssen, bevor die Patches angewendet werden können.

Das "Basis-Commit" wird als " base-commit:" gefolgt vom 40-Hex des Commit-Objektnamens angezeigt .
Ein "vorausgesetzter Patch" wird als " prerequisite-patch-id:" angezeigt, gefolgt von der 40-hexadezimalen "Patch-ID", die Sie erhalten, indem Sie den Patch über den git patch-id --stableBefehl " " übergeben.


Git 2.23 (Q3 2019) wird dies verbessern, da die --baseOption " " von " format-patch" die patch-idserforderlichen Patches auf instabile Weise berechnet hat, die aktualisiert wurde, um auf eine Weise zu berechnen, die mit " git patch-id --stable" kompatibel ist .

Siehe Commit a8f6855 , Commit 6f93d26 (26. April 2019) von Stephen Boyd ( akshayka) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 8202d12 , 13. Juni 2019)

format-patch: --base patch-idAusgabe stabil machen

Wir haben den Kontext nicht jedes Mal geleert , wenn wir einen Teil des patch-idGenerierungscodes in verarbeitet haben diff.c, aber wir haben dies getan, als wir mit dem patch-idTool ' ' "stabile" Patch-IDs generiert haben .

Lassen Sie uns diese ähnliche Logik von patch-id.cin nach portieren, diff.cdamit wir den gleichen Hash erhalten, wenn wir Patch-IDs für ' format-patch --base=' Arten von Befehlsaufrufen generieren .


Vor Git 2.24 (Q4 2019) hat " git format-patch -o <outdir>" ein Äquivalent von " mkdir <outdir>" nicht " mkdir -p <outdir>" gemacht, was korrigiert wird.

Siehe Commit edefc31 (11. Oktober 2019) von Bert Wesarg ( bertwesarg) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit f1afbb0 , 18. Oktober 2019)

format-patch: Erstellen Sie führende Komponenten des Ausgabeverzeichnisses

Unterzeichnet von: Bert Wesarg

'git format-patch -o' hat ein Äquivalent von 'mkdir' und nicht 'mkdir -p' gemacht, was korrigiert wird.

Vermeiden Sie die Verwendung von ' adjust_shared_perm' in den führenden Verzeichnissen, was Auswirkungen auf die Sicherheit haben kann. Erreicht durch vorübergehendes Abschalten von ‚ config.sharedRepository‘ wie ‚ git init‘ der Fall ist.


Mit Git 2.25 (Q1 2020) git rebasefunktionierte " " nicht gut, wenn die format.useAutoBaseKonfigurationsvariable gesetzt wurde, die korrigiert wurde.

Siehe Festschreiben cae0bc0 , Festschreiben 945dc55 , Festschreiben 700e006 , Festschreiben a749d01 , Festschreiben 0c47e06 (04. Dezember 2019) von Denton Liu ( Denton-L) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 71a7de7 , 16. Dezember 2019)

rebase: format.useAutoBaseBruch beheben

Berichtet von: Christian Biesinger
Unterzeichnet von: Denton Liu

Das format.useAutoBase = trueAusführen von rebase führte zu einem Fehler:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

--no-baseBeheben Sie dies, indem Sie von Rebase immer an Format-Patch übergeben, damit der Effekt von format.useAutoBasenegiert wird.

VonC
quelle
8

So generieren Sie einen Pfad aus einem bestimmten Commit (nicht dem letzten Commit):

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE
Makah
quelle
5

Wenn Sie nur die angegebene Datei unterscheiden möchten, können Sie:

git diff master 766eceb - verbindungen /> 000-mysql-connector.patch

jiahut
quelle
0

Mit meinem Quecksilberhintergrund wollte ich verwenden:

git log --patch -1 $ID > $file

Aber ich denke darüber nach, git format-patch -1 $IDjetzt zu verwenden.

alls0rts
quelle
-5

Wie kann ein Patch nur für den spezifischen SHA1 generiert werden?

Es ist ganz einfach:

Option 1. git show commitID > myFile.patch

Option 2. git commitID~1..commitID > myFile.patch

Hinweis: Ersetzen Sie commitIDdurch die tatsächliche Festschreibungs-ID (SHA1-Festschreibungscode).

Ankush
quelle
3
Option 1 ist völlig falsch und hat nichts mit der Frage zu tun.
Anshuman Manral
3
Option 2 ist ebenfalls ein ungültiger Befehl. Sie erhalten folgende Fehlermeldung: git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 ~ 1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git: 'a5f4bcaeb7fa7de27ae79d9522332e87b8f Siehe 'git --help'.
Bitte