Cherry-Picking Commits in Git

Avatar of Tobias Günther
Tobias Günther am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Dieser Artikel ist Teil unserer Serie „Advanced Git“. Folgen Sie uns unbedingt auf Twitter oder melden Sie sich für unseren Newsletter an, um über die nächsten Artikel informiert zu werden!

In Teil 5 dieser Serie haben wir uns Rebase und Merge angesehen. Obwohl es ein paar Unterschiede zwischen git merge und git rebase gibt, haben beide Befehle dasselbe Ziel: Sie integrieren Änderungen von einem Branch in einen anderen.

Heute befassen wir uns mit git cherry-pick und wie es uns ermöglicht, ausgewählte, einzelne Commits von jedem beliebigen Branch in unseren aktuellen HEAD-Branch zu integrieren. Das ist ein großer Unterschied zu git merge oder git rebase, die beide alle neuen Commits vom angegebenen Branch integrieren.

Warum sollte man das also tun und nur einen Commit von einem Branch auswählen, um ihn auf einen anderen anzuwenden? Dafür gibt es natürlich verschiedene Gründe, aber ein besonders hilfreicher ist das Rückgängigmachen von Änderungen. Nehmen wir an, Sie haben versehentlich einen Commit auf dem falschen Branch gemacht. Mit cherry-pick ist das kein großes Problem: Sie können zum richtigen Branch wechseln und dann den Commit per Cherry-Pick holen!


Bevor wir uns ein praktisches Beispiel ansehen, eine Warnung: Seien Sie nicht zu begeistert vom Cherry-Picking. Ihr Hauptziel sollte es sein, auf Branch-Ebene zu arbeiten, und sowohl git merge als auch git rebase wurden genau für diese Aufgabe entwickelt. Cherry-Picking ist für besondere Anlässe gedacht, nicht als Ersatz für Merging und Rebase.

Einen Commit auf einen anderen Branch verschieben

Showing a flow of two git branches, one for master and another for feature/newsletter. A red circle representing a third commit is on the master branch, but has a yellow arrow pointing to the feature/newsletter branch showing where it was intended to go.

Hier ist ein reales Szenario, um zu erklären, wann Cherry-Picking der richtige Ansatz ist. Angenommen, Sie haben etwas auf den master-Branch committet, das stattdessen für den Branch feature/newsletter gedacht war. Was nun? Müssen Sie Ihre Teammitglieder oder Ihren Chef anrufen, um diesen „Fehler“ zu erklären?

Der folgende Screenshot von Tower, einem grafischen Git-Client für macOS und Windows, zeigt das Problem und den Commit 26bf1b48, der versehentlich auf dem master-Branch gemacht wurde.

Showing the Tower app UI with a commit history of a master branch. Red arrows point to the most recent commit and the newsletter branch,. indicating that is where the commit was intended to go.

Alternativ können Sie die Situation auf der Kommandozeile untersuchen, wenn Sie im Terminal git log eingeben.

$ git log
commit 26bf1b4808ba9783e4fabb19ec81e7a4c8160194 (HEAD -> master)
Author: Tobias Günther
Date:   Fri Oct 5 09:58:03 2018 +0200

    Newsletter signup page

Der Commit mit der ID 26bf1b48 ist also auf master gelandet, aber Sie hätten ihn auf den Branch feature/newsletter committen sollen. Lasst uns diesen speziellen Commit per Cherry-Pick nehmen und ihn auf den richtigen Branch verschieben. Zuerst wechseln Sie den Branch und dann per Cherry-Pick den Commit.

$ git checkout feature/newsletter
Switched to branch 'feature/newsletter'
$ git status
On branch feature/newsletter
nothing to commit, working tree clean
$ git cherry-pick 26bf1b48
[feature/newsletter 7fb55d0] Newsletter signup page
 Author: Tobias Günther <[email protected]>
 Date: Fri Oct 5 09:58:03 2018 +0200
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 signup.html

Wenn Sie git log erneut ausführen, sehen Sie den neuen Commit auf dem Branch feature/newsletter.

$ git log
commit 7fb55d06a8e70fdce46921a8a3d3a9de7f7fb8d7 (HEAD -> feature/newsletter)
Author: Tobias Günther <[email protected]>
Date:   Fri Oct 5 09:58:03 2018 +0200

    Newsletter signup page

Was ist im Hintergrund passiert? Git hat eine Kopie des Commits mit denselben Änderungen und derselben Commit-Nachricht auf dem Branch feature/newsletter erstellt. Es handelt sich jedoch um einen komplett neuen Commit mit seiner eigenen, neuen ID. Und was ist mit dem ursprünglichen Commit?

Aufräumen des anderen Branches

Wenn Sie sich den master-Branch ansehen, sehen Sie immer noch diesen „falschen“ Commit. Das bedeutet, dass Cherry-Picking einen geholten Commit nicht vom ursprünglichen Branch „bewegt“; es erstellt lediglich eine Kopie und lässt das Original unberührt.

Um nun aufzuräumen und den Commit rückgängig zu machen, können Sie git reset verwenden.

$ git checkout master
Switched to branch 'master'
$ git reset --hard HEAD~1
HEAD is now at 776f8ca Change about title and delete error page

Das war's – als ob nichts passiert wäre.

Falls Sie eine GUI-App wie Tower verwenden, sieht der gesamte Prozess so aus.

Animated screenshot showing a commit being dragged from master branch and dropped on the feature/newsletter branch where it was intended to go.

Ein Werkzeug für Spezialfälle, nicht für die alltägliche Integration

Immer wenn Sie einen traditionellen Merge oder Rebase verwenden können, sollten Sie dies tun. Cherry-Picking sollte für Fälle reserviert sein, in denen ein git merge oder git rebase nicht möglich ist, wenn Sie nur einzelne Commits von einem Branch auf einen anderen verschieben möchten. Behalten Sie immer im Hinterkopf, dass git cherry-pick „doppelte“ Commits erstellt und Sie danach aufräumen sollten.

Wenn Sie tiefer in fortgeschrittene Git-Tools eintauchen möchten, können Sie sich gerne mein (kostenloses!) „Advanced Git Kit“ ansehen: Es ist eine Sammlung kurzer Videos zu Themen wie Branching-Strategien, Interactive Rebase, Reflog, Submodules und vieles mehr.

Viel Spaß beim Cherry-Picking – und bis bald zum nächsten Teil unserer Serie über „Advanced Git“!