Erstellen Sie einen Git-Patch aus den Änderungen im aktuellen Arbeitsverzeichnis

879

Angenommen, ich habe nicht festgeschriebene Änderungen in meinem Arbeitsverzeichnis. Wie kann ich aus diesen einen Patch erstellen, ohne ein Commit erstellen zu müssen?

vrish88
quelle
29
Die akzeptierte Antwort sollte wahrscheinlich geändert werden, da die zweite Antwort fast viermal beliebter ist.
Tim Ogilvy
5
@ TimOgilvy stimmte zu. OP sollte es tun. Die zweite Antwort ist weitaus beliebter und enthält weitere Informationen
John Demetriou
1
Ich denke, es ist erwähnenswert, dass Sie auch Patches von nicht festgeschriebenen Änderungen im Titel benötigen.
2.

Antworten:

401

git difffür nicht inszenierte Änderungen. git diff --cachedfür inszenierte Änderungen.

Sigjuice
quelle
12
yup, git diff ist die Umkehrung von git apply
Spike Gronim
33
git format-patchEnthält auch binäre Unterschiede und einige Meta-Informationen. Eigentlich wäre das die beste Wahl, um einen Patch zu erstellen, aber afaik funktioniert dies nur für eingecheckte Quellen / Änderungen, oder?
Eric
20
Manchmal kann es nützlich sein, einen Patch relativ zum aktuellen Verzeichnis zu erstellen. Um dies zu erreichen, verwenden Siegit diff --relative
ejboy
30
git diff> a.patch, um es in eine Datei zu schreiben
qasimzee
139
Knapp an Sarkastik grenzend, ist die Antwort unten hilfreicher.
Air
1865

Wenn Sie die Änderungen noch nicht festgeschrieben haben, dann:

git diff > mypatch.patch

Aber manchmal kommt es vor, dass ein Teil der Dinge, die Sie tun, neue Dateien sind, die nicht verfolgt werden und nicht in Ihrer git diffAusgabe enthalten sind. Eine Möglichkeit, einen Patch zu git adderstellen, besteht darin, alles für ein neues Commit ( jede Datei oder nur git add .) bereitzustellen, aber das Commit nicht durchzuführen, und dann:

git diff --cached > mypatch.patch

Fügen Sie die Option 'binär' hinzu, wenn Sie dem Patch Binärdateien hinzufügen möchten (z. B. MP3-Dateien):

git diff --cached --binary > mypatch.patch

Sie können den Patch später anwenden:

git apply mypatch.patch

Hinweis: Sie können auch --stagedals Synonym für verwenden --cached.

jcarballo
quelle
128
Vielen Dank für das Beispiel. Im Gegensatz zur akzeptierten Antwort zeigen Sie den Befehlen, wie es geht und nicht nur zu sprechen. Sehr hilfreich und funktionierte einwandfrei für mich :)
Nuala
4
Ich habe genau das getan und beim Ausführen von git apply "fatal: unerkannte Eingabe" erhalten. Irgendeine Idee, was dies verursachen kann und wie es behoben werden kann?
Vitaly
6
@Vitaly: Ist Ihr Patch lesbar, wenn Sie ihn mit einem Texteditor öffnen? Es sollte sauber sein und keine seltsamen Zeichen enthalten. Wenn beispielsweise die Einstellung color.diff festgelegt ist, enthält Ihr Patch einige 'Farbzeichen', die dazu führen können, dass 'git apply' fehlschlägt. Versuchen Sie es in diesem Fall git diff --no-color. Ansonsten sieht es nach einem Codierungsproblem aus.
Jcarballo
3
Im Zusammenhang mit "neuen Dateien, die nicht verfolgt werden": "git diff" und "git diff --cached" funktionieren nur, wenn "git add <file>" zuerst aufgerufen wurde. (Ich bin neu in Git und fragte mich, warum ich jedes Mal einen leeren Patch bekam)
Anonym
5
Dies brachte mich ziemlich leicht aus einer seltsamen Merge / Rebase-Hölle heraus, danke :)
John Hunt
86

git diffund git applyfunktioniert für Textdateien, aber nicht für Binärdateien.

Sie können problemlos einen vollständigen binären Patch erstellen, müssen jedoch ein temporäres Commit erstellen. Sobald Sie Ihre temporären Commits vorgenommen haben, können Sie den Patch erstellen mit:

git format-patch <options...>

Führen Sie nach dem Erstellen des Patches den folgenden Befehl aus:

git reset --mixed <SHA of commit *before* your working-changes commit(s)>

Dadurch werden Ihre temporären Commits zurückgesetzt. Das Endergebnis lässt Ihre Arbeitskopie (absichtlich) mit denselben Änderungen verschmutzen, die Sie ursprünglich hatten.

Auf der Empfangsseite können Sie den gleichen Trick verwenden, um die Änderungen auf die Arbeitskopie anzuwenden, ohne über den Commit-Verlauf zu verfügen. Wenden Sie einfach die Patches an und git reset --mixed <SHA of commit *before* the patches>.

Beachten Sie, dass Sie möglicherweise gut synchronisiert sein müssen, damit diese gesamte Option funktioniert. Ich habe einige Fehler beim Anwenden von Patches gesehen, als die Person, die sie erstellt hat, nicht so viele Änderungen vorgenommen hat wie ich. Es gibt wahrscheinlich Möglichkeiten, es zum Laufen zu bringen, aber ich habe mich nicht weit damit befasst.


So erstellen Sie dieselben Patches in Tortoise Git (nicht, dass ich die Verwendung dieses Tools empfehle):

  1. Übernehmen Sie Ihre Arbeitsänderungen
  2. Klicken Sie mit der rechten Maustaste auf das Zweigstammverzeichnis und klicken Sie auf Tortoise Git->Create Patch Serial
    1. Wählen Sie den Bereich aus, der Sinn macht ( Since: FETCH_HEADfunktioniert, wenn Sie gut synchronisiert sind)
    2. Erstellen Sie die Patches
  3. Klicken Sie mit der rechten Maustaste auf das Zweigstammverzeichnis und klicken Sie auf Tortise Git->Show Log
  4. Klicken Sie mit der rechten Maustaste auf das Commit vor Ihren temporären Commits und klicken Sie aufreset "<branch>" to this...
  5. Wählen Sie die MixedOption

Und wie man sie anwendet:

  1. Klicken Sie mit der rechten Maustaste auf das Zweigstammverzeichnis und klicken Sie auf Tortoise Git->Apply Patch Serial
  2. Wählen Sie die richtigen Patches aus und wenden Sie sie an
  3. Klicken Sie mit der rechten Maustaste auf das Zweigstammverzeichnis und klicken Sie auf Tortise Git->Show Log
  4. Klicken Sie mit der rechten Maustaste auf das Commit vor den Commits des Patches, und klicken Sie aufreset "<branch>" to this...
  5. Wählen Sie die MixedOption
Merlyn Morgan-Graham
quelle
5
Technisch erfordert dies das Erstellen eines Commits, das OP vermeiden wollte, aber es ist ein temporäres Commit und die Antwort ist trotzdem nützlich.
Davenpcj
33

So erstellen Sie einen Patch mit geänderten und neuen Dateien (bereitgestellt):

git diff HEAD > file_name.patch
Ionel Sirbu
quelle
Vielen Dank, in meinem Fall funktioniert diese Antwort, aber git diff --cached > mypatch.patchnicht.
Bergbau
Ich habe eine Frage: Kann file_name.patchder patchBefehl verwendet werden? Sind sie miteinander kompatibel?
Rakshith Ravi
git diff + git diff --cached / staged == git diff HEAD (zeigt alle Änderungen seit dem letzten Commit an)
K. Symbol
20

Ich mag:

git format-patch HEAD~<N>

Wo <N>ist die Anzahl der letzten Commits, die als Patches gespeichert werden sollen?

Einzelheiten zur Verwendung des Befehls finden Sie im DOC

UPD
Hier finden Sie, wie Sie sie dann anwenden können.

UPD Für diejenigen, die nicht auf die Idee gekommen sind, format-patch
Alias ​​hinzuzufügen:

git config --global alias.make-patch '!bash -c "cd ${GIT_PREFIX};git add .;git commit -m ''uncommited''; git format-patch HEAD~1; git reset HEAD~1"'

Führen Sie dann in einem beliebigen Verzeichnis Ihres Projekt-Repositorys Folgendes aus:

git make-patch

Dieser Befehl wird 0001-uncommited.patchin Ihrem aktuellen Verzeichnis erstellt. Der Patch enthält alle Änderungen und nicht verfolgten Dateien, die für den nächsten Befehl sichtbar sind:

git status .
Eugen Konkov
quelle
@jcarballo: Ich habe die Antwort aktualisiert. Fühlen Sie sich frei, mir Ihre Mitteilungen zukommen zu lassen.
Eugen Konkov
2
Es gibt einen einfacheren Weg als das Erstellen eines Commits und das Aufheben des Commits. Git Diff - zwischengespeichert
Gaurav Agarwal
9

Wenn Sie binär arbeiten möchten, geben --binarySie beim Ausführen eine Option an git diff.

Gitster
quelle
0

Wir könnten auch die Dateien angeben, um nur die Dateien mit relativen Änderungen einzuschließen, insbesondere wenn sie sich über mehrere Verzeichnisse erstrecken, z

git diff ~/path1/file1.ext ~/path2/file2.ext...fileN.ext > ~/whatever_path/whatever_name.patch

Ich fand, dass dies nicht in den Antworten oder Kommentaren angegeben ist, die alle relevant und korrekt sind. Deshalb habe ich beschlossen, es hinzuzufügen. Explizit ist besser als implizit!

Anshu Kumar
quelle