Inhaltsverzeichnis

GitHub

Wichtige Commands

svn checkout: git clone linkZuRepo
svn commit: git commit (-a)
svn up: git pull (zuerst alles commiten!)
svn switch: git checkout (-b) nameDesBranches
svn status: git status (-s)
svn info: git show

Aller Anfang

Damit man nicht immer user/pass eingeben muss, kann man bei github einen public key eintragen und 2 factor auth zu aktivieren schadet auch nicht :-)

Damit commits als github User aufscheinen muss man die Mailadresse (die auch github wissen muss) so lokal konfigurieren:

git config --global user.email "XYZ@technikum-wien.at"

git commit (-a)

Um etwas zu commiten muss es zum „git index“ geaddet werden (git add). Diese Dateien in der aktuellen Version sind dann im index („staged for commit“). Ändert man noch etwas bei einer dieser Dateien muss man sie nochmal adden.

git commit commited alle Änderungen die im index („staged“) sind.

-a erspart das adden. Es staged und commited alle Dateien die schon mal im repository vorhanden waren.

git pull

Holt sich die Änderungen (git fetch) von den remotes (github) und merged (git merge) es ins lokale repository in den aktuellen branch. D.h. wenn es Änderungen gibt, ist git pull auch automatisch gleich ein commit.

Damit man mit den lokalen Änderungen nicht durcheinander, kommt sollte vorher alles lokale commited werden.

Falls bereits lokale Änderungen im Master vorhanden sind wird automatisch ein Merge Commit erzeugt. Um das zu verhindern kann

git pull --rebase

verwendet werden.

Alternative zu merge commit: git rebase

Rebase without tears

Hintergrund: Man arbeitet lokal an einem Fix/Feature, hat bereits eine history (ein paar commits) und benötigt jetzt eine Änderung die irgendjemand gepusht hat. rebasing erzeugt eine sauberere history als ständige merge commits.

Hab es gerade so ausprobiert und geschafft \o/:

Wechsel auf den Branch. Hol die letzten Änderungen von github vom Branch „master“ und rebase deine Änderungen darauf.

# Zuerst master updaten
git checkout master
git pull

# Jetzt den branch rebasen
git checkout mein-feature-branch
git rebase master

Merge (Fast Forward) die Änderungen vom Branch. Push.

git checkout master
git merge mein-feature-branch
git push

In diesem Fall wird die gesamte history (alle commits) vom branch in den master mitgenommen. Wenn das nicht gewollt ist, kann man dem merge-Befehl noch den Parameter --squash mitgeben. Muss dann aber noch einen extra commit durchführen. Git befüllt in diesem Fall die commit message bereits mit allen möglichen Infos.

git checkout master
git merge --squash mein-feature-branch
git commit -a
git push

Wenn man danach mit dem branch noch weiter arbeiten möchte, muss man den Startpunkt ändern (wo zweigt der branch ab).

git checkout master
git branch -f mein-feature-branch <letzterCommit>

Oder branch einfach löschen.

git branch -D mein-feature-branch

Soll ein neuer lokaler Branch für alle zur Verfügung stehen, kann dieser mit folgendem Befehl auf Github gepusht werden

git push origin mein-feature-branch

Damit danach ein status/pull/push korrekt funktioniert muss noch folgender Befehl ausgeführt werden

git branch --set-upstream-to=origin/mein-feature-branch mein-feature-branch

git checkout (-b) nameDesBranches

git checkout nameDesBranches wechselt auf einen bestehenden branch mit Namen „nameDesBranches“.

Wenn man einen neuen branch anfangen will kann man ihn mit -b erstellen und direkt hin switchen.

git status (-s)

Ist sehr detailliert. -s kürzt es ab.

git tag -a nameDesTags

Markiert eine bestimmte Version/Revision. Hilfreich zB wenn man festhalten will welche Version aktuell auf Produktion ist. Ermöglicht dann auch einen einfachen Rollback bei Fehlern zu vorigen Versionen.

git stash

Will man zB auf einen anderen branch wechseln ohne die aktuellen Änderungen zu commiten oder zu verwerfen kann man sie „stashen“. Nach git stash hat man einen sauberen directory tree und kann branch wechseln, commiten, testen usw.

Um die Änderungen wieder auf den aktuellen branch anzuwenden gibts folgende Befehle:

git stash apply
git stash pop
git stash apply --index
git stash pop --index

commit rückgängig machen

Jeder commit hat einen Hash (vergleichbar mit Revisionsnummer). Sehen kann man diese hashes über git log.

commit 1ece8a2f6be4429b3b9ddc934da5030389f7ecb1
Author: Robert Hofer <robert.hofer@technikum-wien.at>
Date:   Tue Jan 20 10:34:08 2015 +0100

    erster commit

Um zu einem vorigen commit zu springen benötigt man diesen:

git checkout 1ece8a2f6be4429b3b9ddc934da5030389f7ecb1

Das Ganze geht auch kürzer:

$ git log --oneline
8d9a142 Squashed commit of the following:
6121e0e acht
08d267d Squashed commit of the following:
37fa721 drei
274478b zwei
1ece8a2 erster commit
$ git checkout 1ece8a2

Vom hash reichen also auch die ersten 7 Stellen aus.

Working Copy zurücksetzen

Wenn bereits lokale Commits vorhanden sind die verworfen werden sollen kann der aktuelle stand des Remote repositorys geholt werden mit:

Auf Branch ci
Ihr Branch ist vor 'origin/ci' um 30 Commits.
  (benutzen Sie "git push", um lokale Commits zu publizieren)
nichts zu committen, Arbeitsverzeichnis unverändert

Diese können mit folgenden Befehl verworfen werden:

git reset --hard origin/ci

wobei ci der name des Remote Branch ist.

Branch Merge

Wenn die Entwicklung in einem eigenen Branch stattfindet können die Änderungen vom Master in den Branch übernommen werden damit der Branch wieder am aktuellen Stand ist.
1. Schritt: Master aktualisieren

git checkout master
git pull

2. Schritt: Branch aktualisieren

git checkout ci
git pull

3. Schritt: Änderungen vom Master in den Branch mergen (Man muss sich im Branch befinden)

git merge master

Wenn es zu Konflikten kommt müssen diese aufgelöst werden. Mit 'git status' bekommt man eine Übersicht über den aktuellen Stand.
Soll bei einem Konflikt die Version des Branches übernommen werden kann das mit folgendem Befehl gemacht werden:

git checkout --ours datei.php

Soll stattdessen die Version aus dem Master übernommen werden:

git checkout --theirs datei.php

Anschließend wird die korrigierte Datei hinzugefügt:

git add datei.php

Wenn alle Konflikte behoben sind werden die Änderungen commited:

git commit

Und nach dem testen gepusht:

git push

Andere interessante Befehle

git reset: zB git reset HEAD index.php
git mv config.server1.php config.server2.php
git rm index.php

Branch auf Commandline anzeigen

Um den aktuellen Branch direkt im Prompt auf der Commandline anzuzeigen kann die Variable $(__git_ps1) in der Datei ~/.bashrc gesetzt werden:

PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\[\033[0;32m\]$(__git_ps1)\[\033[0m\]\$ '

Um zusätzlich anzuzeigen ob es dort Änderungen gibt kann folgende Zeile hinzugefügt werden:

export GIT_PS1_SHOWDIRTYSTATE=1

Alias

In der Datei ~/.gitconfig können Alias Befehle gesetzt werden um zB formatierte Logeinträge leichter anzuzeigen:

[alias]
    ci = commit
    lc = log ORIG_HEAD.. --stat --no-merges
    st = status
    co = checkout
    lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative

Workflow

Um in einem Projekt zu arbeiten ist der normale Workflow: klonen, branch erstellen (passiert nur lokal), developen/commiten bis es passt, in den master mergen, master pushen

Die Grafiken in der git doku sagen mehr als 1000 Worte. Und der Guide schaut auch übersichtlich aus.

Aktuelle git Version installieren

Für debian gibt es nur relativ alte git Versionen (max. 1.9 über backport). Aktuell sind sie aber bei 2.3.0. Die Version muss man selbst kompilieren. Und zwar so:

sudo apt-get install autoconf libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
sudo apt-get remove git
wget https://www.kernel.org/pub/software/scm/git/git-X.Y.Z.tar.gz
tar -zxf git-X.Y.Z.tar.gz
cd git-X.Y.Z
make configure
./configure --prefix=/usr
make all doc info
sudo make install install-doc install-html install-info
cd ..
rm -r git-X.Y.Z

Siehe auch Installing Git

git url alias

Um zum Beispiel https URLs auf ssh URLs umzuschreiben kann man in ~/.gitconfig folgenden Eintrag machen:

[url "git://git@github.com:"]
    insteadOf = https://github.com/

https://github.com/ wird jetzt immer durch git://git@github.com: ersetzt.

Damit dieses Alias bei git submodule greift, müssen vorher in .git/config die submodule gelöscht werden. Beispiel:

[submodule "submodules/tablesorter"]
    url = git@github.com:christianbach/tablesorter.git

Diesen Eintrag entfernen. Den Ordner samt submodule (sicherheitshalber) löschen. Und dann

git submodule init
git submodule update

.git/config kontrollieren, hier sollten jetzt die ssh URLs eingetragen sein.