GIT-Tutorial: Erweitertes Mergen

Aus Info-Theke
Zur Navigation springen Zur Suche springen

GIT-Tutorial: Übersicht

Ausgangspunkt[Bearbeiten]

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

Datei:Gitk-backup-v0.2.png

Änderung im Branch "dev"[Bearbeiten]

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"[Bearbeiten]

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[Bearbeiten]

 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

Datei:Gitk-backup-v03.png

Mergen[Bearbeiten]

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...[Bearbeiten]

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[Bearbeiten]

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

Datei:Gitk-backup-v03-2.png

Zusammenführen aller Branche[Bearbeiten]

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

Datei:Gitk-backup-v03-3.png