Das Erstellen eines Patches in GIT ist eine großartige Möglichkeit, Änderungen zu teilen, die Sie noch nicht veröffentlichen möchten Zweig eines Projekts.
Um besser zu verstehen, wie wir einen Patch erstellen, lassen Sie uns zunächst ein wenig darüber diskutieren, wie sich GIT-Speicher ändern.
Wenn Sie neu bei GIT sind, installieren Sie Git und erhalten Sie eine Starthilfe von diesem GIT-Einführungsartikel.
Wenn eine Datei zum ersten Mal in einem Projekt in GIT festgeschrieben wird, wird eine Kopie gespeichert. Für alle nachfolgenden Commits speichert GIT im Wesentlichen Anweisungen, wie die vorherige Version des Projekts in die neu festgeschriebene Version umgewandelt werden soll.
In GIT werden diese Anweisungen „diffs“ genannt. Immer wenn Sie einen Zweig auschecken, beginnt GIT grundsätzlich mit dem ursprünglichen Zustand des Projekts und wendet alle diese Unterschiede an, um den gewünschten Zustand zu erreichen.
Wenn man jetzt weiß, wie GIT Commits speichert, ist es leicht zu erkennen, dass eine Patch-Datei einfach eine Verkettung der Diffs für jeden der Commits ist, die der Patch umfassen wird.
Nehmen wir für unser Beispiel die folgende Situation an:Wir haben ein einfaches Projekt mit 2 Branches:Master und Experimental.
$ git log --oneline --all * b36f227 (experimental) third commit -- added file3 * f39ebe8 second commit -- added file2 * 04a26e5 (HEAD, master) first commit -- committed file1
Master befindet sich derzeit beim ersten Commit, während Experimental 2 Commits davor liegt. In jedem Commit habe ich jeweils eine Datei mit den Namen file1, file2 und file3 hinzugefügt. Hier ist der aktuelle Status jedes Zweigs:
Auf dem Master haben wir nur file1:
$ git status On branch master nothing to commit, working directory clean $ ls file1
Während wir experimentell sind, haben wir alle 3 Dateien:
$ git status On branch experimental nothing to commit, working directory clean $ ls file1 file2 file3
In diesem Tutorial erklären wir, wie man einen Patch der Änderungen im experimentellen Zweig erstellt und auf den Master anwendet.
Erstellen des GIT-Patches
Wir verwenden den Befehl git diff, um die diff-Ausgabe zu erstellen, und leiten sie dann in eine Datei um. Die Form des diff-Befehls, den wir verwenden werden, ist wie folgt:
git diff from-commit to-commit > output-file
wo:
- from-commit – der Punkt, an dem der Patch beginnen soll. (In unserem Fall der Punkt, an dem Experiment von Master abweicht)
- to-commit – der Patch umfasst die Änderungen bis einschließlich zu diesem Punkt. (In unserem Fall das neueste Commit von Experimental)
- Ausgabedatei – hier wird der Patch geschrieben
Hinweis:Wenn entweder from-commit oder to-commit ausgelassen werden, wird davon ausgegangen, dass sie HEAD sind
Wir spezifizieren die beiden Commits durch ihren eindeutigen Hash. Im Allgemeinen müssen Sie nur genug vom Commit-Hash angeben, um seine Eindeutigkeit zu gewährleisten (4 Zeichen werden wahrscheinlich ausreichen).
$ git diff 04a2 b36f > patch.diff $ ls patch.diff file1 file2 file3
Wie Sie der obigen Ausgabe entnehmen können, wurde die Patch-Datei erstellt.
In diesem speziellen Fall, in dem wir einen Patch des gesamten Zweigs erstellen möchten, können wir GIT einen Teil der Arbeit für uns erledigen lassen. Wir können GIT den Punkt bestimmen lassen, an dem unser experimenteller Zweig vom Master-Zweig abweicht, indem wir den Befehl git merge-base verwenden:
git diff $(git merge-base <public branch> <experimental branch>) > <output file>
git merge-base bestimmt den letzten gemeinsamen Commit zwischen 2 Branches. Beachten Sie auch, dass wir dieses Mal weggelassen haben. Es wird standardmäßig auf HEAD gesetzt, und da der experimentelle Zweig ausgecheckt ist, wird HEAD der neueste Commit des experimentellen Zweigs sein.
$ git diff $(git merge-base master experimental) > anotherPatch.diff $ ls anotherPatch.diff patch.diff file1 file2 file3
Auch hier wurde die Patch-Datei erstellt. Diese Patch-Dateien sind identisch.
Anwenden des GIT-Patches
Sobald die Patch-Datei erstellt wurde, ist die Anwendung einfach. Stellen Sie sicher, dass der von Ihnen ausgecheckte Zweig derjenige ist, auf den Sie den Patch anwenden möchten (in unserem Fall den Master). Anschließend können Sie den Patch mit dem Befehl git apply anwenden:git apply
$ git status On branch master ... (rest of output omitted) ... $ ls anotherPatch.diff patch.diff file1 $ git apply patch.diff $ ls anotherPatch.diff patch.diff file1 file2 file3
Die Änderungen aus dem experimentellen Zweig wurden nun auf master repliziert.
Warnung:Obwohl das Anwenden eines Patches auf diese Weise den Inhalt genau repliziert, wird kein Commit-Verlauf repliziert. Das bedeutet, dass der von Ihnen erstellte Patch, selbst wenn er mehrere Commits umfasst, bei der Anwendung als ein einziger Satz von Änderungen angezeigt wird. Sie verlieren sowohl das Wissen darüber, wie die Commits aufgelöst wurden, als auch die Nachrichten für jeden Commit. Vergleichen wir den Commit-Verlauf für beide Branches:
Bei Experimental hatten wir 3 Commits mit jeweils einer aussagekräftigen Commit-Nachricht.
$ git branch * experimental master $ git log --oneline b36f227 third commit -- added file3 f39ebe8 second commit -- added file2 04a26e5 first commit -- committed file1
Unser Patch hat jedoch einfach die tatsächlichen Änderungen auf den Master-Zweig angewendet.
$ git branch experimental * master $ git log --oneline 04a26e5 first commit -- committed file1
Durch das Anwenden des Patches wurden weder die Änderungen festgeschrieben noch der mit diesen Änderungen verbundene Festschreibungsverlauf mitgebracht. Seien Sie vorsichtig, wenn Sie Patches in GIT verwenden.