====== Git ======
===== Branches anlegen =====
* Annahmen: Es wird ein branch ausgehend vom aktuellen Branch angelegt. Dieser wird bereits getrackt.
* Branch lokal anlegen
git checkout -b
* Lokalen Branch pushen, der entsprechende Remotebranch wird automatisch angelegt.
git push -u origin
===== Branches löschen =====
Angelegte Branches müssen lokal und auf dem Server separat gelöscht werden.
Lokal:
git checkout master
git branch -d
Auf dem Server:
git push origin :
===== Branches umbenennen =====
Stellt man während der Arbeit fest, dass der Branchname nicht gut passt, lassen sich lokale Branches einfach umbenennen:
git branch -m old_branch new_branch
===== Staging =====
git add -A #alle Änderungen in den Stagingbereich übernehmen
git add . #neue und geänderte (keine gelöschten) Dateien in Stagingbereich übernehmen
git add -u #geänderte und gelöschte (keine neuen) Dateien in Stagingbereich übernehmen
===== Nur Teile einer Datei stagen =====
Um nur einen Teil der Änderungung in einer Datei zu stagen, gibt es den Befehl
git add -p filename.x
^Taste^Bedeutung^
|s| teilt in kleinere Teile|
|y| staged den aktuellen Teil|
|n| aktuellen Teil nicht stagen|
|?| Hilfe|
===== Lokales Git Repo auf Server pushen =====
Hat man ein lokales Git-Repo, kann man es mit
git remote add origin https://server/user/repo.git
git push -u origin master # --all für alle lokalen Branches
auf den Server pushen. Wichtig ist das -u beim push, dann wird der branch getrackt. Das bedeutet, das Änderungen vom Server auch wieder zurück in das lokale Repo übernommen werden.
===== Farbige Ausgabe =====
Um die farbige Ausgabe global zu aktivieren:
git config --global color.ui true
===== Nur aktuellen Branch pushen =====
Ein "git push" in der Standardeinstellung pusht alle lokalen Branches. Möchte man mit git push nur den aktuellen Branch pushen, kann man git entsprechend konfigurieren:
git config --global push.default simple
===== Fehlerhafte Commit-Message korrigieren =====
Hat man sich bei der letzten Commit-Message vertippt, kann diese mit
git commit --amend
(öffnet einen Editor, in dem die fehlerhafte Nachricht bearbeitet werden kann) bzw.
git commit --amend -m "correct commit message"
korrigiert werden.
===== URL des Repositorys anzeigen =====
Um sich die URL des aktuellen Repositorys anzeigen zu lassen, kann man diesen Befehl verwenden:
git remote show origin
Ein (fast) vollständiger Ersatz für "svn info" ist [[http://justamemo.com/2009/02/09/git-info-almost-like-svn-info/|hier]] beschrieben.
===== Einzelne Dateien aus Stash holen =====
Um einzelne Dateien aus dem Stash zurückzuholen, kann man den Befehl
git checkout stash@{0} filename
benutzen. Diese Datei ist dann automatisch im Staging-Bereich.
===== Inhalt des Stash anzeigen =====
Um den Inhalt des Stash anzuzeigen, kann der Befehl
git stash show -p
verwendet werden.
Ältere Stashes können mit
git stash show -p stash@{1}
angezeigt werden.
===== Grafisches git blame =====
Mit
git gui blame filename
lässt sich ein grafischen Tool starten, mit dem man sich alle Änderung an einer Zeile in der Vergangenheit ansehen kann.
===== Zeilenumbruch (CRLF und LF) =====
Windows verwendet die beiden Zeichen CRLF, während Linux nur LF als Zeilenumbruch verwendet. Dies kann zu Problemen führen, wenn man ein Repo mit beiden Systemen benutzt oder Code mit unpassender Zeilenumbruchskodierung einfügen möchte. git kann diese Probleme automatisch beheben. Dazu existieren zwei Möglichkeiten: die eine, ältere setzt eine Konfiguration bei jedem Benutzer voraus, die andere wird im Repo abgelegt und gilt daher für alle.
Genauere Beschreibungen:
* [[http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/|Mind the End of Your Line]]
* [[http://stackoverflow.com/a/1967986|Antwort auf Stack Overflow]]
* [[https://help.github.com/articles/dealing-with-line-endings| Dealing with line endings]]
==== Konfiguration für jeden Benutzer ====
Bei dieser Vorgehensweise wird abhängig vom Betriebssystem der Parameter autocrlf gesetzt, unter Linux
git config --global core.autocrlf = input
bzw. unter Windows
git config --global core.autocrlf = true
Als zusätzlich Sicherheitsmaßname sollte safecrlf gesetzt werden, damit git prüft, ob eine Rückumwandlung möglich ist:
git config --global core.safecrlf = true
==== Konfiguration für ganzes Repo ====
Seit git 1.7.2 lässt sich eine Datei .gitattributes anlegen, mit der das Verhalten für das gesamte Repo konfiguriert werden kann. Durch Einträge wie
*.txt text
lässt sich für jede Dateiendung einzeln entscheiden, ob git eine Normalisierung der Zeilenumbrüche auf LF beim commiten durchführt. Beim Ausschecken wird gemäß der Konfigurationsvariablen core.eol ggfls. eine Rückumwandlung durchgeführt. Den Defaultwert nativ sollte man nicht verändern, so dass man unter Windows CRLF und unter Linux LF als Zeilenumbruch erhält.
Git kann in .gitattributes auch angewiesen werden, alle Textdateien automatisch zu erkennen und umzuwandeln.
* text=auto
===== Wortbasierter Diff =====
Mit
git diff --word-diff
lässt sich ein wortbasierter Diff durchführen. Für viele Sprachen enthält Git angepasste Parser. Um diese auszuwählen muss in .gitattributes für die Dateieindung die entsprechene Sprache ausgewählt werden, z.B.:
*.m diff=matlab
Dabei dürfen keine Leerzeichen zwischen diff, dem Gleichheitszeichen und der Sprache stehen.
Eine Liste der unterstützten Sprachen findet sich im [[https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html|Abschnitt "Defining a custom hunk-header"]].
===== Editor für Commit-Message setzen =====
Der Editor, den Git zum Bearbeiten der Commit-Messages aufruft, kann auf mehrere Arten konfiguriert werden. Mit der Konfigurationsvariablen core.editor
git config --global core.editor "nano"
oder den Umgebungsvariablen GIT_EDITOR, VISUAL, EDITOR
export GIT_EDITOR=nano
export VISUAL=nano
export EDITOR=nano
Die Reihenfolge der Auswertung ist GIT_EDITOR, core.editor, VISUAL, EDITOR.
===== Mehrere Remotes =====
git kann mehrere remotes verwalten. Das ist für das Pushen auf mehrere Server praktisch.
Remote hinzufügen:
git remote add
Pushen:
git push
===== Dateien, die nicht im Repo sind, entfernen =====
Dateien, die nicht im Repository sind (untracked), können mit ''git clean'' entfernt werden. Mit
git clean -n
wird ein Trockenlauf durchgeführt. Mit dem Parameter ''-f'' statt ''-n'' wird dann tatsächlich gelöscht. Um ungetrackte Verzeichnisse zu entfernen, muss das Argument ''-d'' hinzugefügt werden.
===== Alle Commits eines Autors anzeigen =====
Um alle Commits eines bestimmten Autors aufzulisten, kann man folgenden Befehl verwendet:
git log --author="name"
Der Name muss nicht vollständig angegeben werden.
Statt des Namens kann auch eine Email-Adresse (oder ein Teil davon) angegeben werden.
Um nicht nur den aktuellen Branch, sondern alle zu durchsuchen, kann der Parameter ''%%--%%all'' hinzugefügt werden.
===== Prüfen, ob Branch einen Commit enthält =====
Um zu prüfen, ob ein Branch einen gegebenen Commit enthält kann man den folgenden Befehl verwenden:
git branch -a --contains
Commits, die über einen Rebase oder Cherry-Pick ins Repo gekommen sind, werden so nicht gefunden.
===== Autor nachträglich ändern =====
Um den Autor oder die Emailadresse nachträglich zu korrigieren, müssen folgendene Schritte durchgeführt werden:
* [[https://gist.github.com/octocat/0831f3fbd83ac4d46451|Skript]] herunterladen und ausführbar machen
* Emailadressen im Skript anpassen
* Skript ausführen
* Änderungen pushen
Diese Operation schreibt die History neu.
Wenn die Commits schon öffentlich sind, sollte man dies nur in Ausnahmefällen tun.
===== Sparse Checkout =====
Um nur Teile (z.B. ein Unterzeichnis) eines Repositories auszuchecken, kann ein sog. Sparse Checkout gemacht werden:
* https://unix.stackexchange.com/a/468182
* https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/
===== Branch in eigenes Repository =====
Um einen Branch ''branch-to-move'' in ein eigenes Repository zu kopieren kann folgendes verwendet werden:
git push url://to/new/repository.git branch-to-move:new-branch-name
''new-branch-name'' ist der Name, den der Branch im neuen Repository gekommen soll.
''url%%://%%to/new/repository.git'' ist der Pfad zum git-Repository, dies kann auch ein lokaler Pfad sein.
===== Leere Verzeichnisse commiten =====
Leere Verzeichnisse lassen sich nicht einchecken, der [[https://stackoverflow.com/questions/115983/how-can-i-add-an-empty-directory-to-a-git-repository/932982#932982|hier]] empfohlenen Workaround ist eine ''.gitignore''-Datei in dem Verzeichnis mit folgendem Inhalt:
# Ignore everything in this directory
*
# Except this file
!.gitignore
Andere Möglichkeit sind leere Dateien wie ''.keep'' oder ''.gitkeep'' in dem Verzeichnis.
Eine Diskussion dazu findet sich auch in obigem Link.
===== git pull oder fetch hängt =====
Wenn ''git pull'' oder ''fetch'' hängt, kann man ''git'' mit
GIT_TRACE=true git pull
ein Trace einschalten.
Auch die Verwendung des von Github deaktivierten, unverschlüsselten [[https://github.blog/changelog/2022-03-15-removed-unencrypted-git-protocol-and-certain-ssh-keys/| ''git://''-Protokolls]] ruft dieses Verhalten hervor (dies lässt sich im o.g. Trace allerdings nicht erkennen).
===== git Archive =====
Um einen Branch in eine Zip-Datei zu packen, können die folgenden Kommandos verwendet werden:
git archive -o zipfile.zip master #master Branch
git archive -o zipfile.zip HEAD #aktueller Branch
===== Nützliche Aliases =====
Diese Aliases können in die ~/.gitconfig eingetragen werden:
[alias]
st = status
ci = commit
br = branch
co = checkout
df = diff
sed = ! git grep -z --full-name -l '.' | xargs -0 sed -i -e
ack = grep --break --heading --line-number #git grep with output like ack
# List all aliases.
aliases = config --get-regexp alias
# Fix whitespace from here:
# http://code.google.com/p/nathan-collins--conf/source/browse/dot.gitconfig
# Fix whitespace in the index while preserving a dirty tree, if
# any.
#
# Assuming your index is empty, some useful variations are:
#
# - fix whitespace in all changes in all versioned files:
#
# git add -u :/ && git fixws && git reset
#
# - fix whitespace in all unversioned files and in all changes in
# all versioned files:
#
# git add --all :/ && git fixws && git reset
#
# Logic:
#
# The 'git stash save' fails if the tree is clean (instead of
# creating an empty stash :P). So, we only 'stash' and 'pop' if
# the tree is dirty.
#
# The 'git rebase --whitespace=fix HEAD~' throws away the commit
# if it's empty, and adding '--keep-empty' prevents the whitespace
# from being fixed. So, we first check that the index is dirty.
#
# Also:
# - '(! git diff-index --quiet --cached HEAD)' is true (zero) if
# the index is dirty
# - '(! git diff-files --quiet .)' is true if the tree is dirty
#
# The 'rebase --whitespace=fix' trick is from here:
# http://stackoverflow.com/a/19156679/470844
fixws = !"\
if (! git diff-files --quiet .) && \
(! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git stash save FIXWS_SAVE_TREE && \
git rebase --whitespace=fix HEAD~ && \
git reset --soft HEAD~ && \
git stash pop ; \
elif (! git diff-index --quiet --cached HEAD) ; then \
git commit -m FIXWS_SAVE_INDEX && \
git rebase --whitespace=fix HEAD~ && \
git reset --soft HEAD~ ; \
fi"
#resets binary permission to the ones in the repo
# from https://gist.github.com/jtdp/5443498
permission-resetb = "!git diff -p --no-ext-diff --no-color --diff-filter=d | grep -E \"^(diff|old mode|new mode)\" | sed -e \"s/^old/NEW/;s/^new/old/;s/^NEW/new/\" | git apply"
''git sed'' ersetzt in allen Dateien im Repository old-name durch new-name (siehe Bespiel). Dies ist sicherer als die entsprechende Lösung mit "find .", da dabei Verwaltungsdateien von Git mit verändert werden können.
Beispiel:
git sed 's/old-name/new-name/g'
===== Links =====
* [[http://git-scm.com/|Git Homepage]]
* [[https://www.atlassian.com/git/tutorials|Git Tutorials]]
* [[https://chrisjean.com/git-submodules-adding-using-removing-and-updating/|Git Submodule Tutorial]]