You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 11_VersionsverwaltungI.md
+98-86Lines changed: 98 additions & 86 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -105,7 +105,9 @@ Eine Versionsverwaltung ist ein System, das zur Erfassung von Änderungen an Dok
105
105
106
106
Ein Beispiel, wie ein Versionsmanagementsystem die Arbeit von verteilten Autoren unterstützt ist die Implementierung von Wikipedia. Jede Änderung eines Artikels wird dokumentiert. Alle Versionen bilden eine Kette, in der die letzte Version als gültige angezeigt wird. Entsprechend der Angaben kann nachvollzogen werden: wer wann was geändert hat. Damit ist bei Bedarf eine Rückkehr zu früheren Version möglich.
107
107
108
-

108
+
Schauen Sie sich live an, wie Wikipedia die Versionsgeschichte des Artikels *Versionsverwaltung* verwaltet — jede Bearbeitung ist mit Zeitstempel, Autor und Diff dokumentiert:
> Erschließen Sie sich den Algorithmus mit einem LLM! Gesucht ist eine grafische Darstellung des Algorithmus, die den Aufbau der Matrix und die Rückverfolgung der LCS zeigt.
437
+
**Warum ist das Ergebnis `ADH`?**
438
+
439
+
LCS steht für *Longest Common **Subsequence*** — nicht *Substring*! Der Unterschied ist entscheidend:
440
+
441
+
- Eine **Substring** wäre ein zusammenhängender Teil (z. B. `ABC` in `ABCDGH`).
442
+
- Eine **Subsequence** ist eine Folge von Zeichen, die in *beiden* Strings in der *gleichen Reihenfolge* vorkommen — aber **nicht zusammenhängend** sein müssen.
443
+
444
+
Gehen wir Zeichen für Zeichen durch:
445
+
446
+
```
447
+
S1: A B C D G H
448
+
S2: A E D F H R
449
+
```
450
+
451
+
Welche Zeichen erscheinen in **beiden** Strings, und zwar in der **gleichen Reihenfolge**?
452
+
453
+
| Zeichen | Position in S1 | Position in S2 | Reihenfolge konsistent? |
Die Matrix `L[i][j]` im Python-Code speichert für jedes Präfix-Paar `(S1[:i], S2[:j])` die Länge der jeweils längsten gemeinsamen Subsequence; die Rückverfolgung am Ende rekonstruiert dann die Zeichenfolge selbst.
462
+
463
+
> **Bezug zur Versionsverwaltung:** Genau das ist das Prinzip hinter `diff` — das Tool findet die längste gemeinsame Subsequence zwischen zwei Dateien und markiert alles, was *nicht* dazugehört, als Änderung (hinzugefügt oder gelöscht).
436
464
437
465
**Schritt 2: Mischen**
438
466
467
+
Das LCS-Ergebnis ist die **Grundlage für das Mischen**. Bleiben wir bei unserem Beispiel `S1 = "ABCDGH"` und `S2 = "AEDFHR"` mit LCS = `ADH`:
468
+
469
+
```
470
+
S1: A B C D G H
471
+
S2: A E D F H R
472
+
LCS: A D H <- gemeinsames Skelett
473
+
```
474
+
475
+
Die LCS bildet das **gemeinsame Skelett** beider Versionen. Alles, was *zwischen* den LCS-Zeichen liegt, ist eine Änderung gegenüber der jeweils anderen Seite:
476
+
477
+
| Position relativ zur LCS | Nur in S1 (entfernt in S2) | Nur in S2 (hinzugefügt in S2) |
Beim **Mischen** stellt sich nun für jede dieser Lücken die Frage: *Was übernehmen wir?* Wenn beide Seiten an derselben Lücke unterschiedliche Inhalte einfügen (wie `B C` vs. `E`), entsteht ein **Konflikt**.
484
+
439
485
In der Praxis wird zwischen zwei Szenarien unterschieden:
440
486
441
-
1. Mischen unabhängiger Dokumente (2-Wege-Mischen) - Ziel ist die Erzeugung eines neuen Dokumentes, dass die gemeinsamen Komponenten und individuelle Teilmengen vereint.
487
+
1. Mischen unabhängiger Dokumente (2-Wege-Mischen) - Ziel ist die Erzeugung eines neuen Dokumentes, dass die gemeinsamen Komponenten und individuelle Teilmengen vereint. Die LCS liefert hier direkt das gemeinsame Skelett.
442
488
443
-
2. Mischen von Dokumenten mit gemeinsamen Ursprung (3-Wege-Mischen) - Ziel ist die Integration möglichst aller Änderungen der neuen Dokumente in eine weiterentwickelte Version des Ursprungsdokumentes
489
+
2. Mischen von Dokumenten mit gemeinsamen Ursprung (3-Wege-Mischen) - Ziel ist die Integration möglichst aller Änderungen der neuen Dokumente in eine weiterentwickelte Version des Ursprungsdokumentes. Hier werden *zwei* LCS-Berechnungen durchgeführt: D0↔D1 und D0↔D2. Aus dem Vergleich beider Diffs erkennt das System, ob Änderungen kompatibel sind oder kollidieren.
444
490
445
491
> Ein Paar von Änderung aus D1 bzw. D2 gegenüber einen Ausgangsdokument D0 kann unverträglich sein, wenn die Abbildung beider Änderungen in einem gemeinsamen Dokument nicht möglich ist. In diesem Fall spricht man von einem Konflikt.
446
492
@@ -561,8 +607,8 @@ Die Entwicklungsgeschichte von git ist mit der des Linux Kernels verbunden:
| 1991 | Änderungen am Linux Kernel via patches und archive files |
563
609
| 2002 | Linux Kernel mit dem Tool BitKeeper verwaltet |
564
-
| 2005 | Bruch zwischen der vertreibenden Firma und der Linux Community |
565
-
|2023| Die aktuelle Version ist 2.40.1|
610
+
| 2005 | Bruch zwischen der vertreibenden Firm> Erschließen Sie sich den Algorithmus mit einem LLM! Gesucht ist eine grafische Darstellung des Algorithmus, die den Aufbau der Matrix und die Rückverfolgung der LCS zeigt.a und der Linux Community |
611
+
|2026| Die aktuelle Version ist 2.43.x|
566
612
567
613
2005 wurde einen Anforderungsliste für eine Neuentwicklung definiert. Dabei wurde hervorgehoben, dass sie insbesondere sehr große Projekte (Zahl der Entwickler, Features und Codezeilen, Dateien) unterstützen können muss. Daraus entstand `Git` als freie Software zur verteilten Versionsverwaltung von Dateien.
568
614
@@ -722,69 +768,48 @@ Nun wird es aber interessanter! Lassen Sie uns jetzt aber zwischen den Varianten
722
768
723
769
`git reset` löscht die Historie bis zu einem Commit. Adressieren können wir die Commits relativ zum `HEAD``git reset HEAD~1` oder mit der jeweiligen ID `git reset <commit-id>`.
Wichtig sind dabei die Parameter des Aufrufes. Erinnern Sie sich an die drei Ebenen aus dem Zustandsmodell: **Arbeitsverzeichnis** (Ihre Dateien auf der Platte), **Staging-Bereich** (das, was mit `git add` markiert wurde) und **Repository** (die committeten Versionen). Die drei Reset-Varianten unterscheiden sich darin, *wie weit* sie diese Ebenen zurückdrehen:
|`git reset --soft`|| zurückgesetzt | unverändert | unverändert | Der Commit wird "rückgängig gemacht" — die Änderungen liegen aber weiterhin staged bereit. **Anwendungsfall:** Sie wollen einen Commit aufteilen oder neu formulieren. |
782
+
|`git reset --mixed`| ✓ (Default) | zurückgesetzt | zurückgesetzt | unverändert | Commit und Staging werden zurückgenommen, Ihre Datei-Änderungen bleiben aber erhalten. **Anwendungsfall:** Sie wollen `git add`-Entscheidungen neu treffen. |
783
+
|`git reset --hard`|| zurückgesetzt | zurückgesetzt | zurückgesetzt | Alles wird auf den Stand des Ziel-Commits zurückgesetzt — **Ihre lokalen Änderungen gehen verloren!** ⚠️ **Anwendungsfall:** Sie wollen einen Fehlversuch komplett wegwerfen. |
784
+
785
+
**Konkretes Mini-Szenario:** Sie haben gerade `git commit -m "Add feature X"` gemacht und merken sofort, dass die Commit-Message Murks ist:
786
+
787
+
-`git reset --soft HEAD~1` → Commit weg, Dateien bleiben staged. Sie können sofort mit einer besseren Message neu committen.
788
+
-`git reset --mixed HEAD~1` → Commit weg, Staging weg. Sie können einzelne Dateien selektiv neu staged committen.
789
+
-`git reset --hard HEAD~1` → Commit weg, Dateien zurückgesetzt. **Alle Änderungen seit dem Vor-Commit sind gelöscht.**
790
+
791
+
> **Merke:**`--hard` ist eine der wenigen Git-Operationen, die wirklich Daten *vernichten* kann. Wenn Sie unsicher sind, prüfen Sie vorher mit `git status` und `git log`, was Sie verlieren würden.
792
+
793
+
739
794
**Variante 2 - Revert**
740
795
741
-
Häufig möchte man nicht die gesamte Historie zurückgehen und alle Änderungen verwerfen, sondern vielmehr eine Anpassung zurücknehmen und deren Auswirkung korrigieren. Eine Anpassung würde aber bedeuten, dass alle nachgeordneten Commits angepasst werden müssten.
796
+
Häufig möchte man nicht die gesamte Historie zurückgehen und alle Änderungen verwerfen, sondern vielmehr eine einzelne Anpassung zurücknehmen. Genau das leistet `git revert`: Statt einen Commit aus der Historie zu *entfernen*, erzeugt es einen **neuen Commit**, der die Änderungen des Ziel-Commits aufhebt.
| Wirkung auf Historie |**Schreibt sie um** — Commits verschwinden |**Erweitert sie** — neuer "Anti-Commit" |
801
+
| Sicher für Remote? | ❌ Nein (Force-Push nötig) | ✓ Ja (ganz normaler Push) |
802
+
| Anwendung | Lokale Fehlversuche wegwerfen | Bereits gepushte Commits zurücknehmen |
803
+
804
+
> **Faustregel:** Geteilte Historie nie umschreiben. Sobald ein Commit gepusht ist und andere damit arbeiten könnten, ist `revert` der einzige saubere Weg.
742
805
743
806
```text @ExplainGit.eval
744
807
git commit -m V1
745
808
git commit -m V2
746
809
git commit -m V3
747
810
```
748
811
749
-
**Variante 3 - Rebase**
750
-
751
-
Ein sehr mächtiges Werkzeug ist der interaktive Modus von `git rebase`. Damit kann die
752
-
Geschichte neugeschrieben werden, wie es die git Dokumentation beschreibt. Im Grund können Sie damit Ihre Versionsgeschichte "aufräumen". Einzelne Commits umbenennen, löschen oder fusionieren. Dafür besteht ein eigenes Interface, dass Sie mit dem folgenden Befehl aufrufen können:
753
-
754
-
```console
755
-
▶git rebase -i HEAD~5
756
-
757
-
pick d2a06e4 Update main.yml
758
-
pick 78839b0 Reconfigures checkout
759
-
pick f70cfc7 Replaces wildcard by specific filename
760
-
pick 05b76f3 New pandoc command line
761
-
pick c56a779 Corrects md filename
762
-
763
-
# Rebase a3b07d4..c56a779 onto a3b07d4 (5 commands)
764
-
#
765
-
# Commands:
766
-
# p, pick = use commit
767
-
# r, reword = use commit, but edit the commit message
768
-
# e, edit = use commit, but stop for amending
769
-
# s, squash = use commit, but meld into previous commit
770
-
# f, fixup = like "squash", but discard this commit's log message
771
-
# x, exec = run command (the rest of the line) using shell
772
-
# d, drop = remove commit
773
-
#
774
-
# These lines can be re-ordered; they are executed from top to bottom.
775
-
#
776
-
# If you remove a line here THAT COMMIT WILL BE LOST.
777
-
#
778
-
# However, if you remove everything, the rebase will be aborted.
779
-
#
780
-
# Note that empty commits are commented out
781
-
```
782
-
783
-
Als Anwendungsfall habe ich mir meine Aktivitäten im Kontext einiger Experimente
784
-
mit den GitHub Actions, die im nächsten Abschnitt kurz eingeführt werden, ausgesucht.
785
-
Schauen wir zunächst auf den ursprünglichen Stand. Alle Experimente drehten sich darum, eine Datei anzupassen und dann auf dem Server die Korrektheit zu testen.
786
-
787
-
> Wir werden `git rebase` im Zusammenhang mit der Arbeit in Branches wieder aufgreifen.
812
+
> Eine dritte Variante — `git rebase` — werden wir in Versionsverwaltung II im Kontext der Arbeit mit Branches kennenlernen.
788
813
789
814
### Was kann schief gehen?
790
815
@@ -796,7 +821,8 @@ Schauen wir zunächst auf den ursprünglichen Stand. Alle Experimente drehten si
796
821
... wir wollen schnell sein und fügen alle Änderungen als staged ein
797
822
git add *
798
823
... Aber halt! Die beiden Dinge gehören doch nicht zusammen!
799
-
git reset
824
+
git reset # default Konfiguration entspricht reset --mixed HEAD
825
+
... Alle Änderungen sind jetzt unstaged, wir können sie jetzt selektiv hinzufügen
800
826
```
801
827
802
828
2.**Ups, eine Datei in der Version vergessen! (Unvollständiger Commit)**
@@ -916,7 +942,7 @@ create origin
916
942
917
943
Die Editoren unterstützen den Nutzer bei der Arbeit, in dem Sie die eigentlichen Commandozeilentools rund um die Arbeitsfläche anordnen.
0 commit comments