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.

    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.

  • 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 bei git fetch und git 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.

    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 Zeile pick durch r (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)'