Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

techniken:gitlab-dienst

Versionsverwaltung mit Git+GitLab

In euren Projekten werdet ihr kollaborativ an eurem Programm-Code arbeiten müssen. Dabei wird es vorkommen das zwei oder mehr, gleichzeitig Änderungen vornehmen, oder zu unterschiedlichen Terminen mit wechselnden Gruppenmitgliedern gearbeitet wird. Um diese Art der Zusammenarbeit zu erleichtern wird Git verwendet. Mit Git könnt ihr euren gemeinsamen Programm-Code aktuell halten und zeitgleich bearbeiten ohne dass ihr Gefahr läuft wichtige Arbeit von anderen zu überschreiben oder vorherige (funktionierende) Versionen eures Codes zu verlieren. Dies macht Git zu einem mächtigen Werkzeug welches weit verbreitet Anwendung erfährt. Damit werden oft Projekte verwaltet, die wesentlich komplexer ist als das, was ihr im Robotiklabor macht. Wenn ihr aber schon am Beispiel eines kleineren Projektes dem Umgang mit Git lernt, erleichtert es euch hoffentlich die Arbeit mit Git in der Zukunft. In diesem Artikel haben wir versucht, euch die Git-Basics vorzustellen. Weitere Infos findet ihr online, z.B.:

Eine ausführliche Anleitung zur verwendung von Git gibt es hier: https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository

Eine einfache in deutscher Sprache z.B. hier: https://rogerdudler.github.io/git-guide/index.de.html

Hier findet ihr Youtube-Videos zum Thema: https://www.youtube.com/watch?v=Nkz7TnhFvWU&list=PL58qjcU5nk8s-UQHfzeVajBDwkbWqwSc6

GitLab

GitLab ist eine webbasierte Software zur Versionierung und gemeinsamen Bearbeitung von Programmcode mit Git. Kernkomponente ist ein Webportal an dem sich die Benutzer anmelden und eigene Projekte anlegen können. Für jedes Projekt wird automatisch ein Git-Repository angelegt, in dem dann der Programmcode versioniert abgelegt werden kann. Zusätzlich stellt GitLab zu jedem Projekt ein Wiki und einen Issue Tracker bereit über die dann Dokumentationen angeboten bzw. Fehler oder Änderungswünsche am Programmcode erfasst und verwaltet werden können.

Für die gemeinsame Arbeit können andere Benutzer zu einem Projekt hinzugefügt werden, wobei differenzierte Berechtigungsstufen möglich sind. Projekte können intern, nur für Projektmitglieder, extern, für alle angemeldeten Benutzer und öffentlich, also weltweit zugänglich sein.

Funktionsweise und -umfang entsprechen im Wesentlichen dem bekannten Webdienst „github.com“, jedoch werden alle Daten auf Servern des tubIT Rechenzentrums gespeichert.

Der Dienst ist somit ideal für das Verwalten von Programmcode, egal ob allein oder im Team.

Installation

Software installieren

Kommandozeilenversion

Die meisten Leute benutzen für die Verwaltung ihrer Git-Repositories ein Kommandozeilentool, für das es im Gegensatz zu den grafischen Tools auch ordentliche Doku gibt. Die aktuelle Git-Version findet ihr hier:

Wenn alles geklappt hat, könnt ihr euch in der Kommandozeile z.B. die aktuelle Version von der git-Installation ansehen:

git --version

Evtl. müsst ihr noch euren Namen und E-Mail festlegen:

git config --global user.name "d.golovko"
git config --global user.email "d.golovko@tu-berlin.de"

Grafische Userinterfaces

Liebhaber Grafischer Oberflächen können eines der folgenden Programme benutzen - leider ist bei denen manchmal nicht wirklich klar, was eigentlich „unter der Motorhaube“ passiert.

Falls Du der/die erste in eurem Team bist: Gruppe und Projekt auf dem TU-Server erstellen

Bei GitLab der TU Berlin anmelden

Projektrepository erstellen

  • Auf Knopf „New Project“ drücken
  • Bei „Project path“ einen aussagekräftigen Namen für das Projekt ohne irgendwelche Sonder- oder Leerzeichen eingeben
  • Den „Create Project“ Knopf drücken.
  • Um andere Teammitglieder hinzuzufügen, drückt auf Settings–>Members (links unten). Die anderen Mitglieder sollen die Rolle „Master“ haben, damit sie volle Schreibrechte bekommen.

Arbeiten mit Git

0.: Grundkonzepte

Git besteht aus vier verschiedenen Orten an denen eure Dateien aufbewahrt werden. Davon sind der workspace, index und local repository auf eurem Computer gespeichert, während das remote repository entfernt auf dem Git-Server liegt.

workspace

Der workspace ist eure Arbeitskopie. Dieser enthält eure Daten mit denen ihr arbeiten könnt. Es kann jede beliebige Datei angelegt werden, nicht nur Code. Zum bearbeiten verwendet ihr die Editoren und IDE's eurer Wahl.

index

Der index dient zum stagen eurer Dateien. Hier gebt ihr an welche Dateien mit dem nächsten commit zum local repository hinzugefügt werden. Zu beginn mag dieser zusätzliche Schritt etwas umständlich wirken, für größere Projekte ist er aber sehr sinnvoll (Warum?). Das Hinzufügen geschieht mit dem Befehlen „add“.

local repository

Im local repository wird jeder commit (Hinzufügen) zu eurem Projekt gespeichert, es ermöglicht auch das zurückkehren zu alten Versionen eures Projektes.

remote repository

Sobald ihr euer lokales Repository auf den neusten Stand gebracht habt, könnt ihr mit „push“ die neue Version zum „remote repository“ schieben. Das „local repository“ und „remote repository“ enthalten alle bisher gespeicherten Zwischenstände eures Projektes. Der „workspace“ hingegen ist nur die aktuellste auf deinem Rechner vorhandene Version.

1.: Repository vom TU-Server auf den eigenen Rechner übertragen ("clone")

Nachdem ihr ein Projekt in GitLab angelegt habt könnt ihr euch davon eine lokale Kopie anlegen. Öffnet euer Terminal/Konsole/Eingabeaufforderung um per Kommandozeile Befehle einzugeben. Zunächst der Befehl zum Klonen des Repository:

git clone <repo> <directory>

Ihr schreibt anstatt <repo> die Adresse eures remote Repository, zu finden auf GitLab auf der Seite eures Projekts. Wechselt zum HTTPS-Link:

Und für <directory> gebt ihr das Verzeichnis an in dem eure working copy liegen soll. Der gesamte Befehl könnte dann wie folgt aussehen:

git clone https://gitlab.tubit.tu-berlin.de/d.golovko/MyProject.git /Documents/Arduino/

Nun habt ihr eine Kopie eures Projekts lokal gespeichert und könnt Änderungen am workspace vornehmen.

Mit mit dem cd-Befehl könnt ihr in der Kommandozeile zum entsprechenden Ordner wechseln:

cd /Documents/Arduino/MyProject/

2.: Neue Dateien der Kopie auf dem eigenen Rechner hinzufügen ("add", "commit")

Der add-Befehl sagt Git das du Änderungen an einer Datei mit dem nächsten commit zum lokalen Repository hinzufügen möchtest. Solange der commit noch nicht ausgeführt wurde, wurden die Änderungen auch nicht übernommen.

Eine Datei zum Index hinzufügen:

git add <file>

Es können nur Ordner zum Git-Repository hinzugefügt werden wenn sie Dateien enthalten, das liegt daran dass Git nur Dateien erfasst und nicht Ordner.

Dateien welche indexiert wurden können nun zum lokalen Repository hinzufügt werden:

git commit -m "Hierher kommt eine Beschreibung was geändert wurde (die Anführungszeichen gehören dazu!)"

Beispiel

Wir fügen die Datei test.rtf zu unserem lokalen Repository hinzu. Zunächst bewegt ihr euch mit der Kommandozeile in den Ordner eures Projektes. Die test.rtf wurde vorher mit einem Texteditor im Projektordner erstellt. Zum Index hinzufügen:

git add test.rtf

Im Anschluss committen wir die Datei zu unserem lokalen Repository:

git commit -m "Eine hello world Test-Datei!"

Nun befindet sich die Datei in eurem lokalen Repository.

3.: Änderungen vom TU Server auf den eigenen Rechner übertragen ("pull")

Um die aktuelle Version von eurem remote Repository zu bekommen verwendet ihr den Befehl:

git pull

Dieser Befehl ist immer vor der Übertragung der eigenen Änderungen in das Repository empfohlen, um eventuelle Änderungen von Anderen einzuarbeiten, bevor ihr euren Code pusht (s. nächten Punkt).

4.: Änderungen auf dem eigenen Rechner in das Repository auf dem TU Server übertragen ("push")

Um die Änderungen auch auf euerem remote Repository verfügbar zu machen verwendet ihr folgenden Befehl:

git push origin master

Bevor am Code gearbeitet wird immer die aktuellste Version „pullen“, nach getaner Arbeit den neuen Stand „pushen“!

5.: Versionskonflikte

Falls jedoch gleichzeitig am Code gearbeitet wird kann es zu Versionskonflikten kommen, diese müssen manuell gelöst werden bevor ein push/pull durchgeführt werden kann.

Beispiel

In unserer „test.rtf“-Datei haben wir „Hello Wörld!“ geschrieben und zum remote repository hinzugefügt. Nun hat aber jemand drittes schon vor dir deinen Fehler bemerkt und versucht ihn zu korrigieren indem er es zu „Hello Earth!“ verbessert. Da deine Intention aber war „Hello World!“ zu schreiben änderst du die Datei entsprechend und versuchst sie zu pushen. Du wirst dann eine Fehlermeldung erhalten die folgendermaßen aussieht:

User$ git push origin master
To git@gitlab.tubit.tu-berlin.de:c.jaedicke/myTestProject.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@gitlab.tubit.tu-berlin.de:c.jaedicke/myTestProject.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Die Lösung des Problems wird bereits genannt. Es müssen zunächst durch einen pull die Änderungen am remote repository in dein local repository integriert werden. Wenn du nun einen pull durchführst wirst du folgende Meldung erhalten:

User$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From gitlab.tubit.tu-berlin.de:c.jaedicke/myTestProject
   2e6d627..a29e896  master     -> origin/master
Auto-merging test.rtf
CONFLICT (content): Merge conflict in test.rtf
Automatic merge failed; fix conflicts and then commit the result.

Git hat versucht automatisch die Änderungen am remote repository mit deinem workspace zu mergen (Zusammenführen). Dabei ist es, wie zu erwarten, zu einem Konflikt gekommen, denn es wurde an gleicher Stelle Änderungen vorgenommen. Ihr könnt euch den Konflikt anzeigen lassen mit:

git diff

Dies gibt euch folgende Antwort von Git:

User$ git diff
diff --cc test.rtf
index 30c8472,642e89a..0000000
--- a/test.rtf
+++ b/test.rtf
@@@ -4,4 -4,4 +4,8 @@@
  \paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
  \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
  
- \f0\fs24 \cf0 Hello World!}
 -\f0\fs24 \cf0 Hello Earth!}
++<<<<<<< HEAD
++\f0\fs24 \cf0 Hello World!}
++=======
++\f0\fs24 \cf0 Hello Earth!}
++>>>>>>> a29e8967e7015e58cd9af8489bec4d8288b84fe4

Um den Konflikt zu lösen muss also „Hello World!“ in eurem local repository zu „Hello Earth!“ geändert werden. Sobald ihr die Änderungen vorgenommen habt muss wieder ein add+commit durchgeführt werden. Nun kann ohne Konflikt ein pull durchgeführt werden, womit dein local repository auf dem aktuellen Stand ist. Ausgehend vom aktuellen Stand kann nun „Hello Earth!“ zu „Hello World!“ geändert werden und zum remote repository gepushed werden.

Mit SourceTree

Branching

In Git gibt es die Möglichkeit sogenannte branches zu erstellen. Ein Branch ist so etwas wie eine Kopie des bisherigen Programms in einer Art unter-repository. Bei Erstellung eines neuen repositorys wird automatisch der „master“ Branch erstellt. In diesem legt man die Ordnerstruktur des Projekts fest. Danach kann das gesamte Team alle Änderungen direkt in den master branch pushen. Das Problem hierbei ist, dass es vorkommen kann, dass jemand fehlerhaften code hochlädt oder dass eine änderung in einem anderen Programmteil einen Fehler in unserem hervorruft. Um derartige Konflikte zu vermeiden ergibt es bei größeren Projekten Sinn für verschiedene Teile des Programms verschiedene branches zu erstellen.
Bsp:
Wir entwickeln eine Software, welche Bilder einer Webcam aufnimmt und darauf 2 Algoritmen A und B laufen lässt. Unser Team besteht aus 5 Menschen. Wir beschliessen nun 2 Leute an Algorithmus A, 2 Leute an Algorithmus B und eine Person am Einlesen des Bildes arbeiten zu lassen. Wir erstellen ein Git repository in welchem wir die Struktur unseres Projekts festlegen und erstellen uns 3 Branches: „Algo_A“, „Algo_B“ und „Einlesen“ (Abb. 3, Pfeil 1). Jedes Team hat nun seinen eigenen Branch (Kopie der Projektstruktur) in dem es arbeitet. Nun hat zB. Team-B ihren Algorithmus zum laufen gebracht und gut getestet, in diesem Fall wird der Branch „algo_B“ in den „master“-Branch gemerged (Abb. 3, Pfeil 2) (dh. alle Änderungen die auf dem Branch algo_B vorgenommen wurden werden in den master Branch übertragen). Die anderen Teams arbeiten vorläufig weiter auf der Kopie des ursprünglichen Master Branches. Wenn nun Team-A ebenfalls ihren algorithmus vorläufig fertig gestellt und gut getestet! hat, wird der master Branch mit den Veränderungen von Team-B erst in den algo_a Branch gemerged (Abb. 3, Pfeil 3) und danach der algo_a Branch in den Master (Abb. 3, Pfeil 4). Dieser Schritt ist wichtig um zu verhindern, dass beim Mergen von algo_a in master konflikte auftreten und am ende des merges die Programmversion im Master nicht mehr funktioniert. Auf diese Weise hat auch jeder jederzeit Zugriff auf die letzte funktionierende Version eures Programms (also den master Branch). Abbildung 3: Branching Beispiel in Git.

Befehle:
Einene Branch mit dem Namen algo_A erstellen. Achtung, ihr brancht immer von dem Branch in dem ihr euch momentan befindet ab.

git branch algo_A

In den Branch algo_A wechseln:

git checkout algo_A

Den Branch algo_A löschen:

git branch -d algo_A

Zum mergen müsst ihr zuerst in den Branch wechseln in welchen ihr mergen wollt. danach merged ihr mit folgendem Befehl:

git merge algo_A


Bsp:

Wenn ihr also zB. erst

git checkout master

ausführt und danach

git merge algo_A

so werden die Änderungen, die in algo_A gemacht wurden, in den master übernommen.

techniken/gitlab-dienst.txt · Zuletzt geändert: 2021/02/01 17:41 von d.golovko