GIT-Tutorial: Verwenden eines zentralen Repositories

Aus Info-Theke
Zur Navigation springen Zur Suche springen

GIT-Tutorial: Übersicht

Einrichten[Bearbeiten]

  • Das zentrale Repository wird in der GIT-Literatur oft auch als Depot oder authoritatives Repository bezeichnet.
  • Ein Depot unterscheidet sich von anderen Repositories:
    • Es wurde durch "git init --bare" oder mit "git clone --bare" erzeugt.
    • Es hat keinen Verweis zu seinem Eltern-Repository, wenn es durch Clonen erzeugt wurde.
    • Es hat kein Arbeitsverzeichnis, ein Auschecken ist nicht möglich. Änderungen kommen auschließlich durch Sychronisation von den geklonten Kind-Repositories ("push") ins Depot.
  • Ein Depot muss nicht notwendigerweise auf einem Server liegen, sondern kann - wie in unserem Fall - auch lokal angelegt sein.

Um für das Tutorial einen nützlichen Ausgangspunkt zu haben, wird das Depot von einer Vorlage geklont:

 DEPOT=/opt/git-depot
 sudo mkdir $DEPOT
 sudo chmod uog+rwx $DEPOT 
 cd $DEPOT 
 git clone --bare git://f-r-e-i.de/backup
  • --bare sorgt dafür, dass das Zielverzeichnis die Endung .git bekommt, hier also backup.git
  • Die Vorlage im Netz ist scheibgeschützt, ein Clonen ohne --bare wäre also nicht sinnvoll
  • Ab jetzt ist das Depot des Musterprojekts unter /opt/git-depot/backup.git zu finden.

Das Musterprojekt[Bearbeiten]

Als Beispielsprojekt dient das Backupscript das im Kapitel GIT-Tutorial: Grundlagen (lokales Repository) entwickelt wurde. Wir führen die gleichen Änderungen durch wie im Kapitel GIT-Tutorial: Erweitertes Mergen, jedoch findet die Parallelentwicklung nicht in zwei Branches statt, sondern wird von zwei Entwicklern (Alice und Bob) in verschieden Repositories durchgeführt.

Ausgangslage[Bearbeiten]

Das Script kopiert ein oder mehrere per Konfiguration festgelegte Quellverzeichnisse in ein Zielverzeichnis.

Veränderung während des Tutorials[Bearbeiten]

  • Protokoll des Backupvorgangs (Entwicklerin Alice)
  • Ersetzen von cp durch rsync (Entwickler Bob)

Einrichten der Entwicklungssrepositories[Bearbeiten]

 for usr in alice bob ; do
   sudo mkdir /opt/$usr
   sudo chmod uog+rwx /opt/$usr
   cd /opt/$usr
   git clone /opt/git-depot/backup.git
   cd /opt/$usr/backup
   # GIT-User für dieses Repository einstellen:
   git config user.name $usr
   git config user.email $usr@localhost
 done

Vorgehensweise[Bearbeiten]

Änderungen bei Alice[Bearbeiten]

Nach dem Clonen:

 gitk --all

Datei:Gitk-backup-alice-v0.2.png

Es fallen zwei Branche auf: remotes/origin/master und remotes/origin/dev. Diese wurde automatisch durch GIT beim Clonen angelegt.

Alice geht auf Nummer Sicher und arbeitet auf einem eigenen Branch:

 cd /opt/alice/backup
 git branch logging
 git checkout logging
 cat >backup.sh <<'EOS'
#! /bin/bash
CONF=/etc/backup/$HOST.conf
if [ ! -f $CONF ] ; then
  echo "SRC=/home\nTRG=/data/backup" > $CONF
fi
source $CONF
date "+%Y.%m.%sd %H:%M: Starting backup $SRC" >>/var/log/backup.log
cp -a $SRC $TRG
date "+%Y.%m.%sd %H:%M: Finished" >>/var/log/backup.log
EOS
 echo >>releasenotes.txt "V0.3: Logging"
 git commit -m "Logging" -a
 git tag -m "logging" v0.3
 gitk --all

Datei:Gitk-backup-alice-v0.3.png

Änderungen bei Bob[Bearbeiten]

Bob braucht keinen eigenen Branch für die Weiterentwicklung, er arbeitet auf master:

 cd /opt/bob/backup
 git checkout master
 perl -pi -e 's/cp/rsync \$1 --delete'/ backup.sh
 echo >>releasenotes.txt "V0.3: More performance using rsync"
 git commit -m "Using rsync" -a
 git tag -m "using rsync" v0.3
 gitk --all

Datei:Gitk-backup-bob-v0.3.png

Bobs Änderungen ins Depot[Bearbeiten]

 git push
 gitk

Das war doch einfach! "push" führt automatisch einen Merge mit dem Branch remotes/origin/master durch und überträgt diesen Stand ins Depot.

Depot nach Bobs push[Bearbeiten]

Den Zustand des Depots bekommen wird am einfachsten heraus, wenn wir erneut clonen:

 cd /tmp
 git clone /opt/git-depot/backup
 cd backup
 gitk --all

Datei:Gitk-backup-bob-v0.3.png

Das Repository entspricht dem von Bob.

Alices Änderungen ins Depot[Bearbeiten]

Zuerst muss Alice ihren Branch logging mit master zusamenbringen, da nachher nur master automatisch ins Depot gebracht werden kann:

 cd /opt/alice/backup
 git checkout master
 git merge logging
Updating 395540c..0fe01d3
Fast-forward
backup.sh        |    2 ++
releasenotes.txt |    1 +
2 files changed, 3 insertions(+), 0 deletions(-)
 gitk --all

Datei:Git-backup-alice-merge-logging-master.png

Ab ins Depot...

 git push
To /opt/git-depot/backup.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to '/opt/git-depot/backup.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again.  See the
'Note about fast-forwards' section of 'git push --help' for details.

Was ist passiert? GIT weigert sich, die Änderungen auf dem Depot einfach durchzuführen, da sonst Datenverlust drohen würde: Die Änderungen von Bob wären weg.

Der Ausweg wird ja schon vorgeschlagen: Die Änderungen vom Depot holen, mit Alices Änderungen zusammenführen und dann mergen.

Änderungen aus dem Depot holen[Bearbeiten]

Der vorige Vorschlag von GIT war das Kommando pull. Das ist eine Kombination von fetch und merge. Alice bevorzugt die Variante mit den Einzelbefehlen:

 git fetch
From /opt/git-depot/backup
395540c..60ba035  master     -> origin/master
 gitk

Datei:Gitk-backup-alice-nach-fetch.png

Das fetch-Kommando schreibt den Branch origin/master, der den Branch master im Depot repräsentiert, fort. Die Änderungen von Bob ("Using rsync") sind angekommen.

Mergen des Depot-Masterbranches[Bearbeiten]

Was jetzt kommt, ist Standard (siehe GIT-Tutorial: Erweitertes Mergen: Alice merged den Zweig origin/master in ihren Branch master:

 git merge origin/master
Auto-merging backup.sh
CONFLICT (content): Merge conflict in backup.sh
Auto-merging releasenotes.txt
CONFLICT (content): Merge conflict in releasenotes.txt
Automatic merge failed; fix conflicts and then commit the result.

Konfliktbehandlung=[Bearbeiten]

Es gibt die zwei Konflikte, die behoben werden müssen:

cat backup.sh
#! /bin/bash
CONF=/etc/backup/$HOST.conf
if [ ! -f $CONF ] ; then
  echo "SRC=/home\nTRG=/data/backup" > $CONF
fi
source $CONF
<<<<<<< HEAD
date "+%Y.%m.%sd %H:%M: Starting backup $SRC" >>/var/log/backup.log
cp -a $SRC $TRG
date "+%Y.%m.%sd %H:%M: Finished" >>/var/log/backup.log
=======
rsync $1 --delete -a $SRC $TRG
>>>>>>> origin/master

Beheben des Konflikts von backup.sh:

cat >backup.sh <<'EOS'
#! /bin/bash
CONF=/etc/backup/$HOST.conf
if [ ! -f $CONF ] ; then
  echo "SRC=/home\nTRG=/data/backup" > $CONF
fi
source $CONF
date "+%Y.%m.%sd %H:%M: Starting backup $SRC" >>/var/log/backup.log
rsync $1 --delete -a $SRC $TRG
date "+%Y.%m.%sd %H:%M: Finished" >>/var/log/backup.log
EOS

Der zweite Konflikt (releasenotes.txt):

cat releasenotes.txt
V0.1: Backup durch kopieren
V0.2: Nutzen einer hostspezifischen Konfiguration
<<<<<<< HEAD
V0.3: Logging
=======
V0.3: More performance using rsync
>>>>>>> origin/master

Beheben:

 perl -ni -e 'print unless /^(<<|==|>>)/;' releasenotes.txt
 echo "V0.4: Logging and rsync" >>releasenotes.txt

Jetzt sollte der Commit klappen:

 git commit -m "Logging and rsync" -a
 git tag -m "Logging and rsync" v0.4
 gitk --all

Datei:Gitk-backup-alice-nach-mergen-origin-master.png

Änderungen ins Depot bringen[Bearbeiten]

Jetzt kann Alice den Abgleich ins Depot nochmal probieren:

 git push
To /opt/git-depot/backup.git
60ba035..71d2af8  master -> master
 gitk --all

Datei:Gitk-backup-alice-v0.4.png

Damit sind die Änderungen von Bob und Alice im Depot, unser Ziel ist erreicht.

Zusammenfassung[Bearbeiten]

Die normale Vorgehensweise im Umgang mit einem Depot:

  • Einrichten einer Kopie des Depots:
    • git clone <depot>
  • Änderungen im lokalen Repository durchführen.

Wenn die Entwicklung einen Stand hat, die ins Depot zurückfließen soll:

  • Eigenen Entwicklungszweig in den Master bringen, wenn ein solcher existiert:
    • git checkout master
    • git merge dev
    • Wenn Konflikte auftreten, diese bereinigen und Ergebnis committen:
      • git commit -m "kommentar" -a
  • Änderungen aus dem Depot holen und mit master zusammenführen:
    • git pull
  • Zusammengeführten Branch ins Depot bringen
    • git push