Git Best Practices#
Macht früh Commits!
Macht euren ersten Commit nachdem ihr die initiale Installation fertiggestellt habt und noch bevor ihr erste Änderungen vornehmt. Für ein Cookiecutter-Template z.B. nach den folgenden Schritten:
$ pipenv run cookiecutter https://github.com/veit/cookiecutter-namespace-template.git full_name [Veit Schiele]: email [veit@cusy.io]: github_username [veit]: project_name [cusy.example]: …
Falls in eurem Projekt noch keine
.gitignore
-Datei vorhanden ist, solltet ihr diese anlegen und zumindest.ipynb_checkpoints
und*/.ipynb_checkpoints/*
ausschließen:Falls ihr versehentlich schon entsprechende Dateien in euer Git-Repository eingecheckt habt, könnt ihr diese wieder entfernen mit:
$ git rm -r .ipynb_checkpoints/
Eine Übersicht über weitere
.gitignore
-Einträge erhaltet ihr entweder im Repository dotfiles oder auf der Website gitignore.io.Anschließend können diese initialen Änderungen eingecheckt werden mit:
$ cd cusy.example $ git init $ git add * $ git add .gitignore $ git commit -m 'Initial commit' $ git remote add origin ssh://git@github.com:veit/cusy.example.git $ git push -u origin main
Auch eine
README.rst
-Datei sollte in jedem Repository vorhanden sein, in der das Deployment und der grundsätzliche Aufbau des Codes beschrieben wird.Macht oft Commits!
Dies erleichtert euch:
die Eingrenzung von Fehlern
das Verständnis für den Code
die zukünftige Wartung und Pflege.
Falls ihr doch einmal mehrere Änderungen an einer Datei durchgeführt habt, könnt ihr diese auch später noch in mehrere Commits aufteilen mit:
$ git add -p my-changed-file.py
Ändert nicht die veröffentlichte Historie!
Auch wenn ihr zu einem späteren Zeitpunkt herausfindet, dass ein Commit, der mit
git push
bereits veröffentlicht wurde, einen oder mehrere Fehler enthält, so solltet ihr dennoch niemals versuchen, diesen Commit ungeschehen zu machen. Vielmehr solltest Du durch weitere Commits den oder die aufgetretenen Fehler zu beheben.Wählt einen Git-Workflow!
Wählt einen Workflow, der am besten zu eurem Projekt passt. Projekte sind keineswegs identisch und ein Workflow, der zu einem Projekt passt, muss nicht zwingend auch in einem anderen Projekt passen. Auch kann sich initial ein anderer Workflow empfehlen als im weiteren Fortschritt des Projekts.
Macht sinnvolle Commits!
Mit dem Erstellen aufschlussreicher und beschreibender Commit-Nachrichten erleichtert ihr die Arbeit im Team ungemein. Sie ermöglichen anderen, eure Änderungen zu verstehen. Auch sind sie zu einem späteren Zeitpunkt hilfreich um nachvollziehen zu können, welches Ziel mit dem Code erreicht werden sollte.
Üblicherweise sollten kurze, 50–72 Zeichen lange Nachrichten angegeben werden, die in einer Zeile ausgegeben werden, z.B. mit
git log --oneline
.Mit
git blame
könnt ihr euch auch später noch für jede Zeile angeben lassen, in welcher Revision und von welchem Autor sie kam. Weitere Informationen hierzu findet ihr in der Git-Dokumentation: git-blame.Wenn ihr Gitmojis in euren Commit-Nachrichten verwendet, könnt ihr später leicht die Absicht des Commits erkennen.
Bemerkung
GitLab interpretiert bestimmte Commit-Nachrichten auch als Links, z.B.:
$ git commit -m "Awesome commit message (Fix #21 and close group/otherproject#22)"
zu Issues:
#123
auch in anderen Projekten:
othergroup/otherproject#123
zu Merge Requests:
!123
zu Snippets:
$123
Dabei sollte es zu jedem Commit mindestens ein Ticket geben, das ausführlichere Hinweise zu den Änderungen geben sollte.
Bemerkung
Wartet euer Repository regelmäßig!
Folgende Wartungsarbeiten solltet ihr regelmäßig durchführen:
Validiert das Repo mit
git fsck
.Komprimiert das Repo mit
git gc
bzw.git gc --aggressive
.Bereinigt die Remote Tracking Branches mit
git remote update --prune
. Noch besser ist, wenn ihr die Standardeinstellung so ändert, dass entfernt gelöschte Zweige auch beigit fetch
undgit pull
bei euch lokal gelöscht werden. Dies erreicht ihr mit:$ git config --global fetch.prune true
Überprüft vergessene Arbeiten mit
git stash list
.
Überprüft eure Repositories regelmäßig auf unerwünschte Dateien!
Mit Gitleaks könnt ihr eure Repositories regelmäßig auf ungewollt gespeicherte Zugangsdaten überprüfen.
Ihr könnt Gitleaks auch automatisch als GitLab-Action ausführen. Hierzu müsst ihr die Secret-Detection.gitlab-ci.yml-Vorlage z.B. in eine Stufe namens
secrets-detection
in eurer.gitlab-ci.yml
-Datei einbinden:stages: - secrets-detection gitleaks: stage: secrets-detection include: - template: Security/Secret-Detection.gitlab-ci.yml
Die Vorlage erstellt Secret Detection-Aufträge in eurer CI/CD-Pipeline und durchsucht den Quellcode eures Projekts nach Secrets. Die Ergebnisse werden als Secret Detection Report Artefakt gespeichert, den ihr später herunterladen und analysieren könnt.
Siehe auch
Mit git-filter-repo könnt ihr unerwünschte Dateien, seien es Zugangsdaten oder große Binärdateien aus eurer Git-Historie entfernen.
Alternativ könnt ihr auch auf der Kommandozeile die Daten löschen.
Löschen des letzten Commits
$ git reset HEAD^ --hard $ git push origin -f
Löschen anderer Commits
$ git rebase -i SHA origin/main
-i
interaktiver Modus, in dem euer Standardeditor geöffnet wird und eine Liste aller Commits nach dem zu entfernenden Commit mit dem Hash-Wert
SHA
angezeigt wird, z.B.:pick d82199e Update readme pick 410266e Change import for the interface …
Wenn ihr nun eine Zeile entfernt, so wird dieser Commit nach dem Speichern und Schließen des Editors gelöscht. Anschließend kann das entfernte Repository aktualisiert werden mit:
$ git push origin HEAD:main -f
Ändern einer Commit-Nachricht
Dies lässt sich ebenfalls einfach mit
rebase
realisieren wobei ihr in eurem Editor nicht die Zeile löschen sondern in der Zeilepick
durchr
(reword) ersetzen müsst.Entfernen einer Datei aus der Historie
Eine Datei kann vollständig aus Git-Historie des aktuellen Branches entfernt werden mit:
$ git filter-repo --invert-paths --path path/somefile $ git push --no-verify --mirror
Bemerkung
Informiert die Team-Mitglieder, dass sie erneut einen Klon des Repository erstellen sollten.
Entfernen einer Zeichenkette aus der Historie
$ git filter-repo --message-callback 'return re.sub(b"^git-svn-id:.*\n", b"", message, flags=re.MULTILINE)'
Siehe auch