Git Archive: saubere Release-Exporte ohne .git-Verzeichnis erstellen
AI generated
git
HEAD
Git
Git Archive
saubere Release-Exporte ohne .git-Verzeichnis

git archive erzeugt aus einem beliebigen Commit, Tag oder Tree einen reinen Datei-Snapshot als zip- oder tar-Archiv, komplett ohne Commit-Historie und ohne .git-Verzeichnis. Wer Release-Pakete bisher per Hand aus einem Checkout zusammenkopiert, findet hier ein deterministisches, direkt in CI-Pipelines einsetzbares Werkzeug, das Git bereits mitbringt.

9 Min. Lesezeit Git Release

1. Was git archive vom normalen Checkout unterscheidet

Ein gewöhnlicher git clone bringt zwangsläufig das komplette .git-Verzeichnis mit, also die vollständige Commit-Historie, alle Branches und alle jemals erstellten Objekte. Für ein Release-Artefakt, das an Kunden ausgeliefert oder in ein Deployment-Paket verpackt wird, ist das in aller Regel unerwünschter Ballast und je nach Historie sogar ein Datenschutzrisiko, wenn frühere Commits sensible Inhalte enthielten, die später zwar entfernt, aber nie aus der Historie getilgt wurden.

git archive löst genau dieses Problem, indem es direkt auf Basis der Objektdatenbank arbeitet und ausschließlich den Dateiinhalt eines einzelnen, exakt bestimmten Commits, Tags oder Trees in ein Archiv schreibt. Es liest dazu intern denselben Baum, den auch git ls-tree anzeigen würde, und benötigt dafür weder ein Working Directory noch überhaupt einen lokalen Checkout, ein bare Repository reicht vollkommen aus.

Das Ergebnis ist deterministisch im Sinne des Dateiinhalts: Derselbe Commit liefert bei jedem Aufruf exakt dieselbe Dateiliste mit demselben Inhalt, unabhängig davon, welcher Branch gerade ausgecheckt ist oder was im Arbeitsverzeichnis sonst noch herumliegt.


# Minimalbeispiel: aktuellen Stand als zip-Archiv exportieren
git archive --format=zip HEAD -o release.zip

# Denselben Snapshot als tar-Archiv aus einem bare Repository heraus
git --git-dir=/pfad/zum/bare-repo.git archive HEAD -o release.tar

2. Ausgabeformate: zip, tar und komprimiertes tar.gz

Über die Option --format unterstützt git archive mindestens zip und tar als Standardformate, wobei sich zip vor allem für Windows-Empfänger anbietet, während tar im Linux- und Container-Umfeld die gebräuchlichere Wahl ist. Wird der Zieldateiname stattdessen über -o mit einer erkennbaren Endung wie .zip angegeben, leitet Git das Format automatisch aus der Endung ab, sodass die explizite --format-Angabe entfallen kann.

Für komprimierte tar-Archive lässt sich das Format tar.gz direkt angeben, Git nutzt dafür die eingebaute Zlib-Kompression, sodass kein externes gzip-Binary erforderlich ist. Wer die Kompressionsstufe steuern möchte, kann eine Zahl von -1 bis -9 anhängen, wobei höhere Werte mehr Rechenzeit gegen eine kleinere Ausgabedatei tauschen und sich für einmalige Release-Builds in der Regel die höchste Stufe lohnt.


# Komprimiertes tar.gz mit maximaler Kompressionsstufe
git archive --format=tar.gz -9 HEAD -o release.tar.gz

# Format wird automatisch aus der Dateiendung erkannt
git archive HEAD -o release.zip

3. Saubere Verzeichnisstruktur mit --prefix

Ohne weitere Angaben landen die Dateien eines Archivs direkt auf der obersten Ebene, was beim Entpacken schnell zu einem unübersichtlichen Verzeichnis führt, in dem sich Release-Dateien mit bereits vorhandenen Dateien im Zielordner vermischen. Die Option --prefix fügt jedem Eintrag im Archiv einen führenden Pfad hinzu, sodass beim Auspacken automatisch ein eigener Wurzelordner entsteht.

Üblich ist ein Präfix, das Projektname und Version enthält, etwa meinshop-2.4.1/, damit beim Entpacken mehrerer Releases nebeneinander keine Dateien überschrieben werden und auf einen Blick erkennbar bleibt, welche Version in welchem Ordner liegt.


# Archiv mit eigenem Wurzelverzeichnis erzeugen
git archive --format=tar.gz --prefix=meinshop-2.4.1/ v2.4.1 -o meinshop-2.4.1.tar.gz

4. Dateien gezielt ausschließen mit .gitattributes

Nicht jede Datei im Repository gehört in ein Release-Archiv. Testverzeichnisse, interne Dokumentation, CI-Konfigurationsdateien oder Entwickler-Tooling sollen häufig zwar versioniert, aber nicht ausgeliefert werden. Genau dafür bietet Git das Attribut export-ignore, das in einer .gitattributes-Datei gesetzt wird und ausschließlich beim Archivieren wirkt, den normalen Checkout aber unangetastet lässt.

Ein ergänzendes Attribut ist export-subst: Es aktiviert die Ersetzung von Platzhaltern wie $Format:%H$ innerhalb einer markierten Datei durch den tatsächlichen Commit-Hash zum Zeitpunkt des Archivierens, was sich hervorragend eignet, um eine Versionsdatei ohne .git-Zugriff nachvollziehbar zu halten.


# .gitattributes im Projekt-Root
tests/            export-ignore
docs-intern/      export-ignore
.gitlab-ci.yml    export-ignore
VERSION           export-subst

5. Archive von einem entfernten Repository ohne lokalen Checkout

Mit der Option --remote lässt sich ein Archiv theoretisch direkt von einem entfernten Repository anfordern, ohne dass zuvor ein lokaler Clone nötig ist. Der Server erzeugt das Archiv dabei selbst und überträgt nur das fertige Paket, was bei sehr großen Repositories mit langer Historie spürbar Bandbreite und Zeit sparen kann.

In der Praxis deaktivieren die meisten gehosteten Plattformen wie GitHub und GitLab diese Funktion serverseitig standardmäßig aus Sicherheitsgründen, da sie einem Angreifer sonst erlauben würde, beliebige Commits abzufragen, ohne dass dies im Zugriffsprotokoll klar sichtbar wäre. Für den praktischen Alltag bedeutet das: Ein lokaler Checkout mit anschließendem lokalem git archive bleibt der zuverlässigere Weg.


# Funktioniert nur, wenn der Server uploadarchive explizit erlaubt
git archive --remote=ssh://git@server/projekt.git --format=tar HEAD | tar -x

6. Archive an Git-Tags koppeln für nachvollziehbare Releases

Statt immer den aktuellen Stand von HEAD zu archivieren, sollte ein Release-Artefakt an einen konkreten, unveränderlichen Tag gebunden werden. Ein annotiertes Tag markiert einen Commit dauerhaft mit einer Versionsnummer, und git archive akzeptiert diesen Tag-Namen anstelle eines Commit-Hashes an genau derselben Stelle im Befehl.

Damit lässt sich ein einfacher, wiederholbarer Ablauf etablieren: Sobald ein Tag wie v2.4.1 gepusht wird, erzeugt ein Pipeline-Job daraus automatisch das passende Archiv und lädt es als benanntes Release-Artefakt hoch, ohne dass jemand manuell nachschauen muss, welcher Commit gerade der aktuelle Release-Stand ist.


# Release-Archiv direkt aus einem Tag erzeugen
git archive --format=tar.gz --prefix=meinshop-2.4.1/ tags/v2.4.1 \
  -o meinshop-2.4.1.tar.gz

7. Reproduzierbarkeit und Prüfsummen für Release-Artefakte

Da der Dateiinhalt eines Archivs eindeutig aus dem gewählten Commit abgeleitet wird, lässt sich für jedes erzeugte Release-Paket eine Prüfsumme berechnen, die als verlässlicher Nachweis dient, dass ein heruntergeladenes Archiv wirklich unverändert dem markierten Commit entspricht. Bei gleicher Git-Version und identischen Optionen bleibt der Dateiinhalt über wiederholte Läufe hinweg stabil.

Kleinere Unterschiede in reinen Archivformat-Metadaten wie Zeitstempeln in der zip-Struktur sind je nach eingesetzter Git-Version zwar möglich, betreffen aber nicht den eigentlichen Dateiinhalt und damit auch nicht die Integrität des Release-Pakets. Eine begleitende sha256sum-Datei neben dem Archiv gehört in eine seriöse Release-Pipeline dazu.


# Prüfsumme neben dem Release-Archiv ablegen
sha256sum meinshop-2.4.1.tar.gz > meinshop-2.4.1.tar.gz.sha256

8. Einsatz von git archive in CI/CD-Pipelines

In einer Pipeline ersetzt ein einzelner git archive-Aufruf oft mehrere Zeilen manueller Kopierlogik, die zuvor bestimmte Verzeichnisse ausschloss und den Rest in ein Archiv packte. Da der Checkout in CI-Runnern ohnehin bereits vorliegt, genügt ein Job-Schritt, der das fertige Artefakt erzeugt und anschließend als Build-Artefakt hochlädt oder in einen Artefakt-Speicher überträgt.

Ein wichtiger Nebeneffekt: Da das Archiv kein .git-Verzeichnis enthält, gelangt auch keine komplette Commit-Historie versehentlich in ein öffentlich zugängliches Release-Paket, was insbesondere bei Open-Source-Downloads oder Kunden-Deployments ein reales Risiko reduziert.


# Beispiel-Job-Schritt in einer CI-Pipeline
build-release:
  script:
    - git archive --format=tar.gz --prefix=app-${CI_COMMIT_TAG}/ \
        ${CI_COMMIT_TAG} -o app-${CI_COMMIT_TAG}.tar.gz
  artifacts:
    paths:
      - app-*.tar.gz

9. Grenzen von git archive: Submodule und generierte Dateien

Zwei Einschränkungen sollten vor dem produktiven Einsatz bekannt sein. Erstens werden Submodule von git archive nicht automatisch mit ausgepackt, im Archiv landet lediglich der Verweis auf den referenzierten Commit des Submoduls, nicht dessen tatsächlicher Inhalt. Für Projekte mit Submodulen sind zusätzliche Skripte wie das bekannte git-archive-all nötig, die rekursiv durch alle Submodule laufen und deren Inhalte anschließend zusammenführen.

Zweitens enthält das Archiv ausschließlich versionierte Dateien. Generierte oder installierte Abhängigkeiten wie Verzeichnisse für Composer- oder npm-Pakete sind üblicherweise nicht Teil des Repositories und müssen dementsprechend in einem separaten Build-Schritt nach dem Archivieren erzeugt werden, bevor das fertige Paket tatsächlich lauffähig ist.

Kriterium git archive git clone --depth 1 Manuelles zip/tar
Enthält .git-Verzeichnis Nein Ja, wenn auch verkleinert Abhängig vom Skript
Deterministischer Inhalt Ja, exakt zum Commit Ja, aber inklusive Metadaten Nein, fehleranfällig
Serverseitig ohne Checkout möglich Ja, bei erlaubtem Remote Nein Nein
Dateien gezielt ausschließen Ja, über .gitattributes Nein, nur nachträgliches Löschen Ja, aber manuell gepflegt
Geeignet für automatisierte Pipelines Ja, ein einzelner Befehl Bedingt, zusätzlicher Aufräumschritt nötig Nein, wartungsintensiv

Mironsoft

Git-Workflows, Branching-Strategien und CI-Hooks

Chaotische Git-Historie und unklare Branching-Regeln im Team?

Wir richten saubere Git-Workflows ein, klären Branching-Strategien fürs Team und automatisieren Qualitätschecks über Git-Hooks und CI-Pipelines, damit die Historie nachvollziehbar bleibt.

Workflow-Audit

Bestehende Branching-Strategie und Merge-Praxis auf Schwachstellen prüfen.

Hook-Automatisierung

Pre-Commit- und Pre-Push-Hooks für Linting, Tests und Commit-Konventionen einrichten.

Team-Schulung

Rebase, Cherry-Pick und Konfliktauflösung im Team praxisnah vermitteln.

10. Zusammenfassung

Git Archive

Kernidee

git archive erzeugt einen reinen Datei-Snapshot eines Commits als zip oder tar, ganz ohne .git-Verzeichnis und ohne Historie.

Saubere Struktur

--prefix sorgt für einen eigenen Wurzelordner im Archiv, .gitattributes mit export-ignore schließt gezielt Dateien aus.

Typischer Einsatz

Ein CI-Job erzeugt bei jedem Tag automatisch ein benanntes, geprüftes Release-Artefakt aus dem markierten Commit.

Bekannte Grenze

Submodule und generierte Abhängigkeiten wie vendor- oder node_modules-Verzeichnisse werden nicht automatisch mit archiviert.

11. FAQ: Git Archive

1Enthält ein mit git archive erzeugtes Paket die vollständige Commit-Historie?
Nein, das Archiv enthält ausschließlich den Dateiinhalt des gewählten Commits als flachen Snapshot, weder die Historie noch das .git-Verzeichnis werden mit übertragen.
2Kann ich mit git archive auch nur einen einzelnen Unterordner exportieren?
Ja, dazu wird der Pfad nach dem Commit oder Tag angegeben, etwa git archive HEAD:src, wodurch das Archiv ausschließlich den Inhalt dieses Unterverzeichnisses enthält.
3Werden nicht committete Änderungen im Archiv berücksichtigt?
Nein, git archive liest ausschließlich aus der Objektdatenbank des angegebenen Commits, Änderungen im Arbeitsverzeichnis oder in der Staging-Area fließen nicht ein.
4Wie schließe ich ein Verzeichnis wie tests zuverlässig aus dem Release-Archiv aus?
Über einen Eintrag wie tests/ export-ignore in der .gitattributes-Datei, der ausschließlich beim Archivieren wirkt und den normalen Checkout unangetastet lässt.
5Funktioniert git archive --remote bei GitHub und GitLab?
In der Praxis meist nicht, da beide Plattformen den serverseitigen Archiv-Export standardmäßig aus Sicherheitsgründen deaktivieren, ein lokaler Checkout mit anschließendem git archive ist dort verlässlicher.
6Kann ich die Kompressionsstufe für tar.gz-Archive festlegen?
Ja, über eine angehängte Zahl von 1 bis 9, wobei ein höherer Wert mehr Rechenzeit gegen eine kleinere Ausgabedatei tauscht, für einmalige Release-Builds lohnt sich meist die höchste Stufe.
7Ersetzt git archive ein Build-System für Release-Artefakte?
Nein, es liefert ausschließlich den reinen Quellcode-Stand als Snapshot, installierte Abhängigkeiten müssen weiterhin in einem separaten Build-Schritt danach erzeugt werden.
8Was passiert mit Submodulen beim Archivieren?
Sie werden nicht automatisch aufgelöst, im Archiv landet lediglich der Verweis auf den referenzierten Commit, der tatsächliche Inhalt des Submoduls fehlt ohne zusätzliches Werkzeug.
9Lässt sich der Commit-Hash automatisch in eine Datei im Archiv einfügen?
Ja, über das Attribut export-subst in der .gitattributes-Datei in Kombination mit einem Platzhalter wie $Format:%H$ in der Zieldatei, der beim Archivieren ersetzt wird.
10Ist ein mit git archive erzeugtes Archiv bei jedem Lauf identisch?
Der Dateiinhalt bleibt bei gleicher Git-Version und gleichen Optionen stabil, kleine Unterschiede in reinen Formatmetadaten wie Zeitstempeln sind dennoch je nach Version möglich.