Erweitertes Mergen (GIT)

Aus Siduction Wiki DE
Wechseln zu: Navigation, Suche

GIT-Tutorial: Übersicht

Ausgangspunkt

Wir verwenden das Repository aus der Kapitel Grundlagen: lokales Repository (GIT).

Wenn nicht vohanden, ist es schnell hergestellt:

 BASE=~/git/
 mkdir -p $BASE
 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

Gitk-backup-v0.2.png

Ä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 ~/git/backup
 git branch dev
 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
 gitk --all

Gitk-backup-v0.3 dev.png

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
 git difftool backup.sh

Meld erw mergen exp backup.png

 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

Gitk-backup-v0.3 experim.png

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.

Was ist ein Konflikt?

  • Zustand 1: A B
  • Zustand 2a: A X B
  • Zustand 2b: A Y B

Zustand 2a und Zustand 2b sind jeweils aus Zustand 1 entstanden. Ein VCS erkennt, dass zwischen A und B jeweils ein anderer Wert (X bzw. Y) eingefügt wurde. Es kann jedoch nicht wissen, welches der denkbaren Ergebnisse eines Zusammenführens korrekt ist:

  • A X B
  • A Y B
  • A X Y B
  • A Y X B
  • A Z B (wobei Z weder X noch Y ist)

Markieren von Konflikten

 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 in beiden Dateien Konfliktmarkierungen angebracht 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 ("date... cp... date...") ersetzt, in experim durch eine andere Zeile ("rsync...").

 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

Gitk-backup-v0.3 merge dev master.png

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

Gitk-backup-v03-3.png