GIT-Tutorial: Erweitertes Mergen
Ausgangspunkt
Wir verwenden das Repository aus der Kapitel GIT-Tutorial: Grundlagen (lokales Repository).
Wenn nicht vohanden, ist es schnell hergestellt:
BASE=/opt/git/
sudo mkdir -p $REP
sudo chmod uog+rwx $REP
cd $BASE
git clone git://f-r-e-i.de/backup
cd backup
git remote rm origin
Das Repository wird aus dem Netz kopiert "(clone")und dann der Rückbezug zum Depot entfernt ("remote rm"). Ohne das Entfernen wären Branche sichtbar, die wir hier nicht brauchen. Nähreres siehe GIT-Tutorial: Verwenden eines zentralen Repositories.
gitk
Änderung im Branch "dev"
Unser Backupscript soll dokumentieren, von wann bis wann es gelaufen ist.
Brav nach Konvention wird dies nicht im Produktivzweig master, sondern im Entwickungszweig "dev" geändert:
cd /opt/git/backup
git checkout dev
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
Und ab ins Repository:
git commit -m "Logging" -a
git tag -m "V0.3dv Logging" v0.3dv
Die Releasenotes anpassen:
echo >>releasenotes.txt "V0.3dv: Logging"
git commit -m "Release notes completed" -a
Neuer Branch "experim"
Einfach nur Kopieren ist nicht der Weisheit letzter Schluss: Dateien bleiben im Backup stehen, wenn sie im Orginal gelöscht werden. Außerdem wird jede Datei immer kopiert, auch wenn sie sich nicht geändert hat. rsync kann das besser als cp.
Für diese neue Entwickung machen wir einen neuen Zweig auf, wobei wir vom Produktivzweig ausgehen:
git checkout master
git branch experim
git checkout experim
Switched to branch 'experim'
Hier die Quellcodeänderung:
perl -pi -e 's/cp/rsync \$1 --delete'/ backup.sh
echo "V0.3ex: rsync instead of cp" >>releasenotes.txt
git commit -m "rsync instead of cp" -a
git tag -m "V0.3ex rsync instead of cp" v0.3ex
Stand vor dem Mergen
git log --graph --pretty=oneline --abbrev-commit --branches
* d999ce7 Release notes completed * 22e6899 Logging | * 24861a3 rsync instead of cp |/ * 96b634d hostspezifischen Konfiguration * bc515ac Release-Notes für V0.1 * cac8976 /bin/bash statt /bin/sh * df23146 Backup mittels Kopieren
Graphisch anspruchvoller ist die Ausgabe von gitk:
gitk --all
Mergen
Der Zweig experim soll jetzt in den Zweig dev übernommen werden:
git checkout dev
git merge -v experim
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.
Konflikt erkennen...
Was ist passiert? Es ist ein Konflikt ist aufgetreten, und zwar in beiden Dateien.
git status
# On branch dev # Unmerged paths: # (use "git add/rm <file>..." as appropriate to mark resolution) # both modified: backup.sh # both modified: releasenotes.txt
Git sagt uns, dass beide Dateien geändert wurden, schauen wir uns die Änderungen an:
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 >>>>>>> experim
GIT hat die Bereiche markiert, die einen Konflikt darstellen: Die beiden Branche dev und experim haben eine gemeinsame Historie bis zum Tag v0.2. Dann wude die letzte Zeile in dev durch die letzten 3 Zeilen ersetzt, in experim durch eine andere Zeile.
cat releasenotes.txt
V0.1: Backup durch kopieren V0.2: Nutzen einer hostspezifischen Konfiguration <<<<<<< HEAD V0.3dv: Logging ======= V0.3ex: rsync instead of cp >>>>>>> experim
...und beheben
GIT kann nicht entscheiden, was korrekt ist. Das müssen wir schon selbst erledigen: Wir entfernen die Markierungen und verschieben die letzte Zeile zwischen die Log-Zeilen:
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
Bei den Releasenotes ist es noch einfacher, hier braucht es nur ein Entfernen der Konfliktmarkierungen. Zusätzlich tragen wir gleich die Version V0.3 ein:
perl -ni -e 'print unless /^(<<|==|>>)/;' releasenotes.txt
echo "V0.3: Logging and rsync" >>releasenotes.txt
Jetzt bleib uns noch, GIT über das Fertigstellen der Konfliktlösung zu informieren...
git add backup.sh releasenotes.txt
... und mit einem Commit den Merge abzuschließen:
git commit -m "Logging and rsync" -a
git tag -m "Logging and rsync" v0.3
gitk --all
Zusammenführen aller Branche
Die Version in dev hat sich bewährt, daher soll sie jetzt für alle 3 Zweige gelten: Wir mergen dev und experim nach master:
git checkout master
git merge dev experim
Fast-forwarding to: dev Already up-to-date with experim Merge made by octopus. backup.sh | 4 +++- releasenotes.txt | 2 ++ 2 files changed, 5 insertions(+), 1 deletions(-) mode change 100644 => 100755 backup.sh gitk --branches