Ankündigung

Einklappen
Keine Ankündigung bisher.

HA - Git-Workflow & Gitea Add-On

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    HA - Git-Workflow & Gitea Add-On

    Anleitung zur Installation von Gitea & Git für HA.

    Eigentlich wollte ich mich mit Git erst dann beschäftigen, wenn ich etwas mehr Linux Kenntnisse hab, aber dann ist mir dieses Gitea Add-On über den Weg gelaufen, und so hab ich den Punkt einfach mal vorgezogen.

    ​Da ich ungefähr null Erfahrung mit Linux und Git habe, ist das eine Anleitung für absolute Neulinge wie mich.

    Ich muss jedoch gestehen, wenn ich von Anfang an gewusst hätte, wie einfach und übersichtlich das alles ist, dann hätte ich mich schon viel früher mit diesem Thema beschäftigt, denn so sind viele Versionsstände meiner HA Entwicklung nicht versioniert worden, und das ist schade. Auch bei so manchen Fehlern hätte ich mir schon öfters mal gewünscht, kurz mal nachsehen zu können, was die letzten Änderungen waren. All das geht jetzt ganz einfach, daher kann ich das jedem nur empfehlen.

    Statt Gitea selbst zu hosten kann man genauso gut natürlich auch GitHub oder GitLab verwenden, das muss halt jeder selbst entscheiden.

    Achtung: Bitte nicht das Gitea Add-On mit der Gitea Integration verwechseln.

    ​Ich beschreibe hier nur das Add-On mit dem man ein Repository erstellen und damit seinen Source-Code versionieren kann.
    Mit der Integration kann man bestehende Repositories tracken, dafür hab ich aber derzeit noch keinen Bedarf.

    Ich habe die Anleitung in 5 Teile gegliedert.

    Teil 1: Installation von Gitea
    Teil 2: Linux & Git Kurzanleitung für Dummies (wie mich)
    Teil 3: Repository Konfiguration
    Teil 4: Die ersten Commits
    Teil 5: Git Anwendung in Studio Code Server

    Installation des Gitea Add-On

    Wer noch nie ein Add-On von alexbelgium instaliert hat, der muss im Add-on Store rechts oben über das 3-Punkte-Menü sein Repository hinzufügen.

    HTML-Code:
    https://github.com/alexbelgium/hassio-addons
    ​

    Danach sollte Gitea gefunden werden und man kann es installieren.
    Bei der Konfiguration hab ich nichts geändert und gleich das Add-On mit der Standard-Konfig gestartet.

    Die Admin-Seite von Gitea wird nicht im HA Menü eingebunden, ich hab sie daher in mein eigenes Menü aufgenommen.

    ​Gitea-Admin-Seite:
    HTML-Code:
    http://homeassistant.local:3000/

    Auf dieser Seite hab ich dann Benutzername, E-Mail und Passwort eingetragen.
    Rechts oben gibt es ein + Symbol, mit dem man Repositories anlegen kann.
    Ich hab mein erstes Repo einfach "homeassistant" genannt und die Sichtbarkeit auf privat gesetzt.

    Das war's auch schon. Ich hab damit Gitea installiert und könnte jetzt sofort mit der Versionierung starten.
    Da ich aber nicht komplett kopflos starten will und auch noch absoluter Anfänger auf dem Gebiet bin, folgt nun Teil 2.

    Zuerst aber noch ein paar mehr oder weniger interessante Links zum nachlesen.

    Version Controlling Your Smart Home: Mastering Home Assistant Configuration with Git

    Mastering Home Assistant Configuration Management with Git: Version Control for a Robust Smart Home

    Config GIT for VSCode editor


    #2
    Teil 2: Linux & Git Kurzanleitung für Dummies

    Zuerst einmal kurz zur Funktionsweise von Git.

    Ich hab mir dazu das Git Buch von Nina Siessegger 2x geholt, einmal aus der Bücherei und dann gleich noch einmal aus der Buchhandlung.

    Es wird immer von einem Repository (ich nenne es einfach nur Repo) gesprochen, eigentlich gibt es sogar 2 davon.

    Das remote-Repo haben wir in Gitea bereits erstellt, ein lokales Repo werden wir im Teil 4 mit "git init" noch erstellen.
    Damit wir dann auch unsere Daten (mit "git push") sichern können, werden wir diese beiden Repos auch (mit "git remote") miteinander verknüpfen.

    Da stellt sich als erstes gleich mal die Frage, wo finde ich in HA eigentlich die Kommandozeile.
    An dieser Stelle bin ich als Linux-Neuling meist etwas nervös, aber es gibt dafür überhaupt keinen Grund.

    Wer in HA den Studio Code Server bereits als Editor in Verwendung hat, der findet rechts oben den Button: Toggle Panel (Ctrl+J)
    VSC - Toggle Panel.png
    Wer ihn noch nicht installiert hat, der sollte genau das jetzt nachholen, denn ohne ihn wird's mühsam.

    Ctrl+J öffnet ein Terminal und die Command Line steht auch bereits im Ordner /homeassistant

    Nur als Hinweis:
    /homeassistant ist ein symlink auf /config, das kann man sich mit dem folgenden Befehl auch anzeigen lassen: realpath .
    Falls man also in einem Forum mal was vom Ordner config liest, dann können wir das mit unserem Ordner gleichsetzen.

    Und noch ein Hinweis:
    Wir lernen jetzt sehr viele git Befehle, werden diese aber im täglichen Einsatz dann eigentlich kaum verwenden, denn unser Editor hat die meisten davon im Gui integriert, dazu aber mehr im Teil 5. Trotzdem halte ich es für sinnvoll, die Basics zu können und sich nicht nur auf das Gui zu verlassen.

    Obwohl wir lokal noch gar kein Repo haben, können wir trotzdem schon mal 3 Files dafür erstellen, denn diese werden wir später dann benötigen.

    README.md ist eine Markdown-Datei die in einem Git-Repo nicht fehlen sollte.
    LICENSE.md (oder einfach nur LICENSE) sollte auch in jedem Projekt vorhanden sein.
    .gitignore ist eine (noch wichtigere) Textdatei, mit der wir festlegen, welche Ordner & Files ausgenommen werden sollen.

    Um mir ein Bild davon zu machen, welche Files ich versionieren will und welche nicht, möchte ich mich nicht nur auf das verlassen was ich im Editor sehe. Viele hidden Files (das sind die mit einem Punkt am Anfang) werden mir im Editor gar nicht angezeigt, auf der Console (mit den richtigen Befehlen) aber schon.

    Es gibt unter Linux 2 sehr einfache Möglichkeiten, sich einen Ordner anzusehen, mit dem Befehl "dir" oder mit "ls". Wer ewig als Linux-Anfänger gelten möchte, der kann den Windows-Befehl "dir" natürlich verwenden, denn genau dafür wurde er in Linux ja auch eingebaut. Alle anderen können gerne hier weiterlesen, denn ich möchte lernen, mit "ls" umzugehen.

    Unter weniger abgespeckten Linux-Systemen könnten wir mit "man <befehl>" oder "info <befehl>" uns ausführliche Information zu jedem Befehl holen, bei HA müssen wir mit "ls --help" auskommen, oder Google bzw. die KI befragen, und so eine KI hat mir dann folgende Befehle gebaut.

    Liste aller Ordner (auch der versteckten) mit Größenangabe
    # summarize device usage, only total (-s), human_readable (-h), only directories (-- */), also hidden dir starting with . (.*/) | sort by key (-k) 2nd column
    HTML-Code:
    du -sh -- */ .*/ | sort -k 2

    Damit sollte es möglich sein, jene Ordner zu finden die wir benötigen, und auch jene, die wir nicht benötigen.

    Liste aller Files mit Größenangabe
    # list all files with long listing format (-l), human_readable (-h), also hidden (-A) | exclude (-v) all lines with directories (lines starting '^' with 'd')
    HTML-Code:
    ls -lhA | grep -v '^d'
    Das gleiche machen wir auch noch mit den Files, und wem die Ausgabe von diesem Befehl zu unübersichtlich ist, dem baut ChatGPT gerne einen noch komplizierteren Befehl mit viel schönerer Ausgabe - es lebe die KI.

    schön formatierte Liste aller Files mit Größenangabe
    # list all files in same format like directories
    HTML-Code:
    find . -maxdepth 1 -type f -exec du -sh {} + | LC_ALL=C sort -k 2 | sed 's|^\(.*\)\./|\1|'
    Da ich lernen möchte, hab ich versucht, alle Befehle auch zu verstehen, kurz nach "sed" hab ich dann aber aufgegeben.

    Im Teil 4 werden wir diese Befehle anwenden. Bevor es so weit ist, möchte ich mir aber noch einen Git-Workflow überlegen.

    Wie bereits erwähnt ist das alles nur zur Übung, im Teil 5 sehen wir uns dann die Möglichkeiten im Gui an.

    Hier einige wichtige Git-Befehle im Schnellkurs.

    git config
    Damit kann man auf 3 Ebenen (system für Computer / global für User über alle Repos / local für jedes einzelne Repo) wichtige Parameter konfigurieren.

    Wir konfigurieren jetzt auf globaler Ebene den eigenen Usernamen & e-Mail.

    HTML-Code:
    git config --global user.name "Your Name"
    git config --global user.email "Your e-Mail"
    Diese Angaben müssen zwar nicht zwingend mit den Angaben im Server-Repo auf der Git-Plattform (also in Gitea) übereinstimmen, im Normalfall werden sie das aber.

    Früher wurde der Haupt-Branch oft als "master" bezeichnet, heute ist aber "main" gebräuchlicher.

    Wir können den Namen des Haupt-Branches als Default hinterlegen.
    ​​
    Die 2. Zeile bewirkt, dass Filenamen in UTF-8 und Umlaute nicht als unlesbare oktale Escape-Sequenzen angezeigt werden.

    HTML-Code:
    git config --global init.defaultBranch main
    git config --global core.quotepath false

    Anzeigen lassen können wir uns diese Config natürlich auch, und wenn wir --no-pager vergessen, dann müssen wir die Anzeige (die dann über less oder more läuft) mit "q" beenden.

    HTML-Code:
    git --no-pager config --list
    Wichtiger Hinweis: Die folgenden Befehle beschreibe ich mal im trockenen, ausführen sollten wir sie aber erst dann, wenn das Kapitel 3 auch abgearbeitet ist.

    HTML-Code:
    git init
    Initialisiert das aktuelle Verzeichnis als lokales Git-Repository und muss nur 1x ausgeführt werden.
    Ab diesem Zeitpunkt ist Git dann in der Lage, alle Änderungen (mit jedem commit) mitzuschreiben.

    HTML-Code:
    git remote add origin http://homeassistant.local:3000/<your_username>/homeassistant.git
    git remote -v
    Damit verbinden wir unser lokales Repo mit dem remote Repo und nennen diese (erste) Verbindung (wie bei git üblich) "origin".
    Solange wir diese Verbindung nicht ändern wollen, muss auch dieser Befehl nicht wiederholt werden.
    Mit dem Parameter -v zeigen wir die gesetzte Verbindung an.

    Zusätzlich zum main Branch gibt es bei größeren Teams noch weitere Branches z.B. für features, bugfixes.
    Um einen Branch zu wechseln gibt es aus historischen Gründen jetzt 2 Befehle, die meisten verwenden immer noch checkout, ich finde switch aber intuitiver.

    HTML-Code:
    git checkout -b <branch>
    # oder
    git switch -c <branch>
    Mit beiden Befehlen kann man einen neuen Branch erstellen und dorthin wechseln.
    Der Wechsel in einen bereits bestehenden Branch geht dann ohne -b oder -c

    HTML-Code:
    git checkout <branch>
    # oder
    git switch <branch>
    ​​Die meisten Teams arbeiten in Git mit einer Vielzahl von Branches (main, feature1, feature2, bugfix, ...)

    Da ich auf absehbare Zeit der einzige Entwickler in unserem Smart-Home bin, werde ich am Beginn nur mit 2 Branches arbeiten: main & dev

    Im dev (Development) Branch werde ich entwickeln, und sobald etwas funktioniert werden die Änderungen in den main übernommen.

    Falls ich für Bugfixing einen weiteren Branch benötige, kann ich den immer noch hinzufügen.

    Hier in diesen Beispielen werde ich jedoch nur am main arbeiten, das ist zwar nicht empfohlen, macht diese Anleitung hier aber etwas schlanker.

    HTML-Code:
    git add <filename>
    Fügt eine Datei zum Staging-Bereich von Git hinzu, nur dieser Bereich wird commitet und mit push dann zum externen Repo übernommen. Es wäre wohl etwas umständlich, wenn wir dafür nicht das Gui des Editors verwenden würden.

    HTML-Code:
    git commit -m "first commit"
    Erstellt einen neuen Commit (Snapshot) mit den Dateien im Staging-Bereich.

    In manchen Projekten werden viele kleine Einzel-Commits zusammengefügt, das geht mit dem Parameter --amend (für ergänzen), ich verwende das aber derzeit noch nicht.

    Auch den Parameter --signoff verwende ich nicht, damit wird ein DCO (Developer Certificate of Origin) also eine Art Unterschrift hinzugefügt: "Signed-off-by: Name <email@adresse.com>"

    HTML-Code:
    git push -u origin main
    Lädt die lokalen Commits vom main-Branch auf das entfernte Repository namens origin hoch (push).

    Der Parameter -u (für --set-upstream) legt origin main als Standard-Upstream für den lokalen Branch fest, sodass weitere git pull und git push Befehle ohne ständige Wiederholung von origin main ausgeführt werden können.

    Das waren die wichtigsten git Befehle, um ein erstes Commit mal zu speichern. Wir erwarten uns von git aber noch viel mehr.

    HTML-Code:
    git log                 # zeigt die neuesten Commits im Remote-Branch
    git fetch               # lädt das remote Repo (per default mit allen Branches) auf das lokale herunter, um den Stand vergleichen zu können, macht aber noch keinen merge (wie bei pull)
    git fetch -p            # -p oder --prune bereinigt die lokalen Branches, falls am Server solche in der Zwischenzeit gelöscht wurden.
    
    git diff                # zeigt alle noch nicht gestagten Änderungen (Staging siehe git add)
    git diff --cached       # zeigt bereits getagte aber noch nicht committete Änderungen
    git diff origin/main    # vergleicht den lokalen Branch mit dem Remote-Branch, Achtung: vorher 'git fetch' aufrufen!
    
    git merge <branch>      # Git erstellt einen neuen „Merge-Commit“, der die Historien beider Branches zusammenführt. (VT: vollständige Historie | NT: bei vielen Merges unübersichtlich)
    git rebase              # Git nimmt die Commits aus einem Branch und „setzt“ sie auf einen neuen Startpunkt, so als wären sie dort entstanden. (VT: lineare Historie | NT: Verzweigungen nicht mehr sichtbar)
    git pull                # holt neue Daten (wie bei fetch) und führt automatisch ein merge am aktiven Branch durch, kann auch Schrittweise erfolgen: git fetch, diff, merge
    
    git status              # vergleicht lokales mit remote Repo und listet auf, welche Files lokal oder remote geändert wurden.
    git branch -vv          # zeigt eine Liste aller lokalen Branches, markiert den aktuellen Branch mit *, zeigt die Verknüpfungen mit remote Branches in [] und jeweils letzte Commit-Nachricht.
    git branch -r           # zeigt eine Liste aller remote Branches.
    git branch --merged     # zeigt alle bereits integrierten Branches.
    git branch              # zeigt an, in welchem Branch wir sind
    
    git clone <url>         # kopiert ein Repo (mit allen Branches und Commits) von remote nach lokal, wenn es lokal noch nicht existiert (im Gegensatz zu pull, wo es lokal bereits existiert)

    Unterschied zwischen clone und fork:

    Clone ist ein git Befehl und kopiert von einem (eigenen oder fremden) remote-Repo zum lokalen Repo.
    Fork ist kein git Befehl, damit kann man auf Gitea, Github oder GitLab ein fremdes remote-Repo zum eigenen remote-Repo kopieren.

    Tipp: Wenn man in einem geforkten Repo Änderungen machen darf, dann kann man upstream auf das Original-Repo setzen, und origin zeigt auf das geforkte Repo.

    HTML-Code:
    git remote add upstream https://github.com/original-author/original-repo.git
    ​​
    Unterschied zwischen merge und rebase:

    ​Änderungen aus feature in main einfügen und einen neuen Merge-Commit erstellen.

    HTML-Code:
    git switch main
    git merge feature

    Commits aus feature nehmen und auf die Spitze von main setzen, so als wären sie direkt dort entstanden.
    Hinweis: rebase ist OK, um lokale Branches aufzuräumen, sollte am Server aber vermieden werden.

    HTML-Code:
    git switch feature
    git rebase main
    Das sind eine ganze Menge an Befehlen und die meisten davon werden wir hoffentlich nie im Terminal händisch eintippen müssen, trotzdem ist es gut, sie zu kennen.

    Ich habe für mich einen Workflow vorbereitet, der zwar für einen Einzel-Entwickler etwas oversized ist, aber wenn ich dann mal in einem Team arbeiten sollte, dann muss ich nicht komplett umlernen.

    Prüfung, ob es im Remote-Repo Änderungen gegeben hat

    HTML-Code:
    git fetch origin                      # lädt das remote Repo auf das lokale herunter (ohne fetch ist der Stand am Server nicht bekannt!)
    git status                            # zeigt, ob der eigene Branch hinter dem Remote liegt
    git log origin/main..HEAD             # zeigt die lokalen Commits, die noch nicht auf dem Server sind
    git diff origin/main                  # zeigt, was sich auf dem Server geändert hat
    git merge origin/main                 # Änderungen vom Server übernehmen, integriert den remote main-Branch in den lokalen main-Branch
    ​

    Code-Entwicklung im dev-Branch

    HTML-Code:
    git switch dev                        # Wechsel in einen bereits bestehenden dev-Branch, beim ersten Mal muss er mit -c noch erstellt werden
    # jetzt werden die Änderungen gemacht
    git add .                             # fügt alle geänderten und neuen Dateien (nicht jedoch gelöschte) im aktuellen Verzeichnis und seinen Unterordnern zur Staging-Area hinzu.
    git add -u                            # fügt alle geänderten und gelöschten Dateien (nicht jedoch neue) hinzu.
    git add -A                            # fügt alles hinzu (geändert, neu, gelöscht) | alternativ: git add --all
    git status                            # zeigt den Staging-Bereich, damit können wir auf vergessene Files kontrollieren
    git status --ignored                  # zeigt zusätzlich auch alle ignorierten Files (das kommt noch in Teil 4)
    git rm -r --cached <file>             # entfernt Files und/oder Folders wieder aus dem Staging-Bereich, mit -r auch Sub-Folders. Achtung: ohne --cached wird (wie bei rm üblich) tatsächlich gelöscht!
    git restore <file>                    # verwirft lokale Änderungen und stellt das Original-File wieder her
    git commit -m "Änderungs-Kommentar"
    git push [-u origin dev]              # lädt die lokalen Commits vom dev-Branch auf das entfernte Repository namens origin hoch, -u muss nur beim ersten mal angeben werden

    Im GUI werden wir alle diese Befehle wiederfinden, den letzten müssen wir im GUI dann aber unterscheiden.
    Push ... git push
    Publish Branch ... git push -u origin <branch>

    Zusammenführen in main (wenn alle Tests positiv sind)

    HTML-Code:
    git switch main                       # Wechsel in den Main-Branch
    git fetch [origin]                    # zur Sicherheit alle Branches vom Server holen, falls es Änderungen gab, origin ist der Default, kann daher entfallen
    git diff origin/main                  # zur Sicherheit anzeigen, ob sich auf dem Server etwas geändert hat
    git merge origin/main                 # zur Sicherheit, falls der main am Server neuer ist als lokal, die Änderungen übernehmen
    git merge dev                         # integriert den lokalen dev-Branch in den lokalen main-Branch
    git push                              # lädt die lokalen Commits vom main-Branch auf das entfernte Repository namens origin hoch
    git switch dev                        # damit wir's nicht vergessen, denn dort werden wir ja weiterarbeiten wollen

    Wenn ein Branch nicht mehr benötigt wird, dann kann er lokal und remote gelöscht werden

    HTML-Code:
    git branch -d dev                     # lokal löschen
    git push origin --delete dev          # remote löschen

    Es gibt noch viele weitere Befehle, die ich als Anfänger nicht so bald einsetzen werden. Hier ein paar davon:

    HTML-Code:
    git stash push -u                         # speichert Änderungen (für kurzfristige Branch-Wechsel) temporär im lokalen Stash-Stack, mit -u (oder --include-untracked) werden auch untracked Files aufgenommen.
    git tag -a <tagname> -m "Message zum Tag" # damit kann man Meilensteine wie z.B. Releases kennzeichnen

    Auch mit Themen wie "cherry-pick", "bisect", "hooks", "submodul", "subtree", "Squash" und vielen weiteren werde ich mich erst dann beschäftigen, wenn ich die Basics besser beherrsche.

    Das klingt jetzt alles viel komplizierter als es ist, aber über's GUI (siehe Teil 5) wird es hoffentlich dann viel einfacher sein. Trotzdem habe ich an mich den Anspruch, das Ganze auch auf Low-Level zumindest mal verstanden zu haben.

    Bei so vielen Befehlen habe ich gerne einen Spickzettel: Git-Cheat-Sheet
    Zuletzt geändert von scw2wi; 05.12.2025, 17:27.

    Kommentar


      #3
      Teil 3: Repository Konfiguration und erste Commits

      Nachdem wir in Teil 2 ausreichend die Grundlagen kennengelernt haben, sollten wir über genügend Know-How verfügen, um das Repo nach unseren Wünschen zu konfigurieren.

      Zuerst werden wir die bereits angesprochenen files README.md und .gitignore erstellen und mit Inhalt füllen.

      Ich hab mir bereits überlegt, welche Ordner und Files ich versionieren möchte, und welche nicht. Genau das möchte ich im README.md dokumentieren.

      Obwohl Mark-Down eine sehr übersichtliche Syntax hat, bin ich trotzdem kein Freund davon, da ich es selten verwende, und es noch dazu mehrere Dialekte gibt.

      Der Studio Code Server bietet für solche Fälle aber die Möglichkeit, hilfreiche Extensions zu installieren, und das werden wir auch gleich machen.

      Im Studio-Code-Server links oben das 5. Symbol (Extensions | Ctrl-Shift-X) anklicken,

      VSC - Extensions.png
      nach "Markdown All in One" (von yzhang) suchen und installieren.

      <Spoiler>
      In Teil 5 werden wir mit GitLens arbeiten, wer will, kann das gleich mit installieren.
      </Spoiler>

      Die neu installierten Befehle (z.B. Ctrl+B für Bold) können wir uns mit F1 und Suche nach 'markdown' anzeigen lassen. Für umfangreiche Mark-Down Texte kann man mit [[TOC]] automatisch ein Inhaltsverzeichnis einfügen, wenn man Überschriften verwendet hat. Die kurze Markdown-Anleitung kennt wohl jeder schon von der Markdown-Card.

      ​Als angehender Linux-Anwender estellen wir die Readme-Datei nicht im GUI sondern im Terminal mit: touch README.md

      README.md

      HTML-Code:
      # Home-Assistant Repository
      
      * **State**: private
      * **Owner**: <your Name>
      * **Folder**: homeassistant/
      
      This repo covers all config files of the homeassistant/ folder
      
      * .storage/lovelace* (all lovelace-dashboards are stored in json-files here, Hinweis: große Dashboards können > 1 MB sein)
      * blueprints/
      * custom_templates/
      * input_booleans/
      * input_numbers/
      * python_scripts/
      * sensors/
      * templates/
      * themes/
      * www/ (without subfolder community/)
      
      * .HA_VERSION
      * .ha_run.lock
      * .shopping_list.json
      * automations.yaml
      * configuration.yaml
      * covers.yaml
      * input_selects.yaml
      * lights.yaml
      * notify.yaml
      * rest.yaml
      * scenes.yaml
      * scrips.yaml
      * switch.yaml
      * utility_meter.yaml
      
      excluded directories:
      
      * .cloud/
      * .storage/ (außer lovelace* für json-Files des lovelace-Dashboards)
      * custom_components/
      * custom_icons/
      * deps/ (dependencies, z.B. für Python)
      * tts/
      * www/community/
      
      excluded files:
      
      * .git-credentials (hier speichert der git credential.helper die Anmeldedaten im Klartext, liegt aber eigentlich in /root/)
      * callgrind.out.*
      * home-assistant.log
      * home-assistant.log.*
      * home-assistant_v2.db*
      * secrets.yaml


      Das wird zwar bei jedem individuell etwas anders aussehen, aber als Basis ist es sicher ganz brauchbar.

      Es gibt auch Leute, die .storage komplett includieren, da dort die gesamte GUI Config im JSON-Format abgelegt ist.
      Die Frage ist aber, was man dann mit solchen Files macht, Änderungen vergleichen geht, bearbeiten sicher nicht.

      Als nächstes müssen wir jetzt ein .gitignore erstellen, das dieses Ziel korrekt umsetzt, also los: touch .gitignore

      .gitignore

      HTML-Code:
      # exclude the following directories
      # Warnung: "foldername/*" würde nur den Inhalt des Ordners ausschließen, nicht jedoch den Ordner selbst
      # Achtung: Kommentare nur am Anfang der Zeile beginnen lassen
      
      # all directories (and files) starting with a dot, with some exceptions (e.g. .gitignore)
      .*
      !.gitignore
      !.ha_run.lock
      !.shopping_list.json
      
      # Der Folder .storage/ wird zuerst von der .* direktive wieder ausgenommen,
      # um dann seinen gesamten Inhalt (bis auf lovelace*) doch wieder zu excluden.
      # Im Folder .storage/ sollen also nur die Files für das lovelace Dashboard gesichert werden.
      # checks all the following files that will now be included: ls -lhA .storage/lovelace*
      !.storage/
      .storage/*
      !.storage/lovelace*
      
      .cloud/
      custom_components/
      custom_icons/
      deps/
      tts/
      www/community/
      
      # exclude the following files
      
      # Profiler-Integration File
      callgrind.out.*
      
      # Log-Files
      home-assistant.log
      home-assistant.log.*
      *.log
      
      # Database-Files
      *.db
      *.db-shm
      *.db-wal
      
      # Sensitive files
      secrets.yaml
      # Die git-credentials liegen eigentlich in /root/, der Eintrag hier schadet aber nicht.
      .git-credentials
      
      # auf Empfehlung im Forum werden auch noch folgende excludes ergänzt
      __pycache__/
      devtools_json_cache.json
      # Z-Wave Config
      zwcfg_*.xml

      Die Beschreibung des LICENSE Files lasse ich hier aus, auf der Seite Choose a License sind genug Vorschläge zu finden.

      ​Damit sind die ersten git-spezifischen Files erstellt, die nächsten Befehle folgen im Terminal.

      prüfe, ob git installiert ist, Ausgabe war bei mir: git version 2.47.3

      HTML-Code:
      git --version

      prüfe, ob Zugriff auf das remote-Repo besteht

      HTML-Code:
      git ls-remote http://homeassistant.local:3000/<your_username>/homeassistant.git

      Achtung: Es wird oben ganz klein ein Dialog eingeblendet, um Username, Password abzufragen. Wenn man das nicht beantwortet, dann kommt nach einiger Zeit der Fehler:
      remote: Unauthorized
      fatal: Authentication failed

      Alternativ kann man die Daten auch direkt im URL-String einfügen. (weitere Alternativen dann in Teil 4)
      HTML-Code:
      git ls-remote http://<your_username>:<your_password>@homeassistant.local:3000/<your_username>/homeassistant.git
      Bei Erfolg wird einfach keine Meldung zurückgegeben, falls das Repo noch leer ist.
      Zuletzt geändert von scw2wi; 05.12.2025, 17:25.

      Kommentar


        #4
        Teil 4: Die ersten Commits

        So, ab jetzt wird's ernst. Wir erstellen das lokale Repo.

        HTML-Code:
        git init
        Initialized empty Git repository in /config/.git/

        Damit haben wir das aktuelle Verzeichnis zu einem lokalen Git-Repository gemacht, es sind einige versteckte Files erstellt worden.

        Der Prompt ändert sich
        von
        /homeassistant
        auf
        /homeassistant git: (main) ✗

        Wir befinden uns also im Git Main-Branch, das '✗' zeigt, dass nicht alles gestaged wurde (eigentlich ja noch gar nichts, das kommt aber noch). Sollte sich jemand nicht im Main sondern im Master-Branch befinden, das hab ich oben bei "git config" beschrieben, wie man das konfigurieren kann.

        HTML-Code:
        git remote add origin http://homeassistant.local:3000/<your_username>/homeassistant.git
        git remote -v
        Lokales Repo und Remote-Repository sind damit verknüpft, das muss auch nicht wiederholt werden.

        HTML-Code:
        git checkout -b main
        # oder
        git switch -c main
        Switched to a new branch 'main'
        So würden wir einen neuen Branch erstellen und dorthin wechseln, in unserem Fall jetzt nicht notwendig, da wir schon im main sind.

        HTML-Code:
        git add README.md
        Für den ersten Test wird mal nur eine Datei verwendet, diese ist jetzt im Staging-Bereich.

        HTML-Code:
        git status --ignored
        zeigt als "Changes to be committed" nur README.md,
        als untracked Files alles was noch nicht gestaged wurde, aber auch nicht ignored wird,
        und als ignored Files alles, war wir in .gitignore definiert haben.

        Damit können wird prüfen, ob unser .gitignore File genau so interpretiert wird, wie wir es geplant haben.

        HTML-Code:
        git commit -m "first commit"
        Erst nach einem Commit kann auch gepusht werden.

        HTML-Code:
        git push -u origin main
        Aktuell müssen wir hier immer noch username & password eingeben, das kann man aber vermeiden und das machen wir auch gleich.

        Damit ist unser erster lokaler Commit auch im Remote-Repository verewigt. Auf der Gitea Seite können wir diesen Commit jetzt auch finden.

        Hinterlegen der Credentials:

        Es gibt viele Möglichkeiten, wie man sich auf seinem Remote-Repository anmeldet.

        1 Bei jedem Vorgang die Daten eingeben (so wie gerade gemacht), ist uns zu mühsam
        2 Bei jedem relevanten Befehl die Daten mitgeben (so wie bei git remote add gemacht), ist auch zu mühsam
        3 Mit dem credential.helper die Anmelde-Daten lokal speichern (für lokale Repos OK), das werden wir gleich machen
        4 SSH-Schlüsselpaar generieren
        5 Personal Access Token (PAT)

        Solange ich Gitea lokal hoste bleibe ich mal bei Lösung 3, bei einem öffentlichen Server werde ich auf die Variante 4 oder 5 umsteigen.

        Anleitung für den git credential.helper

        Zuerst aktivieren wir mal die Speicherung des Passworts ab dem nächsten Login
        HTML-Code:
        git config --global credential.helper store
        Da git die login Daten lokal unverschlüsselt speichert, wollen wir dieses File genauso ausnehmen wie secrets.yaml, also fügen wir die folgende Zeile in .gitignore ein.
        .git-credentials

        Hinweis: Das wäre eigentlich nicht notwendig, da die datei nicht im homeassistant Folder liegt, zur Erinnerung, dass es sie gibt, lasse ich den Eintrag aber bestehen.

        Nach eine Änderung in README.md wiederholen wir die Schritte von oben.

        HTML-Code:
        git add README.md
        git status
        git commit -m "second commit"
        git push http://USERNAME:PASSWORD@homeassistant.local:3000/USERNAME/homeassistant.git
        Ab jetzt genügt ein einfaches git push und die Anmeldedaten sind bereits bekannt.

        Es wurde das File .git-credentials in /root erstellt, und drinnen befindet sich unser Passwort im Klartext!

        HTML-Code:
        cat /root/.git-credentials

        Im nächsten Schritt wollen wir jetzt alle weiteren Files commiten, bis auf den Folder .storage/ da ich mir den für den Schluss aufheben möchte.

        "git add ." kennen wir schon (nimmt alle geänderten oder neuen Files auf), mit "git rm -r --cached" entfernen wir den Folder .storage/ rekursiv (also mit allen Sub-Foldern) wieder vom Staging-Bereich.

        Bei diesem Remove können wir in der Ausgabe gut erkennen, dass eigentlich nur lovelace* Files wieder rausgenommen werden, da alle anderen durch .gitignore ohnehin generell ausgenommen sind.

        Die Ausgabe von "git status" sollte wir jetzt gewissenhaft prüfen, ob das alles Files sind, die uns interessieren.
        .ha_run.lock stammt nicht von uns, wenn das File im Repo stört, kann man es auch noch excluden.

        Wer weitere Files noch auf- oder ausnehmen möchte, kann das File .gitignore jederzeit entsprechend erweitern.

        HTML-Code:
        git add .
        git rm -r --cached .storage/
        git status
        git commit -m "Commit aller restlichen Files ohne .storage/"
        git push

        Kommen wir zuletzt noch zum Folder .storage/

        Alle Einstellungen, die wir im HA GUI vornehmen, landen in diesem Ordner, leider nicht im YAML sondern im JSON-Format, was die Files weniger gut lesbar macht.

        Im Forum gibt es Diskussionen darüber, wie mit diesen Files bei git umgegangen werden soll. Es gibt 3 mögliche Lösungen.

        1 Ordner komplett ausnehmen, da wir darin eigentlich keine einzelnen Einträge zurückholen können, und gesichert werden sie über das Backup ohnehin.
        2 Ordner komplett aufnehmen, da wir damit eine zusätzliche Sicherung der Daten haben.
        3 Im Ordner nur die lovelace Files aufnehmen, da es sich dabei um das Dashboard handelt, und wir so alle Änderungen am Dashboard verfolgen und auch rückgängig machen können.

        Ich beschreibe die Lösung 3, wer sich für 1 oder 2 entscheidet, muss .gitignore jetzt entsprechend anpassen.

        Unser letzter Commit nimmt jetzt alle lovelace Files von .storage/ auf.
        Da "git add ." keine Ausgabe hat können wir mit ";" gleich den nächsten Befehlt dranhängen, der dann Text ausgibt.

        HTML-Code:
        git add . ; git status
        git commit -m "Commit aller lovelace Files in .storage/"
        git push
        Das war's, wir haben ein versioniertes Home-Assistant.

        Für die Config-Files ist es ab jetzt recht einfach, jede Änderung direkt im GUI zu verfolgen. Wie das geht sehen wir uns im nächsten Teil an.

        Wer aber sein Dashboard nicht im YAML-Mode erstellt (und wer macht so etwas heute noch), der hat nur die json-Files in Git, und wenn man da die Änderungen nachvollziehen möchte, dann wird das rasch sehr unübersichtlich, zur Not ist es aber machbar.
        Zuletzt geändert von scw2wi; 05.12.2025, 17:46.

        Kommentar


          #5
          Teil 5: Git Anwendung in Studio Code Server

          In der Standard-Configuration haben wir bereits das Modul Source-Control.

          Source Control.png
          Wer in Teil 3 GitLens noch nicht als Studio-Code Extension installiert hat, der kann das jetzt nachholen.
          Damit stehen uns 2 sehr mächtige GUI Werkzeuge zur Verfügung.

          Viele haben vielleicht schon bemerkt, dass Files und Folders jetzt Farben haben,
          weiß ... versioniert, aber derzeit ohne Änderung
          grau ... ignored (laut .gitignore)

          und im Source-Control auch noch Kennzeichen.
          M - braun ... modified
          U - grün .... untracked, also neu hinzugefügt
          A - grün .... added (zum Staging-Bereich hinzugefügt)
          R - grün .... renamed or moved (nur bei "git mv", nicht bei normalem "mv")
          D - rot ..... deleted (sichtbar nur in Source-Control)

          Laut Anleitung gibt auch noch folgende, das konnte ich aber bisher nicht reproduzieren.
          C - hellgrün .. copied

          Ein Klick auf die Datei im Source-Control zeigt 2-spaltig alle Änderungen an.

          "+" (State Changes) entspricht dem git add (für einzelne Files oder in der obersten Zeile auch für alle)

          Darüber gibt es noch ein paar Icons

          Source Control Icons.png​​

          GitLens ... einige GitLens Befehle
          Stash all Changes ... führt "git stash push --include-untracked" aus, für häufige Branch-Wechsel von Vorteil
          Show Commit Graph ... für häufige Branch-Verzweigungen recht anschaulich
          Commit ... das sollte jetzt schon klar sein, führt "git commit" aus, vorher müssen wir noch das Feld "Message" befüllen.
          Refresh ... führt "git status" aus, falls z.B. Files nicht durch den Editor selbst geändert wurden.

          Im Hamburger-Menü rechts davon gibt es viele weitere Funktionen, von denen uns die meisten bereits bekannt sein sollten.

          Wichtige Unterscheidung:
          "Push" ... git push (für bestehende Branches)
          "Publish Branch" ... git push -u origin <branch> (für neue Branches)

          "Sync Changes" ... git pull (also fetch & merge) ; git push
          "Commit & Sync" ... git commit ; git pull ; git push

          Also wenn man danach immer noch nicht synchron mit dem Remote-Repo ist, dann hat's da was. Bei einem Merge-Conflict wird der Push natürlich ausgelassen.

          Es bewährt sich jetzt, zuerst die shell Befehle kennengelernt zu haben, damit man dann im GUI nicht sinnlos herumklickt.

          Für alle, die bis jetzt durchgehalten haben, gibt es zum Abschluss noch eine kleine Restore-Übung, wo wir auch mal GitLens verwenden können.

          ​Schritt 1: Erstellung einer beliebigen Datei mit beliebigem Inhalt und diese mit "State Changes" & "Commit & Sync" im Remote-Repo sichern.
          Schritt 2: Löschen der Datei und auch diese Änderung wieder pushen.
          Schritt 3: Jetzt holen wir uns dieses "irrtümlich" gelöschte File wieder zurück.

          Zuerst die Anleitung für's GUI, und zwar für GitLens Inspect (das ist das zweite GitLens Icon mit der Lupe)

          Im Bereich FILE HISTORY zum vorletzten Commit gehen, wo das gelöschte File noch enthalten war.

          Im Vergleichsfenster finden wir den letzten Inhalt, den wir manuell herauskopieren müssen und ebenfalls manuell in eine neu erstellte Datei pasten können.

          Das war jetzt zwar kein echter File-Restore, aber zumindest der letzte Inhalt wurde gerettet.

          Und jetzt noch die Anleitung für's Terminal.

          HTML-Code:
          git log --all --name-status | grep <filename>
          Liefert uns mal den Pfad zur Datei, wenn sie gefunden wurde.

          HTML-Code:
          git log --all -- <path>/<filename>
          Liefert uns die 40-stelligen Hash-Codes von Commits, wo die Datei noch enthalten war. Das können wir mit der linken Maustaste markieren und mit der re-Maustaste kopieren. Diese Anzeige können wir mit "q" verlassen.

          Auch im folgenden Fall gibt es heute 2 Befehle und auch hier finde ich restore wesentlich intuitiver.
          HTML-Code:
          git checkout Commit-Hash-Code -- <path>/<filename>
          # oder
          git restore --source Commit-Hash-Code <path>/<filename>
          Holt die Datei aus dem alten Commit und legt sie im Arbeitsverzeichnis ab.

          error: pathspec 'path/filename' did not match any file(s) known to git
          würde bedeuten, wir haben den falschen Commit genommen.

          Bei Erfolg taucht die Datei jetzt grün als ADDED auf.

          Das war jetzt ein echter File-Restore, den ich in dieser Form über's GUI nicht gefunden habe.

          Ich halte es für klug, so einen Vorgang mal zu üben, damit man dann im Fall der Fälle die Nerven behält, und weiß, was zu tun ist.

          Git wird bei mir ab jetzt sicher zu einem entspannteren Workflow beitragen, denn wenn ich mal irgend etwas zerschieße, dann kann ich jederzeit zurück, ohne gleich ein komplettes HA-Restore laufen zu lassen.

          Zuletzt noch ein Tipp:

          Wen diese grauen Zwischenzeilen mit Anzeige der letzten Änderung im Editor stören, der kann sie einfach ausschalten.
          Temporär: Öffnen der Befehlspalette (Ctrl+Shift+P), suche nach "CodeLens" und einmal draufklicken zum togglen.
          Dauerhaft: Öffnen der Settings (Ctrl+'.'), suche nach "CodeLens" und Haken entfernen.

          weitere Infos:

          Automating Home Assistant Configuration to GitHub (inkl. SSH Config)

          2 Bücher haben mir beim Einstieg sehr geholfen:

          O'Reilly Taschenbuch: Git kurz & gut

          Git Projektverwaltung aus dem Rheinwerk-Verlag

          Das war jetzt vermutlich meine umfangreichste Anleitung, die ich je hier geschrieben hab. Wenn es den einen oder anderen motiviert, ebenfalls einen Git-Workflow für das eigene HA-Projekt einzuführen, dann würde ich sagen, war's das wert.
          ​​
          Zuletzt geändert von scw2wi; 05.12.2025, 18:18.

          Kommentar


            #6
            Gesamtübersicht aller Beiträge dieser Serie über HA

            HACS Wetterkarte
            HACS Sonne & Mond (!include Tipps zur configuration.yaml)
            => siehe dazu auch eine alternative configuration Aufteilung über Packages von Tom Bombadil Verwendung von Packages
            HACS Schieberegler (inkl. Möglichkeiten der Icon Farbanpassung & erste Vorstellung Farbschema)​
            HACS Gauges (Tachoanzeigen, inkl. senkrechte Balken-Cards)​
            HACS stack-in-card für Raum-Card
            HACS Graph-Cards
            HACS Thermostat-Cards
            ​​HACS Entity Cards (inkl. stacking Beispiele mit der custom:button-card)
            HACS Reminder (trash-card, atomic-calendar-revive)​
            HACS Person- & Öffi-Card (inkl. Geschichte zu ChatGPT)​​​​
            => siehe dazu auch: DB-Info Integration von SvenA: HACS - Cards für Öffentlichen Nahverkehr
            HA-Behaglichkeits-Diagramm

            HA Kurzeinführung

            HACS Sidebar & Dashboard-Entwurf
            HACS Bewässerung​
            HA & Node-Red
            HA Notifications
            HA Recorder, SQLite, InfluxDB, Grafana
            HA Python Scripts
            HACS Browser_Mod
            HA Newsticker (über Feedreader oder RESTful-API)

            HA Git-Workflow & Gitea Add-On
            HA Watchdog
            Zuletzt geändert von scw2wi; 09.12.2025, 18:22.

            Kommentar


              #7
              Deinen Beitrag finde ich echt gut. Eine Frage zum Backup: ist die Gitea Database im HA Backup enthalten?

              Kommentar


                #8
                Zitat von Noschvie Beitrag anzeigen
                ist die Gitea Database im HA Backup enthalten?
                Ich würde sagen, das hängt von den Einstellungen ab.
                Bei mir steht unter "Zu sichernde Daten" bei Add-ons die Einstellung auf "Alle", und damit werden auch alle Daten der Add-ons gesichert.

                Für die Überwachung der Ordnergrößen verwende ich diesen Befehl.

                HTML-Code:
                du -shc /* | sort -h
                # oder
                du -shc /<folder>/* | sort -h
                ​
                Bei mir sind die Backups in dem Monat der Gitea Installation von 400 MB auf 500 MB angestiegen,
                und durch das Update von HA 2025.10 auf 2025.11 sogar nochmals auf über 900 MB.

                Update:

                Ich hab jetzt ins TAR Archiv reingesehen.

                443 MB core_whisper (da muss wohl seit HA 2025.11 sinnloserweise das gesamte LLM mit gesichert werden)
                243 MB homeassistant
                134 MB squeezelite
                86 MB influxdb
                26 MB music_assistant (den Musik-Ordner selbst hab ich ausgenommen)
                18 MB vscode
                11 MB gitea

                der Rest ist < 100 kB
                Zuletzt geändert von scw2wi; 05.12.2025, 19:26.

                Kommentar

                Lädt...
                X