Deutsch English
Dein Feedback:
Hat die Seite Deine Erwartung erfüllt? vote3 Ja
vote2 Teilweise
vote1 Nein
Noch ein Kommentar?

Nur falls, Du eine Antwort erwartest, Deine E-Mailadresse

Gegebenenfalls noch Dein Name

Do not change this:
Feedback
Suchen

Versionsverwaltung

Diese Seite behandelt Versionsverwaltungen.
05-06-2006 16.45

Subversion (svn)

Subversion ist eines der nützlichsten Dienste überhaupt wenn man auf verschiedenen Computern an seinen Dateien arbeiten möchte ohne die Ergebnisse immer per Hand überall synchronisieren zu müssen.
Hier ist das Subversion Handbuch (Schnellstart)
mkdir -p /usr/local/var/my_svn/
svnadmin create /usr/local/var/my_svn/
mkdir -p ~/foo/; cd ~/foo/
svn co file:///usr/local/var/my_svn/
svn add ...
svn diff -r HEAD
svn diff -r 3:5
svn diff -r {2004-11-28\ 15:30}
svn update
svn commit
Die Datei FOO als binär markieren
svn propset svn:mime-type 'application/octet-stream' FOO
svn proplist -v FOO
svn diff mit Argumenten starten (z.B. um leere Zeile zu ignorieren)
svn diff --diff-cmd diff -x -iEbBu
Um diese Option permanent zu aktivieren einfach in ~/.subversion/config als diff Befehl ein kleines Shellscript angeben.
Die aktuelle Version in trunk kopieren, z.B. um neue, experimentelle Funktionen entwickeln zu können
# svn copy trunk branch/beta1
# svn ci branch/beta1
Committed revision 123.
Änderungen mit dem alten Code mischen:
# cd trunk/
# svn log --stop-on-copy ../branch/beta1
# svn diff -r 123:HEAD ../branch/beta1
# svn merge -r 123:HEAD ../branch/beta1
So sieht eine Apache2 Konfiguration aus die unter /usr/local/var/repositories/svn/NAME Subversion Repositories über die URL http://HOSTNAME/repositories/svn/NAME zur Verfügung stellt:
<Location                     /repositories/svn/>
DAV svn
SVNParentPath /usr/local/var/repositories/svn/
AuthType Basic
AuthName "My Subversion Repository"
AuthUserFile /usr/local/var/repositories/svn/user_passwd
Satisfy Any
Require valid-user
AuthzSVNAccessFile /usr/local/var/repositories/svn/user_authorisation
</Location>
Und so kann man die Rechte unter den Benutzer verteilen:
user_authorisation
## Default is NO
[/]
* =

[REPOS1:/]
usera = rw
userb = r

[REPOS1:/trunk/test]
userb = rw

Zeilenumbruch für eine Datei festlegen
Property:
svn:eol-style LF
svn:eol-style CRLF
svn:eol-style native

Dateien ausschließen
Property:
svn:ignore *

Einen Ordner ohne seinen Inhalt einem Repository hinzufügen
svn add --depth=empty foo

Keine Passworte speichern
~/.subversion/config

[auth]
store-passwords = no
store-auth-creds = no

Winmerge und Subversion

In Winmerge die ganzen .svn Ordner automatisch ignorieren
Winmerge -> Tools -> Filters -> FileFilters -> New -> For all Users -> Install

Diese Datei ablegen und dort auswählen
WinmergeSVNFilter.txt
Ab sofort ignoriert Winmerge .svn Dateien
20-09-2014 11.00

git

Links


Grundlagen

  • großteils vom git Tutorial übernommen
  • git-gui und gitk --all sind gut geeignet um Auswirkungen der Befehle zu beobachten
  • Im Abschnitt SPECIFYING REVISIONS in git-rev-parse(1) enthält eine Reihe Möglichkeiten eine Revision in git zu benennen

Neues Repository starten

Sich gegenüber git vorstellen
git-config --global user.name "Mr Foo"
git-config --global user.email "foo@example.com"

Entweder einen neuen, leeren Ordner anlegen ...
mkdir project
cd project
git-init # git-init-db
... oder einen vorhandenen Ordner nutzen
tar xzf project.tar.gz
cd project
git-init # git init-db

Hinweis: gitk funktioniert in neu angelegt git Repositories erst nach dem ersten Commit. Ansonsten erscheint folgende Fehlermeldung
Error in startup script: child process exited abnormally
while executing
"close $refd"
(procedure "readrefs" line 47)
invoked from within
"readrefs"
(file "/usr/bin/gitk" line 6370)

Alles im Ordner dem Repository hinzufügen und committen
git-add .
git-add--interactive
git-commit

Änderungen ins lokale Repository übernehmen

Erst mal sehen was verändert wurde
git-diff
git-diff path/to/file

Im Gegensatz zu Subversion muss man vor dem commit nochmal alle Dateien auswählen die für den commit relevant sind. Das geht ebenfalls mit git-add
git-add path/to/file
Man kann sie auch sehr bequem mit git-gui auswählen.

Nachdem man die betroffenen Dateien mit git-add übernommen hat, sind die anstehenden Änderungen mit einem einfachen git-diff nicht mehr zu sehen. Man kann sie sich aber trotzdem ansehen
git-diff --cached
git-diff --cached path/to/file

Die ausgewählten Änderungen committen.
git-commit path/to/new/file
git-commit -m "* Bla bla" path/to/new/file

Man kann aber auch alle veränderten Dateien committen ohne dass man sie mit git-add nochmal explizit hinzufügen muss
git-commit -a

Wenn man mit dem letzten Commit nicht zufrieden ist lässt sich noch schnell korrigieren
git-commit --amend
Alternativ
git-reset --soft HEAD^
...
git-commit -c ORIG_HEAD


Änderungen anzeigen
git-diff

git-diff --color --color-words
git-diff --ignore-space-at-eol --ignore-space-change
git-diff -- path/to/file

git-diff HEAD -- path/to/file
git-diff HEAD^ -- path/to/file
git-diff HEAD^^ -- path/to/file
git-diff HEAD^^ HEAD^ -- path/to/file

git-diff 68fcc0 ef6274 -- path/to/file
git-diff HEAD ef6274 -- path/to/file
git-diff ef6274 ef6274^ -- path/to/file
git-diff master experimental -- path/to/file
git-diff master origin/master -- path/to/file

git-whatchanged 68fcc0 ef6274 -- path/to/file

git-diff --name-only 68fcc0 ef6274

git-status

git-log

Nur bestimmt Änderungen anzeigen, z.B. nur gelöschte Dateien oder nur veränderte Dateien
git diff --diff-filter=D --name-only
git diff --diff-filter=M --name-only

Dateien löschen und aus dem Repository entfernen
rm path/to/file # git-rm path/to/file

Dateien nur aus dem Repository löschen
git-rm --cached foo

Anzeigen wer was in einer Datei verändert hat
git-gui blame foo/bar/file.cpp

Dateien vom Repository ausschließen

Es gibt zwei Möglichkeiten Dateien aus dem Repository auszuschließen
  • Mann kann in der Datei .git/info/exclude Dateien ausschließen. Diese Einstellungen gelten dann aber nur für das lokale Repository, sie werden nicht an die anderen Entwickler verteilt.
    # (1)
    foo.txt
    # (2)
    *.html
    # (3)
    !foo.html
    # (4)
    *.[oa]
  • Man kann eine Datei namens .gitignore in einem der Ordner des Repositories anlegen. Die Einstellungen in dieser Datei gelten für den Ordner in dem sie liegt und alle Unterordner. Diese Variante hat den Vorteil dass man die Datei selbst auch dem Repository hinzufügen kann und so alle Entwickler von Ihr profitieren können. Falls man alle Dateien ab einem bestimmten Ordner ausschließen will daran denken die .gitignore nicht auszuschließen wenn man sie verteilt wissen will ;-)
    *
    !.gitignore
Weiter Informationen finden sich in gitignore(5).

Patches

Unterschiede im Repository in per E-Mail versendbare Patches umwandeln und in den angegebenen Ordner speichern.
git-format-patch --numbered --thread -o /tmp/mypatches/ HEAD^^ HEAD
git-format-patch --numbered --thread -o /tmp/mypatches/ -2

Alle Commits die im Branch origin sind, aber nicht im aktuellen Branch als Patch abspeichern
git-format-patch                     -o /tmp/mypatches/ origin

Alle patches die in einer mbox liegen extrahieren und auf den aktuellen Branch anwenden
git-am mymbox
git-format-patch -k --stdout HEAD^^ HEAD | git-am --3way --keep

Patches per E-Mail versenden (lässt man Empfänger oder Absender weg wird der automatisch aus Repository extrahiert)
git-send-email --from foo@example.com --envelope-sender foo@example.com --to bar@example.com  /tmp/mypatches/

Einen Patch anwenden
git-apply --check   foo.patch
git-apply foo.patch
git-apply --reject foo.patch
git-apply --reverse foo.patch

Einen Commit auf den aktuellen Branch anwenden
git-cherry-pick f6a2c

Wartung

Repository durch Komprimierung beschleunigen
(regelmäßig anwenden)
git-gc

Repository auf Fehler überprüfen
git-fsck

Alte Versionen von Dateien erhalten

Alte Version der Datei ansehen
git-show abcde:path/to/file
git-show HEAD:path/to/file
git-show HEAD^:path/to/file
git-show HEAD^^:path/to/file
git-show HEAD~3:path/to/file
Alte Version der Datei wiederherstellen
git-checkout HEAD^ path/to/file

Tags

Ein Tag setzten
git-tag v1.0

Branches

Einen neuen Branch anlegen und in ihn wechseln
git-branch experimental; git-checkout experimental
git-checkout -b experimental

Alle Branches anzeigen
git-branch
git-branch -r
git-branch -a

Der aktuelle Branch
ls -l .git/HEAD

Den Branch wechseln
git-checkout experimental

Zur ursprünglichen zurückwechseln
git-checkout master

Alle lokalen Änderungen im Branch die noch nicht committet wurden rückgängig machen
git-checkout -f

Änderungen aus experimental übernehmen
git-pull . experimental

Branch löschen
git-branch -D experimental

Branch wieder vereinigen
Der aktuelle Branch erhält alle Änderungen aus dem Branch experimental
git-merge experimental
Konflikt beim Mergen vereinigen
git-add path/to/new/file
git-commit

rebase
Angenommen folgende Branches
     -->A-->B-->C foo
/
D-->E-->F-->G master

Man will den foo Zweig
A-->B-->C

Auf den Kopf des master Zweiges draufsetzten
             -->A-->B-->C foo
/
D-->E-->F-->G master

Ist man schon im foo Zweig reicht ein
git-rebase master
um als Aufsetzpunkt für den aktuellen Zweig den Kopf des master Zweiges zu setzen.

Ansonsten kann man mit
git-rebase master foo
unabhängig vom aktuellen Zweig den foo Zweig auf den Kopf des master Zweiges setzten.

Schließlich kann man noch einen beliebigen Zweig ab einer beliebigen Stelle auf einen beliebiegen anderen Zweig draufsetzten. Aus
              F-->G-->H bar
/
C-->D-->E foo
/
A-->B master

wird mit
git-rebase --onto master foo bar

dann

     C-->D-->E  foo
/
A-->B master
\
F-->G-->H bar

Branch Strategien

Teamarbeit

Angenommen Alice hat ein git repository in /home/alice/project, jetzt möchte Bob ihr helfen und am Projekt mitarbeiten. Mit dem folgenden Befehl bekommt er einen Klon des Repositories in den Ordner myrepo.
git-clone /home/alice/project myrepo

Nach dem Klonen eines entfernten Repositories findet man einen Zweig vor, master
git branch
* master

Das entfernte Repository kann natürlich zusätzliche Zweige beinhalten. Glücklicherweise stehen diese auch bereit
git branch -r
git branch -a

Man kann sich jetzt entweder sofort den Inhalt dieser Zweige erst einmal ansehen
git checkout origin/SuperBranchNr1

Oder aber man erzeugt einen entsprechenden lokalen Zweig, der automatisch so konfiguriert wird, dass er Änderungen per Default mit dem entfernten Branch abgleicht
git branch --track SuperBranchNr1 origin/SuperBranchNr1

Bob muss keine URL angeben um Updates von Alice zu ziehen
git-pull

Nachdem er Änderungen commited hat kann Alice sie direkt in ihr Repository übernehmen.
git-pull /home/bob/myrepo

Wenn Bob neue Zweige erzeugt hat, kann er sie so in Alicess Repository kopieren
git push --all origin

So kann er einen einzelnen neuen Zweig namens MyNewBranch in das entfernte Repository origin kopieren
git-push origin MyNewBranch

Man kann auch erst mal nur die Änderungen herunterladen ohne sie gleich anzuwenden
git-fetch /home/bob/myrepo

Es ist auch möglich mehr als ein entferntes Repository einzurichten. So kann man ein weiteres hinzufügen
git remote add origin git@foo/bar
git remote add origin2 git://foo/bar
git remote add origin3 ssh://user@foo.bar/~/foobar.git

Zeige alle entfernten Repositories
git remote show
git remote show origin

Entferne ein entferntes Repository
git remote rm origin2

git Server aufsetzten

Möglich über verschiedene Protokolle:
  • git-deamon
    Schnell, nur lesender Zugriff
  • http
    Langsamer, dafür kein Problem hinter restriktiven Firewalls. Normalerweise auch nur lesend.
  • ssh
    Schreibender Zugriff
  • Zugriff über lokales Dateisystem
    Schnell, schreibender Zugriff möglich
Anleitung öffentliches git Repository einrichten.

Beispiel für einen git deamon server
Server, hat einen Ordner als Basis, z.B. /var/cache/git
git-daemon --verbose --base-path=/var/cache/git

Client, wir wollen ein vorhandenes Repository (z.B. /home/foo/bar) exportieren
git-clone --bare /home/foo/bar MyFirstRepository.git
Zum Export freigeben:
touch MyFirstRepository.git/git-daemon-export-ok
Diesen Ordner auf den Server kopieren
scp -r MyFirstRepository.git myserver.example.com:/var/cache/git/
Ab jetzt sollte es möglich sein das Repository per git zu ziehen
git-clone git://myserver.example.com/MyFirstRepository.git

Beispiel für einen git ssh server
Wir wenden wieder clone auf ein Repository an (oder benutzen ein bereits vorhandenes)
git-clone --bare /home/foo/bar MyFirstRepository.git
Einen neuen User erzeugen, z.B. git mit dem wir uns via ssh einloggen (man kann natürlich auch einen vorhandenen User benutzen).
Wenn man einen neuen User für den git ssh Zugang benutzt, sollte man überlegen den User auf die Shell /usr/bin/git-shell zu beschränken (/etc/passwd)
So kann man einen anderen Port für den ssh Dienst nutzen, der über ssh angeboten wird
git clone ssh://git@foo.bar:9418/~/foo.git

Subversion und git

Ein Subversion Repository einmalig in ein git repository importieren.
git-svnimport http://example.com/mysvnrepository
Erwartet wird per Default die empfohlene Subversion Struktur:
trunk/
branches/foo
branches/bar
branches/...
mit entsprechenden Kommandozeilenparametern können aber auch andere Strukturen vermittelt werden.

In einem meiner Projekte wurde anfangs kein trunk Ordner benutzt. Dann wurde in einem Commit ein trunk und ein branches Ordner angelegt und alle Dateien in den trunk Ordner verschoben. Da die ersten Commits direkt in das Repository gingen und nicht in einen Order (wie z.B. trunk), kann git-svnimport damit noch nicht umgehen (Stand August 2007). Es gibt aber einen kleinen Patch mit dem git-svnimport mit leeren trunk Ordnern umgehen kann. In meinem Projekt wurde ab Revision 325 dann ein trunk Ordner angelegt und alle Dateien und Ordner dorthin verschoben.
Hat man eine Version von git-importsvn die mit leeren trunk Ordnern umgehen kann funktioniert der Import zweistufig:
git-svnimport         -s   1 -T ''      -l 324 http://example.com/myproject
git-svnimport -o tmp1 -s 325 -T 'trunk' http://example.com/myproject
git-checkout tmp1
git-rebase master
Das Mischen der beiden Teile benötigte allerdings einige manuelle Eingriffe.

Will man sowohl git als auch Subversion verwenden lohnt sich vielleicht ein Blick auf git-svn:
git-svn init

git rückgängig machen

Wenn etwas schief ging kann man als letzten Schritt versuchen die letzten git Aktionen rückgängig zu machen
# git reflog
24f34f2... HEAD@{0}: pull : Fast forward
68fh47g... HEAD@{1}: checkout: moving to master
90cdrt3... HEAD@{2}: pull : Fast forward
62dgs35... HEAD@{3}: rebase: ...

# git reset --hard HEAD@{1}

Fehler finden mit bisec

Wenn das aktuelle Projekt einen Fehlverhalten zeigt dass in früheren Versionen noch nicht enthalten war, kann man mit git-bisec die Version markieren die noch funktioniert hat und git-bisec findet dann die Änderung die das Problem verursacht.
git-bisect start
git-bisect bad
git-bisect good v2.6.13-rc2

Jetzt erhält man eine Version zwischen der funktionierenden und der kaputten. Nach einem teste gibt man wieder an ob das Problem dort enthalten ist oder nicht.
git-bisect good
Wenn man das Problem gefunden hat kann man bisec beenden und zurück zur aktuellsten Version gehen
git-bisect reset

Kernel

Das (komplette!) Kernel Repository von Linus ziehen
git-clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linux-2.6
Achtung in diesem git Repository befinden sich keine Tags für stabile kernel Zweig. Wenn man diesen verfolgen möchte also lieber das git für den stabilen Kernel benutzen
git-clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.16.y.git
Dieser hat Tags für den stabilen Kernel Zweig.

Alle verfügbaren Tags auflisten
ls .git/refs/tags/

Wenn man schon den Zweig vom Linus git geladen hat kann man den Ordner als Quelle für das git des stabilen Zweiges nutzen (ungetestet, geht erst ab git 1.3)
git-clone --reference oldfolder git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.16.y.git newfolder

Die Veränderung in der der Datei MAKEFILE aufzeigen
git-diff v2.6.17-rc4..HEAD Makefile

Einen neuen Branch erzeugen und den Kernel mit dem gegebenen Tag in ihn kopieren (benötigt keine Netzwerkverbindung wenn man schon das aktuelle Repository hat).
Mit diesem Befehl kann man also einen bestimmten Kernel aus dem git extrahieren.
git-checkout -f master
git-pull
git-checkout -f -b my-new-branch tags/v2.6.16.19
04-08-2010 00.07
Powered by PHP Created with Xemacs Valid XHTML 1.0! Valid CSS!