Cherry-Picking

Unser Kunde hat eine weitere Anforderung. Die Begrüßung "Hello" sei zu klanglos, "Greetings" solle es sein.

Die Implementierung ist trivial.

$ git checkout master
[...]
$ git checkout -b change/greet-with-greetings
[...]
$ sed -i '' 's/Hello/Greetings/' Main.java
[...]
$ git diff
diff --git a/Main.java b/Main.java
index 782fe2e..cd2eb1d 100644
--- a/Main.java
+++ b/Main.java
@@ -6,7 +6,7 @@ public class Main {
public static void main(String[] args) {
String name = askName();
- System.out.println(String.format("Hello, %s!", name));
+ System.out.println(String.format("Greetings, %s!", name));
}
}
$ make run
javac Main.java
Hey, what's your name?
> Lou Bega
Greetings, Lou Bega!

Funktioniert. Ab nach master damit.

$ git add Main.java
$ git commit
[...]

Change "Hello" to "Greetings"

$ git checkout master
[...]
$ git pull
[...]
$ git merge --no-ff change/greet-with-greetings
[...]
$ git push
[...]

Der Verantwortliche für diese Änderung ist schneller in der Abnahme und möchte diese Änderung baldmöglichst produktiv stellen. Das Refactoring darf weiterhin noch nicht produktiv gestellt werden.

Diese Situation ist generell schwierig, da die meisten Änderungen nicht im Vakuum erstellt werden und sich oft überschneiden. Deshalb ist hier Vorsicht geboten.

In unserem Fall wissen wir aber, dass keine andere Änderung die betroffene Zeile berührt hat. Wir können diese Änderung deshalb selektiv in unsere Branch production bringen. Dafür brauchen wir zuerst den Hash des Commits.

$ git log
commit 2dbf5865deb7ba5f6a358a3e3be3f8889f403e2d (HEAD -> master, origin/master)
Merge: 72103b1 6422492
Author: Some One <some.one@proclane.com>
Date: Mon Dec 9 16:54:49 2019 +0100
Merge branch 'change/greet-with-greetings'
commit 642249273b5a787ad648f0d484e73be265ddee8c (change/greet-with-greetings)
Author: Some One <some.one@proclane.com>
Date: Mon Dec 9 16:54:36 2019 +0100
Change "Hello" to "Greetings"

Commit 642249 soll es also sein. Wir arbeiten wieder auf einer production-basierten Branch:

$ git checkout production
[...]
$ git pull
[...]
$ git checkout -b hotfix/partial-deployment-greetings
[...]
$ git cherry-pick 642249
Auto-merging Main.java
[hotfix/partial-deployment-greetings 1e6433e] Change "Hello" to "Greetings"
Date: Mon Dec 9 16:54:36 2019 +0100
1 file changed, 1 insertion(+), 1 deletion(-)

Wieder ist ein neuer Commit mit dem gewünschten Resultat das Ergebnis. Trotz des gleichen Inhalts hat dieser Commit aber einen eigenen Hash, da Zeitpunkt und Parent-Commit anders sind.

cherry-pick erlaubt auch die Auswahl mehrerer Commits auf einmal.

$ cat Main.java
import java.util.Scanner;
public class Main {
private static String askName() {
System.out.println("Hey, what's your name?");
System.out.print("> ");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
scanner.close();
return name;
}
public static void main(String[] args) {
String name = askName();
System.out.println(String.format("Greetings, %s!", name));
}
}
$ git log
commit 1e6433ea5310e0d42e9f690d6cd31d94e1157381 (HEAD -> hotfix/partial-deployment-greetings)
Author: Kolja Kube <kolja.kube@proclane.com>
Date: Mon Dec 9 16:54:36 2019 +0100
Change "Hello" to "Greetings"

Dieser wird deployed.

$ git checkout production
[...]
$ git pull
[...]
$ git merge --no-ff hotfix/partial-deployment-greetings
[...]
$ git tag -a prd/2019-12-01-change-greeting-text
[...]
$ git push
[...]
$ git push --tags

Nach master muss diesmal nichts, dort ist es ja schon.