Fork me on GitHub

Web Development

Ein Lehrbuch für das Informatik oder Medien-Informatik Studium.

Wie funktioniert die Arbeit mit git, wenn ich auf zwei Computern arbeite? Oder wenn zwei Personen zusammen arbeiten?

Verteiltes Versionskontrollsystem

Git ist ein Verteiltes Versionskontrollsystem. “Verteilt” (distributed) heißt hier: Auf mehreren Computer kann eine Version des Repository liegen.

Mit dem Befehlen push und pull übertragen wir Information zwischen den verschiedenen Computern.

Zwei Computer

Szenario: ich beginne mein Projekte auf dem Laptop, pushe auf ein remote Repository. Später will ich die Arbeit auf meinem PC fortsetzen.

Wichtige Vorbereitung: auf dem zweiten Computer brauche ich wider meinen private key als Datei ~/.ssh/id_rsa. Und bei ersten Mal hole ich das Repository mit git clone auf den Computer.

Später brauche ich dann nur noch den Befehl git pull um die Daten vom remote repository ins local repository zu holen und von dort auch gleich in die working copy.

Zwei Personen

Szenario: ich arbeit mit Andreas zusammen an einem Projekt.

Wichtige Vorbereitung: Über die Weboberfläche gitlab gebe ich Andreas Zugriffsrechte auf das Remote Repository. (Projekt Information → Mitglieder → grüner Button ‘Invite Members’ …). Bei ersten Mal holt sich Andreas das Repository mit git clone auf seinen Computer.

Später braucht er dann nur noch den Befehl git pull um die Daten vom remote repository ins local repository zu holen und von dort auch gleich in die working copy.

Zwei Änderungen

Was passiert, wenn in zwei verschiedenen Repositories etwas geändert wurde? Das erfahre ich, wenn ich den Befehl git push ausführe:

$ git push origin main
To gitlab.mediacube.at:bjelline/barcamp.git
 ! [rejected]        main -> main (fetch first)
error: Fehler beim Versenden einiger Referenzen nach 'gitlab.mediacube.at:bjelline/barcamp.git'
Hinweis: Aktualisierungen wurden zurückgewiesen, weil das Remote-Repository Commits enthält,
Hinweis: die lokal nicht vorhanden sind. Das wird üblicherweise durch einen "push" von
Hinweis: Commits auf dieselbe Referenz von einem anderen Repository aus verursacht.
Hinweis: Vielleicht müssen Sie die externen Änderungen zusammenführen (z. B. 'git pull ...')
Hinweis: bevor Sie erneut "push" ausführen.
Hinweis: Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'
Hinweis: für weitere Details.

Die Fehlermeldung weist mich in die richtige Richtung: “Vielleicht müssen Sie die externen Änderungen zusammenführen (z. B. ‘git pull …’) bevor Sie erneut push ausführen.”

Vorbereitung

Vor dem nächsten Schritt muss ich zwei Punkte konfigurieren: Eine Merge-Strategie:

git config --global pull.rebase false

Und einen Editor, den git von der Kommandozeile aus starten kann. Wenn ich Visual Studio Code installiert habe, und es sich von der Kommandozeile aus mit dem Befehl code starten lässt, dann kann ich es so konfigurieren:

git config --global core.editor "code --wait"

Änderungen pullen

Ich habe also Änderungen (commits) in meinem lokal Repository, und andere Änderungen (commits) im remote Repository. Wenn ich nun den Befehl git pull ausführe werden diese Änderungen zusammengefürt. Der englische Fachbegriff ist merge.

Bei der Zusammenführung entsteht ein neuer Commit (c6 im Bild) mit einer Commit Message.

Die Merge Nachricht schreiben

Damit ich für den Merge Commit die Commit Message zu schreiben kann öffnet git automatisch einen Editor. Nachdem ich die Message gespeichert habe wird der Vorgang abgeschlossen, das sieht so aus:

$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Entpacke Objekte: 100% (3/3), 290 Bytes | 96.00 KiB/s, fertig.
Von gitlab.mediacube.at:bjelline/barcamp
   99463f7..1c698be  main       -> origin/main
Merge made by the 'recursive' strategy.
 README.md | 1 +
 1 file changed, 1 insertion(+)

Merge Konflikt erkennen

In diesem Beispiel tritt nach dem Pull ein Merge Konflikt auf. Welche Dateien sind betroffen?

$ git pull
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 8 (delta 3), reused 0 (delta 0), pack-reused 0
Entpacke Objekte: 100% (8/8), 669 Bytes | 66.00 KiB/s, fertig.
Von gitlab.mediacube.at:bjelline/Jellinek_Brigitte_devtools
   a313bb2..2e2e6fc  main       -> origin/main
automatischer Merge von 2/index.html
KONFLIKT (Inhalt): Merge-Konflikt in 2/index.html
Automatischer Merge fehlgeschlagen; beheben Sie die Konflikte und committen Sie dann das Ergebnis.

Antwort: nur eine Datei, 2/index.html ist betroffen.

Merge Konflikt in der Datei

Was macht git mit den beiden verschiedenen Versionen einer Datei?

Git speichert beide Versionen in einer Datei und fügt zusätzliche Zeilen ein: mit kleiner-Zeichen, mit gleich-Zeichen und mit größer-Zeichen (die Farben sind nur zur Orientierung hinzugefügt.)

<section id="banner">
  <div class="inner">
<<<<<<< HEAD
<h2><img class="banner-image" src="barcamp_logo.svg" alt="Logo Barcamp Salzburg - The Next Web"></h2> <h3>Web, UX/UI und VR</h3>
=======
<h2><img class="banner-image" src="barcamp_logo_neu.svg" alt="Logo Barcamp Salzburg - The Next Web"></h2> <h3>Web, Game, UX und VR</h3>
>>>>>>> 2e2e6fc1d781655bf556b9db7b10a1c5054eac15
<p>

Achtung! Damit ist die Datei erst einmal kaputt: compiliert nicht mehr, wird vom Browser nicht mehr korrekt angzeigt, ist kein valides HTML mehr, …

Merge Konflikt auflösen

Die Datei mit dem Merge Konfligt kann ich ganz normal editieren. Ich überlege welche Version ich behalten will, und entferne die andere Version und die extra-Zeilen:

<section id="banner">
  <div class="inner">
    <h2><img class="banner-image" src="barcamp_logo_neu.svg" alt="Logo Barcamp Salzburg - The Next Web"></h2>
    <h3>Web, Game, UX und VR</h3>
    <p>

Nun teste ich ob alles funktioniert: ich schau mir die HTML-Datei im Browser an.

Wenn alles passt muss ich nun die Datei neu committen, damit ist der merge Konflikt beseitigt.

$ git add index.html
$ git commit -m 'Neues Logo bleibt'
[main 59353a9] Neues Logo bleibt
$ git push
Objekte aufzählen: 11, fertig.
Zähle Objekte: 100% (11/11), fertig.
Delta-Kompression verwendet bis zu 8 Threads.
Komprimiere Objekte: 100% (5/5), fertig.
Schreibe Objekte: 100% (5/5), 626 Bytes | 626.00 KiB/s, fertig.
Gesamt 5 (Delta 2), Wiederverwendet 0 (Delta 0), Pack wiederverwendet 0
To gitlab.mediacube.at:bjelline/Jellinek_Brigitte_devtools.git
   d741640..59353a9  main -> main