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?


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.


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.


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

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

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 .

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


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!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.