Dies ist eine alte Version des Dokuments!
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
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.
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.
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"
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.
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.
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.
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“.
Im local repository wird jeder commit (Hinzufügen) zu eurem Projekt gespeichert, es ermöglicht auch das zurückkehren zu alten Versionen eures Projektes.
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.
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/
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>
git commit -m "Hierher kommt eine Beschreibung was geändert wurde (die Anführungszeichen gehören dazu!)"
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.
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).
Um die Änderungen auch auf euerem remote Repository verfügbar zu machen verwendet ihr folgenden Befehl:
git push origin master
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.
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.
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).
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.