Git

Spickzettel für die Versionsverwaltung Git.

Weblinks

Tägliches Arbeiten

Lokales Repo aktualisieren:

git pull

Lokales Repo aktualisieren mit Rebase statt Merge:

git pull --rebase

Entferntes Repo aktualisieren:

git push

Status zeigen:

git status

Dateien ignorieren:

echo "filename" > .gitignore

Interaktiv per Diff Code-Teile zum commit vormerken:

git add -p

Dateien hinzufügen (= zum commit vormerken):

git add filename

Alles hinzufügen aber trotzdem im Diff anzeigen:

git add -N .

Datei doch nicht in commit aufnehmen (git add rückgängig machen):

git reset filename

Datei reverten:

git checkout filename

Gelöschte Datei wieder herstellen:

git checkout HEAD^ filename

Diff anzeigen - Änderungen, die noch nicht staged (also für den Commit vorgesehen) sind:

git diff

Diff anzeigen - Änderungen, die mit "git commit" (ohne -a) committed würden:

git diff --cached

Diff anzeigen - Änderungen, die mit "git commit -a" committed würden:

git diff HEAD

Die letzte commit-Message ändern oder Dateien zum letzten Commit hinzufügen:

git commit --amend

Letzten Commit rückgängig machen (Details siehe Quelle):

git reset --soft HEAD^

Ins lokale Repo commiten:

git commit -m "Commit message"

Ins lokale Repo commiten und alles adden (Achtung: Neue Dateien werden nicht geaddet):

git commit -am "Commit message"

Graphische Oberfläche anzeigen:

gitk

Dateien entfernen (vor erstem Commit):

git rm --cached filename

Verzeichnisse entfernen (vor erstem Commit):

git rm --cached -r dirname

Diff einer eingecheckten Revision anzeigen:

git show <rev>

Git-Repo prüfen:

git fsck

Garbage Collection durchführen - entfernt staged, aber nie committete Dateien (dangling blob) und Commits, die nicht im Baum hängen (dangling commits):

git gc

Branchen und mergen

Details siehe Basic Branching and Merging

git branch experimental      # Neuen Branch anlegen
git branch                   # Vorhandene Branches anzeigen
git checkout experimental    # Zu anderem Branch wechseln
git commit -am "Bla"         # Commit im Branch experimental
git checkout master          # Zum Master-Branch wechseln
git commit -am "Blubb"       # Commit im Master-Branch
git merge experimental       # Branch experimental in master hinein mergen
git diff                     # Eventuelle Konflikte anzeigen
git commit -am "Blablubb"    # Konfliktlösung committen
gitk                         # History ansehen
git branch -d experimental   # Branch experimental löschen

Branch pushen:

git push -u origin mybranch

Alle Branches (auch Remote-Branches) anzeigen:

git branch -a

Remote-Branch auschecken:

git checkout -b mybranch origin/mybranch

Remote-Branch löschen:

git push origin --delete mybranch

Branch mergen ohne Auto-Commit (So dass man den Merge noch bearbeiten kann):

git merge mybranch --no-commit --no-ff

Merge abbrechen:

git reset --hard HEAD

Branch auf bestimmten Commit setzen:

git checkout mybranch
git reset --hard 1258f0d0aae

Taggen

Tag erstellen:

git tag mytag

Tag verschieben:

git tag -f mytag
git push --tags

Tag in Remote-Repo löschen:

git tag -d mytag
git push origin :refs/tags/mytag

Tag umbenennen:

git tag new old
git tag -d old
git push origin :refs/tags/old
git push --tags

Stashen

Stash schnell erstellen (alle Dateien außer neue):

git stash

Stash mit Beschreibung erstellen (alle Dateien außer neue):

git stash save 'My description'

Stash erstellen, 'staged' Dateien behalten (-k für 'keep index'):

git stash save -k 'My description'

Stash erstellen mit allen Dateien (-u für 'untracked'):

git stash save -u 'My description'

Stash-Stack ansehen:

git stash list

Letzten Stash zurückholen:

git stash pop

Patchen

Details siehe Blog-Artikel Patch-Workflows: git format-patch, git apply-patch, git am

Patch aus Änderungen im aktuellen Arbeitsverzeichnis erzeugen:

git diff --cached > mypatch.patch

"Normalen" Patch anwenden (ohne Mail-Header, also ohne Commit-Message und Autor):

git apply mypatch.patch

Patch Series erzeugen (als Mail - mit Commit-Message und Autor):

git format-patch -M [rev1]..[rev2]

Patch-Mails anwenden (am = apply mail - übernimmt Commit-Message und Autor):

git am < 0001-first-change.patch
git am < 0002-next-change.patch
...

3-Wege-Merge, wenn sich Patch-Mail nicht anwenden lässt:

git am -3 < 0001-first-change.patch

Repo anlegen

Repo anlegen (lokal):

cd myproject
git init
git add .

Repo anlegen (auf Server):

cd www-data/my-dav
sudo -u www-data mkdir my-new-repo.git
cd my-new-repo.git
sudo -u www-data git --bare init
sudo -u www-data git --bare update-server-info
mv hooks/post-update.sample hooks/post-update

Repo klonen (von Server nach lokal):

export GIT_SSL_NO_VERIFY=1
git clone https://<server-host>/some/path/my-repo.git

Entferntes Repo das erste mal aktualisieren (nach Fehlermeldung "No refs in common and none specified; doing nothing."):

git push origin master

Remote-Repo aus einem lokalen Repo erstellen

Details siehe Create a new Git Remote Repository from some local files (or local git repository)

Leeres Remote-Repo anlegen:

mkdir /path/to/new-remote-repo.git
cd /path/to/new-remote-repo.git
git --bare init

Remote-Repo bei lokalem Repo anmelden:

cd /path/to/existing-local-repo
git remote add origin /path/to/new-remote-repo.git

Nur Master-Branch pushen:

git push -u origin master

Alle Branches pushen:

git push origin --all

Alle Tags pushen:

git push origin --tags

Remote-Repo umstellen

URL des Remote-Repo anzeigen:

git remote -v

URL des Remote-Repo ändern:

git remote set-url origin myuser@myserver:/path/to/remote-repo.git

Fork-Repo erstellen

Quelle: Keeping a fork up to date

Fork klonen:

git clone https://github.com/myuser/myforkrepo.git

Original-Repo in Fork-Repo als Remote eintragen und "importieren":

cd into/cloned/fork-repo
git remote add upstream https://github.com/otheruser/originalrepo.git
git fetch upstream

Eingetragene Remotes (origin und upstream) anzeigen:

git remote -v

Fork-Main-Branch anlegen und nach origin pushen:

git checkout [rev]
git branch my-main
git push -u origin my-main

Fork aktualisieren:

git checkout main
git fetch upstream
git fetch origin
git pull upstream main
git push

Submodules

Details siehe:

Submodule zu lokalem Repo hinzufügen:

git submodule add /path/to/lib-repo.git path/to/submodule

Diff mit schönerem Output für Submodules anzeigen:

git diff --submodule

Submodules bei bereits bestehendem lokalen Repo auschecken:

git submodule update --init

Repo zusammen mit Submodules auschecken:

git clone --recurse-submodules /path/to/remote-repo.git

Submodule aktualisieren (master-Branch):

git submodule update --remote name-of-submodule

Anzeigen, welchen Commit Submodule verwendet:

git submodule

Submodule auf anderen Commit umstellen:

cd path/to/submodule
git checkout hash-of-commit

Submodule auf anderen Branch umstellen:

git config -f .gitmodules submodule.name-of-submodule.branch name-of-branch
git submodule update --remote

Submodule entfernen (Details siehe stackoverflow):

git submodule deinit -f -- path/to/submodule
rm -rf .git/modules/path/to/submodule
git rm -f path/to/submodule

git status um Informationen zu Submodules erweitern:

git config status.submodulesummary 1

Nutzer umstellen

Nutzername und Mail-Adresse für ein Repo ändern (für künftige Commits):

cd myrepo
git config user.name "Tim Buktu"
git config user.email "tim@example.com"

Nutzername und Mail-Adresse global ändern (für künftige Commits):

git config --global user.name "Tim Buktu"
git config --global user.email "tim@example.com"

Nutzername und Mail-Adresse bei bestehenden Commits ändern:

git filter-branch --commit-filter 'if [ "$GIT_AUTHOR_EMAIL" = "otto@example.com" ]; then
  export GIT_AUTHOR_NAME="Tim Buktu";
  export GIT_AUTHOR_EMAIL=tim@example.com;
  export GIT_COMMITTER_NAME="Tim Buktu";
  export GIT_COMMITTER_EMAIL=tim@example.com;
fi; git commit-tree "$@"'

Commits squashen

Beschreibung: http://www.gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

Interaktives Rebase starten:

git rebase -i HEAD~5

Installation

Mac - Client

Mit Homebrew:

brew install git

Ubuntu - Client

Kommandozeilen-Client unter Ubuntu:

sudo apt-get install git-core

Konfiguration

git auf englisch umstellen:

echo "alias git='LANG=en_US.UTF-8 git'" >> ~/.bashrc

Farbige Konsolenausgabe aktivieren:

git config --global color.ui auto

Eigene Benutzerdaten festlegen:

git config --global user.name "Your Name"
git config --global user.email you@example.com

Unter Mac verhindern, dass man ständig das Passwort eingeben muss:
Datei ~/.ssh/config mit folgendem Inhalt anlegen (Quelle):

Host *
   AddKeysToAgent yes
   UseKeychain yes
   IdentityFile ~/.ssh/id_rsa

Client für HTTP-Repository konfigurieren

Datei ~/.netrc mit folgendem Inhalt anlegen (sonst muss man sehr oft das Passwort angeben):

machine <server-host>
login <username>
password <password>

Dateirechte anpassen:

chmod 600 ~/.netrc

Entfertes Repo klonen:

git clone https://<server-host>/some/path/my-repo.git

Wenn GIT wegen dem SSL-Zertifikat rumnervt, kann man GIT dazu veranlassen, es nicht zu prüfen:

export GIT_SSL_NO_VERIFY=1

Ubuntu - Shared repository über https

Anleitung angelehnt an: http://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt

Verzeichnis einrichten, das über WebDAV erreichbar ist. Im folgenden heißt dieses Verzeichnis www-data/my-dav.

Neues, leeres Git-Repository anlegen:

cd www-data/my-dav
sudo -u www-data mkdir my-new-repo.git
cd my-new-repo.git
sudo -u www-data git --bare init

Danach:

sudo -u www-data git --bare update-server-info
mv hooks/post-update.sample hooks/post-update