GIT-Tutorial: Grundlagen (lokales Repository)
Vorbemerkung
Dieser Teil führt in die grundlegenden Arbeiten mit GIT ein. Als Beispiel wird ein Backupscript entwickelt. Das Tutorial setzt keine Kenntnis von Versionskontrollsystem voraus, aber das Arbeiten mit der Konsole muss vertraut sein.
Anlegen des Repositories
Das Repository ist ein Verzeichnisbaum. In ihm findet die Pflege der Dateien statt (Arbeitsverzeichnis, "working directory"), es ist aber auch die GIT-Datenbank enthalten.
REP=/opt/git/backup
sudo mkdir -p $REP
sudo chmod uog+rwx $REP
cd $REP
git init
Initialized empty Git repository in /opt/git/backup/.git/
find
. ./.git ./.git/hooks ./.git/hooks/update.sample ... ./.git/info/exclude
Wir sehen, dass das Unterverzeichnis .git angelegt wurde, die Datenbank von GIT.
Datei ins Repository bringen
Erstellen der ersten Quelldatei:
cat >backup.sh <<EOS
#! /bin/sh
cp -a /home /data/backup
EOS
ls -l
-rw-r--r-- 1 hm hm 41 23. Aug 20:33 backup.sh
Jetzt schauen wir uns an, was GIT zu unserem Werk meint:
git status
# On branch master # Initial commit # Untracked files: # (use "git add <file>..." to include in what will be committed) # backup.sh
GIT hat bemerkt, dass im Arbeitsverzeichnis eine Datei erstellt wurde. Sie gehört aber noch nicht zum Repository ("untracked"). Wir müssen explizit sagen, wenn die Datei "dazugehören" soll:
git add backup.sh
git status
# On branch master # Initial commit # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # new file: backup.sh
Damit ist backup.sh "unter Aufsicht", jedoch noch nicht in der Datenbank. Das erreichen wir mit
git commit -m "Backup mittels Kopieren" backup.sh
[master (root-commit) 2d6da1e] Backup mittels Kopieren 1 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 backup.sh
git status
# On branch master nothing to commit (working directory clean)
Da fällt uns auf, dass als /bin/sh verwendet wird, wir aber mit dieser Einfachvariante nicht zurechtkommen. Wir wollen mit /bin/bash arbeiten:
cat >backup.sh <<EOS
#! /bin/bash
cp -a /home /data/backup
EOS
Änderungen anzeigen
Ob GIT was von der Änderung merkt?
git status
# On branch master # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # modified: backup.sh
Mit GIT können wir den Unterschied zur Version in der Datenbank anzeigen lassen:
git diff backup.sh
diff --git a/backup.sh b/backup.sh index efc03ba..e23c985 100644 --- a/backup.sh +++ b/backup.sh @@ -1,2 +1,2 @@ -#! /bin/sh +#! /bin/bash
cp -a /home /data/backup
Komfortabler geht es mit einem GUI-Difftool, z.B. kdiff3:
git difftool backup.sh
Dazu muss GIT allerdings passend konfiguriert werden: Siehe GIT-Tutorial: Konfiguration
git commit -m "/bin/bash statt /bin/sh" backup.sh
[master cac8976] /bin/bash statt /bin/sh 1 files changed, 1 insertions(+), 1 deletions(-) git status # On branch master nothing to commit (working directory clean)
Die Änderung ist in der Datenbank angekommen.
Verarbeitungszustände einer Datei
Eine Datei kann also verschiedene Verarbeitungszustände haben:
- unbeaufsichtigt ("untracked"). Nur im Arbeitsverzeichnis.
- neu ("new") Nur im Arbeitsverzeichnis.
- unverändert ("clean") Identisch im Arbeitsverzeichnis und in der Datenbank.
- verändert ("modified") Unterschiedlich im Arbeitsverzeichnis und in der Datenbank.
Anzeige der Log-Meldungen
Ein anständiges Projekt braucht Release-Notes:
echo "V0.1: Backup durch kopieren" >releasenotes.txt
git add releasenotes.txt
git commit -m "Release-Notes für V0.1" *.txt
git log
commit bc515ac5af1c75e6e9f654171e90512a4e913627 Author: hamatoma <hamatoma@gmx.de> Date: Tue Aug 23 22:08:19 2011 +0200 Release-Notes für V0.1 commit cac89761c748c3221ba20420646672cccc9e681c Author: hamatoma <hamatoma@gmx.de> Date: Tue Aug 23 22:06:06 2011 +0200 /bin/bash statt /bin/sh commit df231468f88d5f49ca9a171015471ed041d6d4c8 Author: hamatoma <hamatoma@gmx.de> Date: Tue Aug 23 21:56:04 2011 +0200 Backup mittels Kopieren
Mit dem log-Kommando sehen wir die Historie des Projekts. Hier tauchen die Texte auf, die wir beim Commit mit der -m-Option angegeben haben. Es ist also wichtig, beim Commit informative Texte als Kommentar anzugeben!
Tag erstellen
Unser Script ist soweit funktionstüchtig, also wollen wir den Zustand markieren. Diese Markierung wird "Tag" genannt. Ein Tag hat einen Namen und einen Kommentar:
git tag -m "Backup mittels Kopieren" v0.1
git tag
v0.1
git log
Unter GIT sind Tags nur Namen für einen Commit. Sie haben den Vorteil, mit "git tag" gelistet werden zu können und sprechendere Namen zu haben als die SHA-1-Hashes der Commits.
Branch einrichten
Unser Backupscript funktioniert, kann also produktiv eingesetzt werden. Andererseits ist es verbesserungsfähig. Damit die Produktionsversion aber erhalten bleibt, legen wir einen Entwicklungszweig ("Branch") an:
git branch dev
git branch
dev * master
Es werden zwei Branches angezeigt, der neue "dev" und der "master". Letzterer ist der Branch, der automatisch mit Anlegen eines Repositories vorhanden ist. Der '*' zeigt den aktiven Branch an: Das Arbeitsverzeichnis ist immer einem Branch zugeordnet. Wir wechseln in den Branch dev:
git checkout dev
Switched to branch 'dev'
git branch
* dev master
Aha, jetzt ist dev als aktiver Branch eingestellt.
Änderungen im neuen Branch
Eine bahnbrechende Idee: Nutzung des Scripts auf verschiedenen Rechnern, die unterschiedliche Sicherungsverzeichnisse haben. Also jetzt eine Version, die die Konfiguration aus einer rechnerspezifischen Datei holt:
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
cp -a $SRC $TRG
EOS
echo >>releasenotes.txt "V0.2: Nutzen einer hostspezifischen Konfiguration"
git status
# On branch dev # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # modified: backup.sh # modified: releasenotes.txt
git commit -m "hostspezifischen Konfiguration" -a
[dev 96b634d] hostspezifischen Konfiguration 2 files changed, 7 insertions(+), 1 deletions(-)
git tag -m "hostspezifischen Konfiguration" v0.2
Die Option -a bewirkt, dass der Index angepasst und die Änderungen dann ins die Datenbank übernommen werden. Da keine Dateien angegeben sind, werden alle geänderten Dateien committed, hier also backup.sh und releasenotes.txt.
gitk --all
Datei:Gitk-backup-v0.2-dev.png
gitk ist ein GUI-Programm, das umfangreiche Anzeige- und Suchmöglichkeiten für GIT-Repositories bietet.
Mergen
Das Script bewährt sich, wir lassen es produktiv gehen: Es soll in den master-Branch übernommen werden. Das Zusammenführen von Entwicklungszweigen wird "Mergen" genannt. Zuerst stellen wir den zu änderenden Branch ein, also master:
git checkout master
Switched to branch 'master'
Die Änderungen von dev nach master übernehmen:
git merge -v dev
Fast-forward backup.sh | 7 ++++++- releasenotes.txt | 1 + 2 files changed, 7 insertions(+), 1 deletions(-) git log --graph --pretty=oneline --abbrev-commit * 96b634d hostspezifischen Konfiguration * bc515ac Release-Notes für V0.1 * cac8976 /bin/bash statt /bin/sh * df23146 Backup mittels Kopieren
Das letzte log-Kommando mit den vielen Optionen liefert eine kompaktere Information als ohne Optionen. Ist eine GUI vorhanden, ist gitk bequemer und ansprechender:
gitk --all
Wir sehen, die Historie von dev ist jetzt in die Historie von master übernommen worden.