[{"data":1,"prerenderedAt":761},["ShallowReactive",2],{"/de-de/blog/a-beginners-guide-to-the-git-reftable-format":3,"navigation-de-de":39,"banner-de-de":443,"footer-de-de":453,"blog-post-authors-de-de-Patrick Steinhardt":658,"blog-related-posts-de-de-a-beginners-guide-to-the-git-reftable-format":672,"assessment-promotions-de-de":710,"next-steps-de-de":751},{"id":4,"title":5,"authorSlugs":6,"body":8,"categorySlug":9,"config":10,"content":14,"description":8,"extension":28,"isFeatured":12,"meta":29,"navigation":12,"path":30,"publishedDate":20,"seo":31,"stem":36,"tagSlugs":37,"__hash__":38},"blogPosts/de-de/blog/a-beginners-guide-to-the-git-reftable-format.yml","A Beginners Guide To The Git Reftable Format",[7],"patrick-steinhardt",null,"open-source",{"slug":11,"featured":12,"template":13},"a-beginners-guide-to-the-git-reftable-format",true,"BlogPost",{"heroImage":15,"body":16,"authors":17,"updatedDate":19,"date":20,"title":21,"tags":22,"description":27,"category":9},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664595/Blog/Hero%20Images/blog-image-template-1800x945__9_.png","Bis vor Kurzem war das „files“-Format die einzige Möglichkeit in Git, Referenzen zu speichern. Mit der [Version Git 2.45.0](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-45-0/) kann Git nun Referenzen im „reftable“-Format speichern. Dieses neue Format ist ein Binärformat, das deutlich komplexer als das alte “files” Format ist. Diese Komplexität ermöglicht es jedoch, einige Mängel des „files“-Formats zu beheben. Die Entwicklungsziele des „reftable“-Formats sind unter anderem folgende:\n\n- Die Suche nach einzelnen Referenzen und die Iterationen über zahlreichen Referenzen soll so effizient und schnell wie möglich sein.\n- Das konsistente Lesen von Referenzen soll unterstützt werden, sodass Git nie einen Zwischenzustand liest, wenn ein Update an mehreren Referenzen nur teilweise angewendet wurde.\n- Atomares Schreiben soll unterstützt werden, sodass die Aktualisierung von mehreren Referenzen nur entweder vollständig oder gar nicht möglich ist.\n- Effiziente Speicherung von Referenzen und Reflog-Einträgen.\n\nIn diesem Artikel kommen wir allen Feinheiten des „reftable“-Formats auf die Schliche und sehen uns genau an, wie es funktioniert.\n\n> **Über 6,4 Mio. Builds pro Monat: So transformiert Siemens seine Softwareentwicklung mit GitLab** Über 40.000 Entwickler(innen) bei Siemens nutzen GitLab, um weltweit zusammenzuarbeiten und jeden Monat mehr als 6,4 Millionen Software-Versionen automatisch bereitzustellen. Erfahre, wie eine offene DevOps-Kultur und eine zentrale Plattform die Effizienz und Sicherheit steigern. [Erfolgsstory lesen](https://about.gitlab.com/de-de/customers/siemens/)\n\n## So speichert Git Referenzen\n\nBevor wir uns die Details des „reftable“-Formats ansehen, fassen wir nochmals kurz zusammen, wie Git in der Vergangenheit Referenzen gespeichert hat. Wenn du damit bereits vertraut bist, kannst du gleich zum nächsten Abschnitt springen.\n\nEin Git-Repository enthält zwei wesentliche Datenstrukturen:\n\n- [Objekte](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects), die die eigentlichen Daten deines Repositorys enthalten. Dazu gehören Commits, die Verzeichnisstruktur und die Blobs, die deinen Quellcode enthalten. Objekte verweisen aufeinander und bilden so einen Objektgraphen. Außerdem hat jedes Objekt eine Objekt-ID, durch die es eindeutig identifiziert wird.\n\n- Referenzen wie Branches und Tags sind Wegweiser im Objektgraphen, sodass du Objekten Namen geben kannst, die einfacher zu merken sind, und verschiedene Wege deines Entwicklungsverlaufs nachverfolgen kannst. Ein Repository kann zum Beispiel einen `main`-Branch enthalten, der eine Referenz mit dem Namen `refs/heads/main` ist und auf einen bestimmten Commit zeigt.\n\nReferenzen werden in der Referenzdatenbank gespeichert. Bis Git 2.45.0 gab es nur das Datenbankformat „files“. In diesem Format wird jede Referenz als einfache Datei gespeichert, die eines der folgenden Elemente enthält:\n\n- Eine normale Referenz, die die Objekt-ID des Commits enthält, auf den sie zeigt.\n- Eine symbolische Referenz, die den Namen einer anderen Referenz enthält. Dies ist ähnlich wie ein symbolischer Link, der auf eine andere Datei zeigt.\n\nIn regelmäßigen Abständen werden diese Referenzen in eine einzige `packed-refs`-Datei komprimiert, damit Referenzen effizienter durchsucht werden können.\n\nDie folgenden Beispiele sollen eine Vorstellung davon geben, wie das „files“-Format funktioniert:\n\n```shell\n$ git init .\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) 6917c17] Initial commit\n\n# HEAD ist eine symbolische Referenz, die auf refs/heads/main zeigt.\n$ cat .git/HEAD\nref: refs/heads/main\n\n# refs/heads/main ist eine normal Referenz, die auf einen Commit zeigt.\n$ cat .git/refs/heads/main\n6917c178cfc3c50215a82cf959204e9934af24c8\n\n# git-pack-refs(1) komprimiert diese Referenzen in eine packed-refs Datei.\n$ git pack-refs --all\n$ cat .git/packed-refs\n# pack-refs with: peeled fully-peeled sorted\n6917c178cfc3c50215a82cf959204e9934af24c8 refs/heads/main\n```\n\n## Hochrangige Struktur von reftables\n\nWenn du nun Git 2.45.0 oder eine neuere Version installiert hast, kannst du ein Repository mit dem „reftable“-Format erstellen, indem du den Switch `--ref-format=reftable` verwendest:\n\n```shell\n$ git init --ref-format=reftable .Initialized empty Git repository in /tmp/repo/.git/\n$ git rev-parse --show-ref-format\nreftable\n\n# Irrelevante Dateien wurden für ein einfacheres Verständnis entfernt.\n$ tree .git\n.git\n├── config\n├── HEAD\n├── index\n├── objects\n├── refs\n│   └── heads\n└── reftable\n  ├── 0x000000000001-0x000000000002-40a482a9.ref\n  └── tables.list\n\n4 directories, 6 files\n```\n\nSieh dir zunächst die Repository-Konfiguration an. Du wirst feststellen, dass sie den Schlüssel `extension.refstorage` enthält:\n\n```shell\n$ cat .git/config\n[core]\n    repositoryformatversion = 1\n    filemode = true\n    bare = false\n    logallrefupdates = true\n[extensions]\n    refstorage = reftable\n\n```\n\nDiese Konfiguration teilt Git mit, dass das Repository mit dem „reftable“-Format initialisiert wurde und gibt an, dass Git das „reftable“-Backend nutzen muss, um darauf zuzugreifen.\n\nSeltsamerweise enthält das Repository immer noch einige Dateien, die aussehen, als würde das „files“-Backend verwendet werden:\n\n- `HEAD` würde normalerweise eine symbolische Referenz sein, die auf deinen derzeit ausgecheckten Branch zeigt. Obwohl es nicht vom „reftable“-Backend verwendet wird, ist es für Git-Clients erforderlich, um das Verzeichnis als Git-Verzeichnis zu erkennen. Wenn du also das „reftable“-Format verwendest, ist `HEAD` ein Stub mit dem Inhalt `ref: refs/heads/.invalid`.\n\n- `refs/heads` ist eine Datei mit dem Inhalt `this repository uses the reftable format`. Git-Clients, die das Format „reftable“ nicht kennen, würden normalerweise erwarten, dass dieser Pfad ein Verzeichnis ist. Wenn du also diesen Pfad bewusst als Datei erstellst, führt dies dazu, dass ältere Git-Clients fehlschlagen, wenn sie versuchen, mit dem „files“-Backend auf das Repository zuzugreifen.\n\nDie tatsächlichen Referenzen werden im Verzeichnis `reftable/` gespeichert:\n\n```shell\n$ tree .git/reftable\n.git/reftable/\n├──0x000000000001-0x000000000001-794bd722.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000001-794bd722.ref\n```\n\nEs gibt hier zwei Dateien:\n\n- `0x000000000001-0x000000000001-794bd722.ref` ist eine Tabelle mit Referenzen und den Reflog-Einträgen in einem Binärformat.\n\n- `tables.list` ist eine Liste von Tabellen. Im aktuellen Status des Repositorys enthält die Datei eine Zeile, die der Name der Tabelle ist. Diese Datei verfolgt den aktuellen Satz aktiver Tabellen in der „reftable“-Datenbank und wird aktualisiert, wenn neue Tabellen zum Repository hinzugefügt werden.\n\nWenn du eine Referenz aktualisierst, wird eine neue Tabelle erstellt:\n\n```shell\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) 1472a58] Initial commit\n\n$ tree .git/reftable\n.git/reftable/\n├──0x000000000001-0x000000000002-eb87d12b.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000002-eb87d12b.ref\n```\n\nWie du sehen kannst, wurde die vorherige Tabelle durch eine neue ersetzt. Darüber hinaus wurde die Datei `tables.list` aktualisiert und enthält nun die neue Tabelle.\n\n## Die Struktur einer Tabelle\n\nWie bereits erwähnt, sind die eigentlichen Daten der Referenzdatenbank in Tabellen enthalten. Grob gesagt ist eine Tabelle in mehrere Abschnitte unterteilt:\n\n- Der „Header“ enthält Metadaten zur Tabelle. Dazu gehören unter anderem die Version des Formats, die Blockgröße und die vom Repository verwendete Hash-Funktion (z. B. SHA1 oder SHA256).\n- Der Abschnitt „Ref“ enthält deine Referenzen. Diese Datensätze haben einen Schlüssel, der dem Referenznamen entspricht und entweder auf eine Objekt-ID für reguläre Referenzen oder auf eine andere Referenz für symbolische Referenzen zeigt.\n- Der Abschnitt „Obj“ enthält die umgekehrte Zuordnung von Objekt-IDs zu den Referenzen, die auf diese Objekt-IDs zeigen. Diese ermöglichen es Git, effizient zu suchen, welche Referenzen auf eine bestimmte Objekt-ID zeigen.\n- Der Abschnitt „Log“ enthält deine Reflog-Einträge. Diese Datensätze haben einen Schlüssel, der dem Referenznamen entspricht, sowie einen Index, der die Nummer des Reflog-Eintrags darstellt. Außerdem enthalten sie die alten und neuen Objekt-IDs sowie die Nachricht für diesen Reflog-Eintrag.\n- Der „Footer“ enthält Zeiger zu den verschiedenen Abschnitten.\n\n![Lange Tabelle mit allen reftable-Abschnitten](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_1_-_Reftable_overview.svg)\n\nDie Abschnittstypen sind alle ähnlich strukturiert. Abschnitte enthalten eine Reihe von Datensätzen, die nach den Schlüsseln der einzelnen Datensätze sortiert sind. Wenn du zum Beispiel zwei Ref-Datensätze `refs/heads/aaaaa` und `refs/heads/bbb` hast, hast du zwei Ref-Datensätze mit diesen Referenznamen als jeweiligen Schlüssel, weshalb `refs/heads/aaaaa` vor `refs/heads/bbb` kommt.\n\nDarüber hinaus ist jeder Abschnitt in Blöcke mit einer festen Länge unterteilt. Diese Blocklänge ist im Header codiert und dient zwei Zwecken:\n\n- Da sie den Anfang des Abschnitts markieren und die Blockgröße angeben, weiß der bzw. die Leser(in) implizit, wo jeder der Blöcke beginnt. Dadurch kann Git gleich in die Mitte des Abschnitts springen, ohne vorherige Blocks lesen zu müssen. So kann die binäre Suche in Blöcken das Durchsuchen von Datensätzen beschleunigen.\n- Sie stellt sicher, dass Git weiß, wie viele Daten gleichzeitig von der Festplatte gelesen werden sollen. Folglich ist die Blockgröße standardmäßig auf 4 KiB eingestellt, was die häufigste Sektorgröße für Festplatten ist. Die maximale Blockgröße beträgt 16 MB.\n\nWenn wir zum Beispiel in einen „ref“-Abschnitt schauen, sieht er ungefähr wie die folgende Grafik aus. Achte darauf, wie die Datensätze lexikografisch in den Blocks, aber auch blockübergreifend sortiert sind.\n\n![Referenzblock, nicht komprimiert](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_2_-_Ref_block_uncompressed.svg)\n\nMit diesem Wissen können wir nun einen Datensatz finden, indem wir die folgenden Schritte befolgen:\n\n1. Führe eine Binärsuche über die Blocks durch, indem du dir die Schlüssel der jeweiligen ersten Datensätze ansiehst und den Block identifizierst, der unseren Datensatz enthalten muss.\n\n2. Führe eine lineare Suche in den Datensätzen dieses Blocks durch.\n\nBeide Schritte sind immer noch recht ineffizient. Wenn wir viele Blöcke haben, müssen wir logarithmisch viele davon in unserer Binärsuche lesen, um den gewünschten Block zu finden. Und wenn Blöcke viele Datensätze enthalten, müssen wir vielleicht bei der linearen Suche alle davon lesen.\n\nDas „reftable“-Format verfügt über zusätzliche integrierte Mechanismen, um diese Leistungsbedenken auszuräumen. Wir gehen in den nächsten Abschnitten darauf ein.\n\n### Präfix-Komprimierung\n\nWie du vielleicht bemerkt hast, haben alle Datensatzschlüssel das gleiche Präfix `refs/`. Dies ist häufig so in Git:\n\n- Alle Branches beginnen mit `refs/heads/`.\n- Alle Tags beginnen mit `refs/tags/`.\n\nDaher gehen wir davon aus, dass nachfolgende Datensätze höchstwahrscheinlich einen signifikanten Anteil ihres Schlüssels gemeinsam haben. Dies ist eine gute Gelegenheit, um wertvollen Speicherplatz zu sparen. Da wir wissen, dass die meisten Schlüssel ein gemeinsames Präfix haben, ist es sinnvoll, dies zu optimieren.\n\nDie Optimierung verwendet Präfix-Komprimierung. Jeder Datensatz kodiert eine Präfixlänge, die den Leser(innen) mitteilt, wie viele Bytes des Schlüssels des vorhergehenden Datensatzes wiederverwendet werden sollen. Wenn wir zwei Datensätze haben, `refs/heads/a` und `refs/heads/b`, kann letzterer kodiert werden, indem man eine Präfixlänge von 11 angibt und dann nur das Suffix `b` speichert. Die Leser(innen) nehmen dann die ersten 11 Bytes von `refs/heads/a`, was `refs/heads/` ist, und fügen das Suffix `b` hinzu.\n\n![Präfix-Komprimierung](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_3_-_Ref_block_prefix_compression.svg)\n\n### Neustart-Punkte\n\nWie bereits erklärt, ist eine lineare Suche der beste Weg, mit unserem derzeitigen Wissen über das „reftable“-Format in einem Block nach einer Referenz zu suchen. Der Grund dafür ist, dass die Datensätze keine fixe Länge haben. Daher können wir nicht feststellen, wo Datensätze beginnen, ohne von Anfang an den Block zu durchsuchen. Auch wenn Datensätze eine fixe Länge hätten, könnten wir nicht in der Mitte eines Blocks suchen, da die Präfix-Kompression erfordert, dass wir auch die vorhergehenden Datensätze lesen.\n\nEine lineare Suche wäre ziemlich ineffizient, da Blöcke Hunderte oder sogar Tausende von Datensätzen enthalten können. Um dieses Problem zu beheben, codiert das „reftable“-Format sogenannte Neustart-Punkte in jeden Block. Neustart-Punkte sind unkomprimierte Datensätze, bei denen keine Präfix-Komprimierung verwendet wird. Folglich enthalten Datensätze an Neustart-Punkten immer ihren vollständigen Schlüssel, und es wird möglich, den Datensatz direkt zu suchen und zu lesen, ohne die vorhergehenden Datensätze lesen zu müssen. Diese Neustart-Punkte sind in der Fußzeile jedes Blocks aufgeführt.\n\nMit diesen Informationen können wir eine lineare Suche über den Block vermeiden. Stattdessen können wir jetzt eine Binärsuche über die Neustart-Punkte durchführen, bei der wir nach dem ersten Neustart-Punkt mit einem Schlüssel suchen, der lexikographisch größer ist als der gesuchte Schlüssel. Daraus folgt, dass sich der gewünschte Datensatz in dem Abschnitt befinden muss, der sich vom _vorhergehenden_ Neustart-Punkt bis zum identifizierten Neustart-Punkt erstreckt.\n\nDaher ist unser erstes Vorgehen bei der Suche nach einem Datensatz (Binärsuche nach dem Block, Linearsuche nach dem Datensatz) nun wie folgt:\n\n1. Führe eine Binärsuche über die Blocks durch und finde den Block, der unseren Datensatz enthalten muss.\n\n2. Führe eine Binärsuche über die Neustart-Punkte durch und identifiziere den Unterabschnitt des Blocks, der unseren Datensatz enthalten muss.\n\n3. Führe eine lineare Suche in den Datensätzen dieses Unterabschnitts.\n\n![Lineare Suche nach einem Datensatz](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_4_-_Restart_points.svg)\n\n### Indizes\n\nDie Suche nach Datensätzen in einem Block wäre nun einigermaßen effizient. Es ist aber weiterhin ineffizient, den Block selbst zu finden. Eine Binärsuche kann bei ein paar Blöcken funktionieren, aber Repositories mit Millionen von Referenzen können Hunderte oder sogar Tausende von Blöcken haben. Ohne zusätzliche Datenstruktur würde dies durchschnittlich logarithmisch viele Festplattenzugriffe verursachen.\nUm dies zu vermeiden, kann auf jeden Abschnitt ein Indexabschnitt folgen, der eine effiziente Möglichkeit bietet, einen Block nachzuschlagen. Jeder Indexdatensatz enthält die folgenden Informationen:\n\n- Die Position des Blocks, den er indiziert.\n- Der Schlüssel des letzten Datensatzes des Blocks, den er indiziert.\n\nBei drei oder weniger Blöcken erfordert eine Binärsuche immer höchstens zwei Festplattenlesevorgänge, um den gewünschten Zielblock zu finden. Dies ist die gleiche Anzahl von Lesevorgängen, die wir mit einem Index hätten: einen, um den Index selbst zu lesen, und einen, um den gewünschten Block zu lesen. Folglich werden Indizes nur geschrieben, wenn sie tatsächlich einige Lesevorgänge einsparen würden, was ab vier indizierten Blöcken der Fall ist.\n\nNun stellt sich die Frage: Was passiert, wenn der Index selbst so groß wird, dass er sich über mehrere Blöcke erstreckt? Du hast es vielleicht erraten: Wir schreiben einen weiteren Index, der den Index indiziert. Diese mehrstufigen Indizes werden erst dann wirklich notwendig, wenn du Repositories mit hunderttausenden von Referenzen hast.\n\nMit diesen Indizes können wir jetzt das Verfahren zum Nachschlagen von Datensätzen noch effizienter machen:\n1. Finde heraus, ob es einen Index gibt, indem du dir die Fußzeile der Tabelle ansiehst.\n  - Wenn es einen gibt, führe eine Binärsuche über den Index durch, um den gewünschten Block zu finden. Dieser Block kann selbst auf einen Indexblock verweisen. In diesem Fall müssen wir diesen Schritt wiederholen, bis wir einen Datensatz des gewünschten Typs finden.\n  - Ansonsten führe eine Binärsuche über die Blöcke durch, wie wir es zuvor getan haben.\n2. Führe eine Binärsuche über die Neustart-Punkte durch und identifiziere den Unterabschnitt des Blocks, der unseren Datensatz enthalten muss.\n3. Führe eine lineare Suche in den Datensätzen dieses Unterabschnitts durch.\n\n## Mehrere Tabellen\n\nBis jetzt haben wir nur besprochen, wie man eine _einzelne_ Tabelle liest. Aber wie der Name `tables.list` schon sagt, kannst du tatsächlich eine Liste von Tabellen in deiner „reftable“-Datenbank haben.\n\nJedes Mal, wenn du eine Referenz in deinem Repository aktualisierst, wird eine neue Tabelle geschrieben und an `tables.list` angehängt. So hast du schließlich mehrere Tabellen:\n\n```shell\n$ tree .git/reftable/\n.git/reftable/\n├──0x0000000000000001-0x000000000007-8dcd8a77.ref\n├── 0x000000000008-0x000000000008-30e0f6f6.ref\n└── tables.list\n\n$ cat .git/reftable/tables.list\n0x000000000001-0x000000000007-8dcd8a77.ref\n0x000000000008-0x000000000008-30e0f6f6.ref\n```\n\nUm den tatsächlichen Status eines Repositorys zu lesen, müssen wir diese mehreren Tabellen zu einer einzigen virtuellen Tabelle zusammenführen.\n\nDu fragst dich vielleicht: Wenn für jede Referenzaktualisierung eine Tabelle geschrieben wird und dieselbe Referenz mehrmals aktualisiert wird, woher kennt das „reftable“-Format den aktuellsten Wert einer bestimmten Referenz? Intuitiv könnte man davon ausgehen, dass der Wert derjenige aus der neuesten Tabelle ist, die die Referenz enthält.\n\nTatsächlich hat jeder einzelne Datensatz einen sogenannten Aktualisierungsindex, der die „Priorität“ eines Datensatzes kodiert. Wenn beispielsweise zwei Ref-Datensätze mit demselben Namen existieren, überschreibt derjenige mit dem höheren Aktualisierungsindex denjenigen mit dem niedrigeren Aktualisierungsindex.\n\nDiese Aktualisierungsindizes sind in der obigen Dateistruktur sichtbar. Die langen Hex-Zeichenfolgen (z. B. `0x000000000001`) sind die Aktualisierungsindizes, wobei die linke Seite des Tabellennamens der minimale Aktualisierungsindex ist, der in der Tabelle enthalten ist, und die rechte Seite der maximale Aktualisierungsindex ist.\n\nDas Zusammenführen der Tabellen erfolgt dann über eine [Vorrangwarteschlange](https://de.wikipedia.org/wiki/Vorrangwarteschlange), die nach dem Schlüssel des Ref-Datensatzes sowie dem Aktualisierungsindex geordnet ist. Angenommen, wir möchten alle Ref-Datensätze durchsuchen, würden wir wie folgt vorgehen:\n\n1. Füge für jede Tabelle ihren ersten Datensatz zur Vorrangwarteschlange hinzu.\n\n![Ersten Datensatz zur Vorrangwarteschlange hinzufügen](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_5_-_Priority_queue_1.svg)\n\n2. Liefere den Kopf der Vorrangwarteschlange. Da die Warteschlange nach Aktualisierungsindex geordnet ist, muss sie die aktuellste Version sein. Füge das nächste Element aus dessen Tabelle zur Vorrangwarteschlange hinzu.\n\n![Head der Vorrangwarteschlange angeben](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_6_-_Priority_queue_2.svg)\n\n3. Ziehe alle Datensätze aus der Warteschlange, die den gleichen Namen haben. Diese Datensätze werden verschattet, was bedeutet, dass sie nicht angezeigt werden. Füge für jede Tabelle, für die wir Datensätze ablegen, den nächsten Datensatz zur Vorrangwarteschlange hinzu.\n\n![Alle Datensätze aus der Warteschlange ablegen, die den gleichen Namen haben](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749675179/Blog/Content%20Images/Frame_7_-_Priority_queue_3.svg)\n\nJetzt können wir bereinigen und den Vorgang wiederholen, um Datensätze für andere Schlüssel zu lesen.\n\nTabellen können spezielle „tombstone“-Datensätze enthalten, die einen Datensatz als gelöscht markieren. So können wir Datensätze löschen, ohne den jeweiligen Datensatz aus allen Tabellen löschen zu müssen.\n\n### Autokomprimierung\n\nWährend die Idee hinter der Vorrangwarteschlange zwar einfach ist, wäre es allerdings eher ineffizient, Hunderte oder sogar nur Dutzende von Tabellen auf diese Weise zusammenzuführen. Es stimmt, dass jede Aktualisierung an deinen Referenzen eine neue Tabelle an deine `tables.list`-Datei anhängt. Das ist jedoch nur ein Teil der Wahrheit.\n\nDer andere Teil ist die Autokomprimierung: Nachdem eine neue Tabelle an die Liste der Tabellen angehängt wurde, überprüft das „reftable“-Backend, ob manche der Tabellen zusammengeführt werden sollen. Dies erfolgt durch eine einfache Heuristik. Wir überprüfen, ob die Liste der Tabellen eine [geometrische Folge](https://de.wikipedia.org/wiki/Geometrische_Folge) der Dateigrößen bildet. Jede Tabelle `n` muss mindestens doppelt so groß sein wie die nächstletzte Tabelle `n + 1`. Wenn gegen diese geometrische Folge verstoßen wird, komprimiert das Backend die Tabellen, sodass die geometrische Folge wiederhergestellt wird.\n\nIm Laufe der Zeit führt dies zu Strukturen, die wie folgt aussehen:\n\n```shell\n$ du --apparent-size .git/reftable/*\n429    .git/reftable/0x000000000001-0x00000000bd7c-d9819000.ref\n101    .git/reftable/0x00000000bd7d-0x00000000c5ac-c34b88a4.ref\n32    .git/reftable/0x00000000c5ad-0x00000000cc6c-60391f53.ref\n8    .git/reftable/0x00000000cc6d-0x00000000cdc1-61c30db1.ref\n3    .git/reftable/0x00000000cdc2-0x00000000ce67-d9b55a96.ref\n1    .git/reftable/0x00000000ce68-0x00000000ce6b-44721696.ref\n1    .git/reftable/tables.list\n```\n\nBeachte, wie für jede einzelne Tabelle die Eigenschaft `size(n) > size(n+1) * 2` gilt.\n\nEine der Folgen der Autokomprimierung ist, dass sich das „reftable“-Backend selbst erhält. Wir müssen somit nicht mehr den Befehl `git pack-refs` zum Optimieren der Referenzen ausführen.\n\n## Möchtest du mehr erfahren?\n\nDu solltest jetzt ein gutes Verständnis dafür haben, wie das neue „reftable“-Format im Detail funktioniert. Wenn du noch tiefer in das Format eintauchen möchtest, kannst du dir dessen [technische Dokumentation](https://git-scm.com/docs/reftable) des Git-Projekts ansehen.\n\n> Lies dir unsere [Zusammenfassung von Git 2.45.0](https://about.gitlab.com/blog/whats-new-in-git-2-45-0/) durch, um herauszufinden, was sonst noch in dieser Version von Git auf dich wartet.\n",[18],"Patrick Steinhardt","2024-07-29","2024-05-30","Der Anfängerleitfaden zum „reftable“-Format von Git",[23,24,25,26],"git","tutorial","open source","performance","In Git 2.45.0 hat GitLab das reftable Backend in Git eingeführt – dies verändert die Art und Weise, wie Referenzen gespeichert werden, von Grund auf. Erhalte detaillierte Einblicke, wie dieses neue Format funktioniert.","yml",{},"/de-de/blog/a-beginners-guide-to-the-git-reftable-format",{"ogTitle":21,"ogImage":15,"ogDescription":27,"ogSiteName":32,"noIndex":33,"ogType":34,"ogUrl":35,"title":21,"canonicalUrls":35,"description":27},"https://about.gitlab.com",false,"article","https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format","de-de/blog/a-beginners-guide-to-the-git-reftable-format",[23,24,9,26],"gnbWuwwkufN_NteflqRC5TmnWCS3l_In2qReUkO8_Vc",{"data":40},{"logo":41,"freeTrial":46,"sales":51,"login":56,"items":61,"search":370,"minimal":405,"duo":423,"pricingDeployment":433},{"config":42},{"href":43,"dataGaName":44,"dataGaLocation":45},"/de-de/","gitlab logo","header",{"text":47,"config":48},"Kostenlose Testversion anfordern",{"href":49,"dataGaName":50,"dataGaLocation":45},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":52,"config":53},"Vertrieb kontaktieren",{"href":54,"dataGaName":55,"dataGaLocation":45},"/de-de/sales/","sales",{"text":57,"config":58},"Anmelden",{"href":59,"dataGaName":60,"dataGaLocation":45},"https://gitlab.com/users/sign_in/","sign in",[62,89,185,190,291,351],{"text":63,"config":64,"cards":66},"Plattform",{"dataNavLevelOne":65},"platform",[67,73,81],{"title":63,"description":68,"link":69},"Die intelligente Orchestrierungsplattform für DevSecOps",{"text":70,"config":71},"Erkunde unsere Plattform",{"href":72,"dataGaName":65,"dataGaLocation":45},"/de-de/platform/",{"title":74,"description":75,"link":76},"GitLab Duo Agent Platform","Agentische KI für den gesamten Softwareentwicklungszyklus",{"text":77,"config":78},"Lerne GitLab Duo kennen",{"href":79,"dataGaName":80,"dataGaLocation":45},"/de-de/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":82,"description":83,"link":84},"Gründe, die für GitLab sprechen","Erfahre, warum Unternehmen auf GitLab setzen",{"text":85,"config":86},"Mehr erfahren",{"href":87,"dataGaName":88,"dataGaLocation":45},"/de-de/why-gitlab/","why gitlab",{"text":90,"left":12,"config":91,"link":93,"lists":97,"footer":167},"Produkt",{"dataNavLevelOne":92},"solutions",{"text":94,"config":95},"Alle Lösungen anzeigen",{"href":96,"dataGaName":92,"dataGaLocation":45},"/de-de/solutions/",[98,123,145],{"title":99,"description":100,"link":101,"items":106},"Automatisierung","CI/CD und Automatisierung zur Beschleunigung der Bereitstellung",{"config":102},{"icon":103,"href":104,"dataGaName":105,"dataGaLocation":45},"AutomatedCodeAlt","/de-de/solutions/delivery-automation/","automated software delivery",[107,111,114,119],{"text":108,"config":109},"CI/CD",{"href":110,"dataGaLocation":45,"dataGaName":108},"/de-de/solutions/continuous-integration/",{"text":74,"config":112},{"href":79,"dataGaLocation":45,"dataGaName":113},"gitlab duo agent platform - product menu",{"text":115,"config":116},"Quellcodeverwaltung",{"href":117,"dataGaLocation":45,"dataGaName":118},"/de-de/solutions/source-code-management/","Source Code Management",{"text":120,"config":121},"Automatisierte Softwarebereitstellung",{"href":104,"dataGaLocation":45,"dataGaName":122},"Automated software delivery",{"title":124,"description":125,"link":126,"items":131},"Sicherheit","Entwickle schneller, ohne die Sicherheit zu gefährden",{"config":127},{"href":128,"dataGaName":129,"dataGaLocation":45,"icon":130},"/de-de/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[132,136,141],{"text":133,"config":134},"Application Security Testing",{"href":128,"dataGaName":135,"dataGaLocation":45},"Application security testing",{"text":137,"config":138},"Schutz der Software-Lieferkette",{"href":139,"dataGaLocation":45,"dataGaName":140},"/de-de/solutions/supply-chain/","Software supply chain security",{"text":142,"config":143},"Software Compliance",{"href":144,"dataGaName":142,"dataGaLocation":45},"/de-de/solutions/software-compliance/",{"title":146,"link":147,"items":152},"Bewertung",{"config":148},{"icon":149,"href":150,"dataGaName":151,"dataGaLocation":45},"DigitalTransformation","/de-de/solutions/visibility-measurement/","visibility and measurement",[153,157,162],{"text":154,"config":155},"Sichtbarkeit und Bewertung",{"href":150,"dataGaLocation":45,"dataGaName":156},"Visibility and Measurement",{"text":158,"config":159},"Wertstrommanagement",{"href":160,"dataGaLocation":45,"dataGaName":161},"/de-de/solutions/value-stream-management/","Value Stream Management",{"text":163,"config":164},"Analysen und Einblicke",{"href":165,"dataGaLocation":45,"dataGaName":166},"/de-de/solutions/analytics-and-insights/","Analytics and insights",{"title":168,"items":169},"GitLab für",[170,175,180],{"text":171,"config":172},"Enterprise",{"href":173,"dataGaLocation":45,"dataGaName":174},"/de-de/enterprise/","enterprise",{"text":176,"config":177},"Kleinunternehmen",{"href":178,"dataGaLocation":45,"dataGaName":179},"/de-de/small-business/","small business",{"text":181,"config":182},"den öffentlichen Sektor",{"href":183,"dataGaLocation":45,"dataGaName":184},"/de-de/solutions/public-sector/","public sector",{"text":186,"config":187},"Preise",{"href":188,"dataGaName":189,"dataGaLocation":45,"dataNavLevelOne":189},"/de-de/pricing/","pricing",{"text":191,"config":192,"link":194,"lists":198,"feature":278},"Ressourcen",{"dataNavLevelOne":193},"resources",{"text":195,"config":196},"Alle Ressourcen anzeigen",{"href":197,"dataGaName":193,"dataGaLocation":45},"/de-de/resources/",[199,232,250],{"title":200,"items":201},"Erste Schritte",[202,207,212,217,222,227],{"text":203,"config":204},"Installieren",{"href":205,"dataGaName":206,"dataGaLocation":45},"/de-de/install/","install",{"text":208,"config":209},"Kurzanleitungen",{"href":210,"dataGaName":211,"dataGaLocation":45},"/de-de/get-started/","quick setup checklists",{"text":213,"config":214},"Lernen",{"href":215,"dataGaLocation":45,"dataGaName":216},"https://university.gitlab.com/","learn",{"text":218,"config":219},"Produktdokumentation",{"href":220,"dataGaName":221,"dataGaLocation":45},"https://docs.gitlab.com/","product documentation",{"text":223,"config":224},"Best-Practice-Videos",{"href":225,"dataGaName":226,"dataGaLocation":45},"/de-de/getting-started-videos/","best practice videos",{"text":228,"config":229},"Integrationen",{"href":230,"dataGaName":231,"dataGaLocation":45},"/de-de/integrations/","integrations",{"title":233,"items":234},"Entdecken",[235,240,245],{"text":236,"config":237},"Kundenerfolge",{"href":238,"dataGaName":239,"dataGaLocation":45},"/de-de/customers/","customer success stories",{"text":241,"config":242},"Blog",{"href":243,"dataGaName":244,"dataGaLocation":45},"/de-de/blog/","blog",{"text":246,"config":247},"Remote",{"href":248,"dataGaName":249,"dataGaLocation":45},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":251,"items":252},"Vernetzen",[253,258,263,268,273],{"text":254,"config":255},"GitLab-Services",{"href":256,"dataGaName":257,"dataGaLocation":45},"/de-de/services/","services",{"text":259,"config":260},"Community",{"href":261,"dataGaName":262,"dataGaLocation":45},"/community/","community",{"text":264,"config":265},"Forum",{"href":266,"dataGaName":267,"dataGaLocation":45},"https://forum.gitlab.com/","forum",{"text":269,"config":270},"Veranstaltungen",{"href":271,"dataGaName":272,"dataGaLocation":45},"/events/","events",{"text":274,"config":275},"Partner",{"href":276,"dataGaName":277,"dataGaLocation":45},"/de-de/partners/","partners",{"backgroundColor":279,"textColor":280,"text":281,"image":282,"link":286},"#2f2a6b","#fff","Perspektiven für die Softwareentwicklung der Zukunft",{"altText":283,"config":284},"the source promo card",{"src":285},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":287,"config":288},"Lies die News",{"href":289,"dataGaName":290,"dataGaLocation":45},"/de-de/the-source/","the source",{"text":292,"config":293,"lists":295},"Unternehmen",{"dataNavLevelOne":294},"company",[296],{"items":297},[298,303,309,311,316,321,326,331,336,341,346],{"text":299,"config":300},"Über",{"href":301,"dataGaName":302,"dataGaLocation":45},"/de-de/company/","about",{"text":304,"config":305,"footerGa":308},"Karriere",{"href":306,"dataGaName":307,"dataGaLocation":45},"/jobs/","jobs",{"dataGaName":307},{"text":269,"config":310},{"href":271,"dataGaName":272,"dataGaLocation":45},{"text":312,"config":313},"Geschäftsführung",{"href":314,"dataGaName":315,"dataGaLocation":45},"/company/team/e-group/","leadership",{"text":317,"config":318},"Team",{"href":319,"dataGaName":320,"dataGaLocation":45},"/company/team/","team",{"text":322,"config":323},"Handbuch",{"href":324,"dataGaName":325,"dataGaLocation":45},"https://handbook.gitlab.com/","handbook",{"text":327,"config":328},"Investor Relations",{"href":329,"dataGaName":330,"dataGaLocation":45},"https://ir.gitlab.com/","investor relations",{"text":332,"config":333},"Trust Center",{"href":334,"dataGaName":335,"dataGaLocation":45},"/de-de/security/","trust center",{"text":337,"config":338},"AI Transparency Center",{"href":339,"dataGaName":340,"dataGaLocation":45},"/de-de/ai-transparency-center/","ai transparency center",{"text":342,"config":343},"Newsletter",{"href":344,"dataGaName":345,"dataGaLocation":45},"/company/contact/#contact-forms","newsletter",{"text":347,"config":348},"Presse",{"href":349,"dataGaName":350,"dataGaLocation":45},"/press/","press",{"text":352,"config":353,"lists":354},"Kontakt",{"dataNavLevelOne":294},[355],{"items":356},[357,360,365],{"text":52,"config":358},{"href":54,"dataGaName":359,"dataGaLocation":45},"talk to sales",{"text":361,"config":362},"Support-Portal",{"href":363,"dataGaName":364,"dataGaLocation":45},"https://support.gitlab.com","support portal",{"text":366,"config":367},"Kundenportal",{"href":368,"dataGaName":369,"dataGaLocation":45},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":371,"login":372,"suggestions":379},"Schließen",{"text":373,"link":374},"Um Repositories und Projekte zu durchsuchen, melde dich an bei",{"text":375,"config":376},"gitlab.com",{"href":59,"dataGaName":377,"dataGaLocation":378},"search login","search",{"text":380,"default":381},"Vorschläge",[382,384,389,391,396,401],{"text":74,"config":383},{"href":79,"dataGaName":74,"dataGaLocation":378},{"text":385,"config":386},"Code Suggestions (KI)",{"href":387,"dataGaName":388,"dataGaLocation":378},"/de-de/solutions/code-suggestions/","Code Suggestions (AI)",{"text":108,"config":390},{"href":110,"dataGaName":108,"dataGaLocation":378},{"text":392,"config":393},"GitLab auf AWS",{"href":394,"dataGaName":395,"dataGaLocation":378},"/de-de/partners/technology-partners/aws/","GitLab on AWS",{"text":397,"config":398},"GitLab auf Google Cloud",{"href":399,"dataGaName":400,"dataGaLocation":378},"/de-de/partners/technology-partners/google-cloud-platform/","GitLab on Google Cloud",{"text":402,"config":403},"Warum GitLab?",{"href":87,"dataGaName":404,"dataGaLocation":378},"Why GitLab?",{"freeTrial":406,"mobileIcon":411,"desktopIcon":416,"secondaryButton":419},{"text":407,"config":408},"Kostenlos testen",{"href":409,"dataGaName":50,"dataGaLocation":410},"https://gitlab.com/-/trials/new/","nav",{"altText":412,"config":413},"GitLab-Symbol",{"src":414,"dataGaName":415,"dataGaLocation":410},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":412,"config":417},{"src":418,"dataGaName":415,"dataGaLocation":410},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":200,"config":420},{"href":421,"dataGaName":422,"dataGaLocation":410},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/de-de/compare/gitlab-vs-github/","get started",{"freeTrial":424,"mobileIcon":429,"desktopIcon":431},{"text":425,"config":426},"Erfahre mehr über GitLab Duo",{"href":427,"dataGaName":428,"dataGaLocation":410},"/de-de/gitlab-duo/","gitlab duo",{"altText":412,"config":430},{"src":414,"dataGaName":415,"dataGaLocation":410},{"altText":412,"config":432},{"src":418,"dataGaName":415,"dataGaLocation":410},{"freeTrial":434,"mobileIcon":439,"desktopIcon":441},{"text":435,"config":436},"Zurück zur Preisübersicht",{"href":188,"dataGaName":437,"dataGaLocation":410,"icon":438},"back to pricing","GoBack",{"altText":412,"config":440},{"src":414,"dataGaName":415,"dataGaLocation":410},{"altText":412,"config":442},{"src":418,"dataGaName":415,"dataGaLocation":410},{"title":444,"button":445,"config":450},"Sieh dir an, wie agentische KI die Softwarebereitstellung transformiert",{"text":446,"config":447},"GitLab Transcend jetzt ansehen",{"href":448,"dataGaName":449,"dataGaLocation":45},"/de-de/events/transcend/virtual/","transcend event",{"layout":451,"icon":452},"release","AiStar",{"data":454},{"text":455,"source":456,"edit":462,"contribute":467,"config":472,"items":477,"minimal":650},"Git ist eine Marke von Software Freedom Conservancy und unsere Verwendung von „GitLab“ erfolgt unter Lizenz.",{"text":457,"config":458},"Quelltext der Seite anzeigen",{"href":459,"dataGaName":460,"dataGaLocation":461},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":463,"config":464},"Diese Seite bearbeiten",{"href":465,"dataGaName":466,"dataGaLocation":461},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":468,"config":469},"Beteilige dich",{"href":470,"dataGaName":471,"dataGaLocation":461},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":473,"facebook":474,"youtube":475,"linkedin":476},"https://x.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[478,501,556,583,617],{"title":63,"links":479,"subMenu":484},[480],{"text":481,"config":482},"DevSecOps-Plattform",{"href":72,"dataGaName":483,"dataGaLocation":461},"devsecops platform",[485],{"title":186,"links":486},[487,491,496],{"text":488,"config":489},"Tarife anzeigen",{"href":188,"dataGaName":490,"dataGaLocation":461},"view plans",{"text":492,"config":493},"Vorteile von Premium",{"href":494,"dataGaName":495,"dataGaLocation":461},"/de-de/pricing/premium/","why premium",{"text":497,"config":498},"Vorteile von Ultimate",{"href":499,"dataGaName":500,"dataGaLocation":461},"/de-de/pricing/ultimate/","why ultimate",{"title":502,"links":503},"Lösungen",[504,509,512,514,519,524,528,531,534,539,541,543,546,551],{"text":505,"config":506},"Digitale Transformation",{"href":507,"dataGaName":508,"dataGaLocation":461},"/de-de/topics/digital-transformation/","digital transformation",{"text":510,"config":511},"Sicherheit und Compliance",{"href":128,"dataGaName":135,"dataGaLocation":461},{"text":120,"config":513},{"href":104,"dataGaName":105,"dataGaLocation":461},{"text":515,"config":516},"Agile Entwicklung",{"href":517,"dataGaName":518,"dataGaLocation":461},"/de-de/solutions/agile-delivery/","agile delivery",{"text":520,"config":521},"Cloud-Transformation",{"href":522,"dataGaName":523,"dataGaLocation":461},"/de-de/topics/cloud-native/","cloud transformation",{"text":525,"config":526},"SCM",{"href":117,"dataGaName":527,"dataGaLocation":461},"source code management",{"text":108,"config":529},{"href":110,"dataGaName":530,"dataGaLocation":461},"continuous integration & delivery",{"text":158,"config":532},{"href":160,"dataGaName":533,"dataGaLocation":461},"value stream management",{"text":535,"config":536},"GitOps",{"href":537,"dataGaName":538,"dataGaLocation":461},"/de-de/solutions/gitops/","gitops",{"text":171,"config":540},{"href":173,"dataGaName":174,"dataGaLocation":461},{"text":176,"config":542},{"href":178,"dataGaName":179,"dataGaLocation":461},{"text":544,"config":545},"Öffentlicher Sektor",{"href":183,"dataGaName":184,"dataGaLocation":461},{"text":547,"config":548},"Bildungswesen",{"href":549,"dataGaName":550,"dataGaLocation":461},"/de-de/solutions/education/","education",{"text":552,"config":553},"Finanzdienstleistungen",{"href":554,"dataGaName":555,"dataGaLocation":461},"/de-de/solutions/finance/","financial services",{"title":191,"links":557},[558,560,562,564,567,569,571,573,575,577,579,581],{"text":203,"config":559},{"href":205,"dataGaName":206,"dataGaLocation":461},{"text":208,"config":561},{"href":210,"dataGaName":211,"dataGaLocation":461},{"text":213,"config":563},{"href":215,"dataGaName":216,"dataGaLocation":461},{"text":218,"config":565},{"href":220,"dataGaName":566,"dataGaLocation":461},"docs",{"text":241,"config":568},{"href":243,"dataGaName":244,"dataGaLocation":461},{"text":236,"config":570},{"href":238,"dataGaName":239,"dataGaLocation":461},{"text":246,"config":572},{"href":248,"dataGaName":249,"dataGaLocation":461},{"text":254,"config":574},{"href":256,"dataGaName":257,"dataGaLocation":461},{"text":259,"config":576},{"href":261,"dataGaName":262,"dataGaLocation":461},{"text":264,"config":578},{"href":266,"dataGaName":267,"dataGaLocation":461},{"text":269,"config":580},{"href":271,"dataGaName":272,"dataGaLocation":461},{"text":274,"config":582},{"href":276,"dataGaName":277,"dataGaLocation":461},{"title":292,"links":584},[585,587,589,591,593,595,597,601,606,608,610,612],{"text":299,"config":586},{"href":301,"dataGaName":294,"dataGaLocation":461},{"text":304,"config":588},{"href":306,"dataGaName":307,"dataGaLocation":461},{"text":312,"config":590},{"href":314,"dataGaName":315,"dataGaLocation":461},{"text":317,"config":592},{"href":319,"dataGaName":320,"dataGaLocation":461},{"text":322,"config":594},{"href":324,"dataGaName":325,"dataGaLocation":461},{"text":327,"config":596},{"href":329,"dataGaName":330,"dataGaLocation":461},{"text":598,"config":599},"Sustainability",{"href":600,"dataGaName":598,"dataGaLocation":461},"/sustainability/",{"text":602,"config":603},"Vielfalt, Inklusion und Zugehörigkeit",{"href":604,"dataGaName":605,"dataGaLocation":461},"/de-de/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":332,"config":607},{"href":334,"dataGaName":335,"dataGaLocation":461},{"text":342,"config":609},{"href":344,"dataGaName":345,"dataGaLocation":461},{"text":347,"config":611},{"href":349,"dataGaName":350,"dataGaLocation":461},{"text":613,"config":614},"Transparenzerklärung zu moderner Sklaverei",{"href":615,"dataGaName":616,"dataGaLocation":461},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":618,"links":619},"Nimm Kontakt auf",[620,623,628,630,635,640,645],{"text":621,"config":622},"Sprich mit einem Experten/einer Expertin",{"href":54,"dataGaName":55,"dataGaLocation":461},{"text":624,"config":625},"Support",{"href":626,"dataGaName":627,"dataGaLocation":461},"/support/","get help",{"text":366,"config":629},{"href":368,"dataGaName":369,"dataGaLocation":461},{"text":631,"config":632},"Status",{"href":633,"dataGaName":634,"dataGaLocation":461},"https://status.gitlab.com/","status",{"text":636,"config":637},"Nutzungsbedingungen",{"href":638,"dataGaName":639,"dataGaLocation":461},"/terms/","terms of use",{"text":641,"config":642},"Datenschutzerklärung",{"href":643,"dataGaName":644,"dataGaLocation":461},"/de-de/privacy/","privacy statement",{"text":646,"config":647},"Cookie-Einstellungen",{"dataGaName":648,"dataGaLocation":461,"id":649,"isOneTrustButton":12},"cookie preferences","ot-sdk-btn",{"items":651},[652,654,656],{"text":636,"config":653},{"href":638,"dataGaName":639,"dataGaLocation":461},{"text":641,"config":655},{"href":643,"dataGaName":644,"dataGaLocation":461},{"text":646,"config":657},{"dataGaName":648,"dataGaLocation":461,"id":649,"isOneTrustButton":12},[659],{"id":660,"title":18,"body":8,"config":661,"content":663,"description":8,"extension":28,"meta":667,"navigation":12,"path":668,"seo":669,"stem":670,"__hash__":671},"blogAuthors/en-us/blog/authors/patrick-steinhardt.yml",{"template":662},"BlogAuthor",{"name":18,"config":664},{"headshot":665,"ctfId":666},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661952/Blog/Author%20Headshots/pks-gitlab-headshot.png","pksgitlab",{},"/en-us/blog/authors/patrick-steinhardt",{},"en-us/blog/authors/patrick-steinhardt","SV9Yd_vW69UbvntDP-SEOV9NKT_VwUAj5nfftf2ElSw",[673,686,698],{"content":674,"config":684},{"title":675,"description":676,"authors":677,"heroImage":679,"date":680,"body":681,"category":9,"tags":682,"updatedDate":680},"Kubernetes: Container-Orchestrierung verstehen und einsetzen","Kubernetes (K8s) für containerisierte Anwendungen: Dieser Artikel erklärt Architektur, Vorteile, Grenzen und den Einsatz mit GitLab.",[678],"GitLab Team","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660215/Blog/Hero%20Images/kubernetes-container-orchestration-solution.jpg","2026-03-02","Kubernetes automatisiert die Bereitstellung und Verwaltung\ncontainerisierter Anwendungen in großem Maßstab. Mit der Zeit ist\nKubernetes zu einem zentralen Werkzeug für die Anwendungsentwicklung\ngeworden – etwa in den Bereichen\n[Microservices](https://about.gitlab.com/de-de/topics/microservices/),\nWebanwendungen und Datenbanken. Leistungsfähigkeit und Skalierbarkeit\nmachen K8s heute zum anerkannten Standard im Container-Management.\n\nDieser Artikel bietet einen umfassenden Einstieg in Kubernetes.\n\n## Was ist Kubernetes?\n\nKubernetes ist ein Open-Source-System zur effizienten Orchestrierung von\nContainern einer Softwareanwendung. Containerisierung ist ein weit\nverbreiteter Ansatz in der Anwendungsentwicklung – besonders im Bereich\nder digitalen Transformation und der Cloud.\n\nZur Erinnerung: **Containerisierung ist eine Methode der\nAnwendungsentwicklung, bei der die Komponenten einer Anwendung in\nstandardisierte, geräte- und betriebssystemunabhängige Einheiten –\nsogenannte Container – zusammengefasst werden.** Durch die Isolierung von\nAnwendungen von ihrer Umgebung erleichtert diese Technologie die\nBereitstellung und Portabilität und reduziert Kompatibilitätsprobleme.\n\nHier kommt Kubernetes ins Spiel. Container ermöglichen zwar die Aufteilung\nvon Anwendungen in kleinere, eigenständige Module, die leichter\nbereitzustellen sind. Damit Container jedoch innerhalb einer Anwendung\nzusammenarbeiten können, ist ein übergeordnetes Verwaltungssystem\nerforderlich. Genau das leistet Kubernetes: Die Plattform steuert, wo und\nwie Container ausgeführt werden, und ermöglicht so die Orchestrierung und\nPlanung containerisierter Anwendungen in großem Maßstab.\n\n> Weitere [GitLab-Artikel zu Kubernetes](https://about.gitlab.com/de-de/blog/tags/kubernetes/).\n\n## Wie funktioniert eine Kubernetes-Architektur?\n\nUm die Kubernetes-Architektur zu verstehen, sind einige grundlegende\nKonzepte wichtig – allen voran das des Clusters, der die umfassendste\nEinheit innerhalb der Architektur darstellt. Ein Kubernetes-Cluster ist\ndie Gesamtheit der virtuellen oder physischen Maschinen, auf denen eine\ncontainerisierte Anwendung betrieben wird.\n\n![Komponenten von\nKubernetes](https://res.cloudinary.com/about-gitlab-com/image/upload/v1749673941/Blog/Content%20Images/components-of-kubernetes.png)\n\nQuelle:\n[Kubernetes](https://kubernetes.io/docs/concepts/overview/components/).\n\nEin Cluster besteht aus verschiedenen Elementen:\n- Node: Eine Arbeitseinheit im Kubernetes-Cluster – eine virtuelle oder\nphysische Maschine, die Aufgaben im Auftrag der Anwendung übernimmt.\n- Pod: Der kleinste bereitstellbare Baustein in Kubernetes. Ein Pod ist\neine Gruppe von Containern, die gemeinsam auf demselben Node ausgeführt\nwerden. Container innerhalb eines Pods teilen dasselbe Netzwerk und\nkommunizieren über localhost miteinander.\n- Service: Ein Kubernetes-Service macht einen Pod für das Netzwerk oder\nandere Pods zugänglich und bietet einen stabilen, klar definierten\nZugangspunkt zu den in Pods gehosteten Anwendungen.\n- Volume: Eine Ordnerabstraktion, die Probleme beim Teilen und Abrufen\nvon Dateien innerhalb eines Containers löst.\n- Namespace: Ein Namespace ermöglicht die Gruppierung und Isolierung von\nRessourcen zu einem virtuellen Cluster.\n\nDie Kubernetes-Architektur basiert auf zwei Knotentypen: dem Master Node\nund den Worker Nodes. Der Master Node ist für die übergeordnete Verwaltung\ndes Kubernetes-Clusters und die Kommunikation mit den Worker Nodes\nzuständig. Zu seinen zentralen Komponenten zählt die API als\nKommunikationszentrum zwischen Nutzenden und Cluster. Das\n[etcd](https://kubernetes.io/docs/concepts/overview/components/#etcd)\nist die Key-Value-Datenbank, in der Konfigurationen, Systemzustand und\nObjekt-Metadaten gespeichert werden. Der Controller Manager koordiniert\nHintergrundoperationen wie die Pod-Replikation, der Scheduler platziert\nPods auf Nodes entsprechend der verfügbaren Ressourcen.\n\nWorker Nodes hingegen sind die Maschinen, auf denen die in den Pods\nenthaltenen Anwendungen ausgeführt und verwaltet werden. Das\n[kubelet](https://kubernetes.io/docs/concepts/overview/components/#kubelet)\nist der Agent, der auf jedem Node läuft und mit dem Master kommuniziert,\num Befehle zu empfangen und den Status der Pods zu übermitteln. Der\nNetzwerk-Proxy\n[kube-proxy](https://kubernetes.io/docs/concepts/overview/components/)\npflegt die Netzwerkregeln auf den Nodes und ermöglicht so den Zugriff auf\nServices von außerhalb des Kubernetes-Clusters. Die Container-Runtime\nschließlich ist die Software, die für die Ausführung und Verwaltung der\nContainer innerhalb der Pods verantwortlich ist.\n\n### Die Rolle von Docker\n\nBei allen Komponenten eines K8s-Clusters ist die Wahl der Runtime innerhalb\nder Worker Nodes von Bedeutung. Verschiedene Softwarelösungen stehen dafür\nzur Verfügung, etwa CRI-O – Docker ist jedoch das am häufigsten eingesetzte\nWerkzeug.\n\n### Was ist der Unterschied zwischen Docker und Kubernetes?\n\nDocker ist eine Open-Source-Lösung, die speziell auf Container-Ebene\neingesetzt wird. Sie ermöglicht die Paketierung von Containern in einem\nstandardisierten und schlanken Format, was ihre Portabilität in\nverschiedenen Umgebungen erhöht. Docker ist damit ein ergänzendes Werkzeug\nzu K8s: Es vereinfacht die Verwaltung der Container selbst, während\nKubernetes deren Integration und Kommunikation innerhalb der Anwendung\nerleichtert.\n\n## Welche Vorteile bietet Kubernetes?\n\nSeit dem Start durch Google im Jahr 2014 und der ersten stabilen Version\nim Juli 2015 hat sich Kubernetes als Referenz im Bereich der\nContainer-Orchestrierung etabliert – insbesondere für\nMicroservice-orientierte Architekturen. Diese Verbreitung ist vor allem\nauf die Leistungsfähigkeit von K8s in der Container-Orchestrierung\nzurückzuführen.\n\nDie Vorteile von Kubernetes im Überblick:\n- Automatisierung: Kubernetes erleichtert die Automatisierung von Aufgaben\nrund um Bereitstellung, Skalierung und Aktualisierung containerisierter\nAnwendungen.\n- Flexibilität: Die Software passt sich an unterschiedliche\nContainer-Technologien sowie verschiedene Hardware-Architekturen und\nBetriebssysteme an.\n- Skalierbarkeit: K8s ermöglicht die Bereitstellung und Verwaltung\ntausender Container – unabhängig von deren Status: laufend, pausiert oder\ngestoppt.\n- Migration: Anwendungen lassen sich zu Kubernetes migrieren, ohne den\nQuellcode ändern zu müssen.\n- Multi-Cluster-Unterstützung: Kubernetes verwaltet zentral mehrere\nContainer-Cluster, die über verschiedene Infrastrukturen verteilt sind.\n- Update-Management: Die Software unterstützt Rolling-Update-Deployments,\num Anwendungen ohne Serviceunterbrechung zu aktualisieren.\n\n## Ein robustes und skalierbares Ökosystem\n\nKubernetes zeichnet sich durch die Fähigkeit aus, Container effizient und\nzuverlässig zu verwalten und dabei unabhängig von Cloud-Infrastrukturanbietern\nzu bleiben. Die modulare Architektur passt sich den spezifischen\nAnforderungen jedes Unternehmens an und unterstützt ein breites Spektrum\nan Anwendungen und Diensten – von Webservices über Datenverarbeitung bis\nhin zu mobilen Anwendungen.\n\nKubernetes profitiert dabei von einem umfangreichen und aktiven\nOpen-Source-Ökosystem. Verwaltet von der Cloud Native Computing Foundation\n([CNCF](https://www.cncf.io/)), wird K8s von tausenden Entwicklerinnen\nund Entwicklern weltweit unterstützt, die kontinuierlich zur\nWeiterentwicklung des Projekts und seiner Funktionen beitragen.\n\n## Was sind die Grenzen von Kubernetes?\n\nDie Stärken von Kubernetes machen es für viele Entwicklungsteams im\nCloud-nativen Bereich zur soliden Grundlage. Dennoch lohnt es sich,\neinige Einschränkungen zu benennen. Kubernetes erfordert fundierte\ntechnische Kenntnisse sowie die Einarbeitung in neue Entwicklungskonzepte\nund -methoden. Die Konfiguration kann zu Beginn eines Projekts komplex\nsein – ist dabei aber entscheidend, insbesondere für die Absicherung der\nPlattform. Ein erfahrenes Entwicklungsteam mit K8s-Kenntnissen ist daher\nein wesentlicher Vorteil.\n\nEine weitere Herausforderung ist die Implementierung und Wartung einer\nK8s-Architektur, die Zeit und Ressourcen erfordert – vor allem für die\nAktualisierung der verschiedenen Komponenten und Softwareteile. Dabei\nstellt sich auch die Frage nach möglichem Oversizing: Bei kleineren\nAnwendungen oder Projekten ohne besondere Skalierungsanforderungen kann\neine einfachere Architektur ausreichend und wirtschaftlicher sein.\n\n## Kubernetes im Unternehmenseinsatz\n\nZehntausende Unternehmen haben eine Kubernetes-Architektur für ihre\ndigitale Transformation übernommen. K8s wird von Organisationen aller\nGrößen genutzt – von Startups bis zu multinationalen Konzernen.\n\nEin Beispiel für eine erfolgreiche Integration ist Haven Technologies.\nDas Unternehmen hat seine SaaS-Dienste zu K8s migriert. Dabei setzt es\nauf eine Kubernetes-Strategie mit der GitLab-DevSecOps-Plattform –\nmit messbaren Verbesserungen bei Effizienz, Sicherheit und\nEntwicklungsgeschwindigkeit. Weitere Details in der\n[Kundenreferenz](https://about.gitlab.com/customers/haven-technologies/).\n\n## Kubernetes, Git und GitLab\n\nKubernetes, Git und GitLab sind zentrale Bausteine der DevOps-Landschaft.\nKubernetes bietet hohe Flexibilität bei der Bereitstellung und Verwaltung\nder verschiedenen Anwendungskomponenten. GitLab – aufgebaut auf Git und\ndessen nativer Versionskontrolle – ermöglicht eine präzise Nachverfolgung\nvon Quellcode und Änderungen und stellt eine umfassende Werkzeugsammlung\nfür den gesamten Software-Entwicklungslebenszyklus bereit.\n\nDiese Kombination schafft gemeinsam mit einem\n[GitOps-Ansatz](https://about.gitlab.com/de-de/topics/gitops/), der die\nAutomatisierung moderner Cloud-Infrastrukturen zum Ziel hat, eine agile\nUmgebung für Anwendungsentwicklung und -bereitstellung. Alle\n[GitLab-Lösungen für den Einsatz mit Kubernetes](https://about.gitlab.com/de-de/solutions/kubernetes/)\nim Überblick.\n\n## Kubernetes FAQ\n\n### Welche Alternativen zu K8s gibt es?\n\nEs gibt verschiedene Alternativen zu Kubernetes, darunter Docker Swarm\nund Marathon. Kubernetes gilt jedoch als die ausgereifteste und am\nweitesten verbreitete Lösung auf dem Markt. Die große Nutzerbasis,\numfangreiche Dokumentation und eine aktive Community machen K8s zur\nsoliden Wahl für alle, die ein Container-Orchestrierungssystem einsetzen\nmöchten.\n\n### Was ist ein Kubernetes-Cluster?\n\nEin Kubernetes-Cluster besteht aus einem Master Node und mehreren Worker\nNodes. Der Master Node koordiniert die Aufgaben im Cluster, während die\nWorker Nodes diese Orchestrierungsaufgaben ausführen und die Container\nhosten. K8s-Cluster sind hoch skalierbar – Nodes lassen sich hinzufügen\noder entfernen, um die Clusterressourcen an die Anforderungen der Anwendung\nanzupassen.\n\n### Wie startet man mit Kubernetes?\n\nZunächst ist die Installation der Kubernetes-Software in einer kompatiblen\nUmgebung (Linux, macOS oder Windows) erforderlich. Kubernetes lässt sich\nsowohl in einer klassischen Hosting-Umgebung als auch in der Cloud\ninstallieren – etwa auf Google Kubernetes Engine oder Amazon EKS. Nach\ndem Download und der Installation von der offiziellen Website folgt die\nErstkonfiguration zur Verbindung von Master und Worker Nodes. Danach ist\ndie erste Anwendung mit Kubernetes einsatzbereit.\n\n### Warum Kubernetes wählen?\n\nKubernetes bietet hohe Flexibilität und vollständige Portabilität zwischen\nverschiedenen Cloud-Plattformen oder On-Premises-Infrastrukturen. Durch\ndie Automatisierung von Orchestrierungsaufgaben lassen sich Ressourcen\noptimieren und Betriebskosten senken. Das Kubernetes-Ökosystem ist\numfangreich und wird von einer großen Open-Source-Community\nkontinuierlich weiterentwickelt.\n\n## Mehr erfahren\n\n- [Logs über das GitLab Dashboard für Kubernetes streamen](https://about.gitlab.com/blog/how-to-stream-logs-through-the-gitlab-dashboard-for-kubernetes/)\n- [Kubernetes-Überblick: Cluster-Daten im Frontend verwalten](https://about.gitlab.com/blog/kubernetes-overview-operate-cluster-data-on-the-frontend/)\n- [Cloud-Account-Management für Kubernetes-Zugriff vereinfachen](https://about.gitlab.com/blog/simplify-your-cloud-account-management-for-kubernetes-access/)\n",[683,25],"kubernetes",{"slug":685,"featured":33,"template":13},"kubernetes-the-container-orchestration-solution",{"content":687,"config":696},{"title":688,"description":689,"authors":690,"date":692,"body":693,"heroImage":694,"category":9,"tags":695},"Was ist neu in Git 2.53.0?","Alles, was du über dieses Release wissen musst, darunter Fixes für geometrisches Repacking, Updates zu den Commit-Signature-Handling-Optionen von git-fast-import(1) und mehr.",[691],"Justin Tobler","2026-02-02","Das Git-Projekt hat kürzlich [Git 2.53.0](https://lore.kernel.org/git/xmqq4inz13e3.fsf@gitster.g/T/#u) veröffentlicht. Schauen wir uns einige Highlights dieses Releases an, das auch Beiträge vom Git-Team bei GitLab enthält.\n\n## Unterstützung für geometrisches Repacking mit Promisor Remotes\n\nNeu geschriebene Objekte in einem Git-Repository werden oft als einzelne Loose Files gespeichert. Um gute Performance und optimale Nutzung des Speicherplatzes zu gewährleisten, werden diese Loose Objects regelmäßig in sogenannte Packfiles komprimiert. Die Anzahl der Packfiles in einem Repository wächst im Laufe der Zeit durch die Aktivitäten des Users, wie das Schreiben neuer Commits oder das Fetchen von einem Remote. Je mehr Packfiles sich in einem Repository befinden, desto mehr Arbeit hat Git beim Nachschlagen einzelner Objekte. Um die optimale Repository-Performance zu erhalten, werden Packfiles daher regelmäßig über git-repack(1) neu gepackt, um die Objekte in weniger Packfiles zu konsolidieren. Beim Repacking gibt es zwei Strategien: „All-into-One\" und „Geometric\".\n\nDie All-into-One-Strategie ist relativ unkompliziert und derzeit der Standard. Wie der Name schon sagt, werden alle Objekte im Repository in ein einziges Packfile gepackt. Aus Performance-Sicht ist das großartig für das Repository, da Git nur ein einzelnes Packfile durchsuchen muss, um Objekte nachzuschlagen. Der Hauptnachteil dieser Repacking-Strategie ist, dass die Berechnung eines einzigen Packfiles für ein Repository bei großen Repositories erheblich viel Zeit in Anspruch nehmen kann.\n\nDie Geometric-Strategie hilft, dieses Problem zu entschärfen, indem sie eine geometrische Progression von Packfiles basierend auf ihrer Größe beibehält, anstatt immer in ein einziges Packfile neu zu packen. Also: Beim Repacking pflegt Git eine Reihe von Packfiles, die nach Größe geordnet sind, wobei jedes Packfile in der Sequenz mindestens doppelt so groß sein soll wie das vorhergehende Packfile. Wenn ein Packfile in der Sequenz diese Eigenschaft verletzt, werden Packfiles bei Bedarf kombiniert, bis die Progression wiederhergestellt ist. Diese Strategie hat den Vorteil, dass sie die Anzahl der Packfiles in einem Repository minimiert und gleichzeitig den Arbeitsaufwand für die meisten Repacking-Operationen minimiert.\n\nEin Problem mit der geometrischen Repacking-Strategie war, dass sie nicht mit Partial Clones kompatibel war. Partial Clones ermöglichen es dir, nur Teile eines Repositorys zu klonen, indem du zum Beispiel alle Blobs größer als 1 Megabyte überspringst. Das kann die Größe eines Repositorys erheblich reduzieren, und Git weiß, wie es fehlende Objekte nachträglich abrufen kann, auf die es zu einem späteren Zeitpunkt zugreifen muss.\n\nDas Ergebnis ist ein Repository, dem einige Objekte fehlen, und jedes Objekt, das möglicherweise nicht vollständig verbunden ist, wird in einem „Promisor\"-Packfile gespeichert. Beim Repacking muss diese Promisor-Eigenschaft für Packfiles, die ein Promisor-Objekt enthalten, beibehalten werden, damit bekannt ist, ob ein fehlendes Objekt erwartet wird und vom Promisor Remote nachgeladen werden kann. \n\nBei einem All-into-One-Repack weiß Git, wie es Promisor-Objekte richtig behandelt und speichert sie in einem separaten Promisor-Packfile. Leider wusste die geometrische Repacking-Strategie nicht, Promisor-Packfiles eine Sonderbehandlung zu geben, und würde sie stattdessen mit normalen Packfiles zusammenführen, ohne zu berücksichtigen, ob sie auf Promisor-Objekte verweisen. Glücklicherweise schlägt aufgrund eines Bugs das zugrunde liegende git-pack-objects(1) fehl, wenn geometrisches Repacking in einem Partial-Clone-Repository verwendet wird. Das bedeutet, dass Repositories in dieser Konfiguration sowieso nicht neu gepackt werden konnten, was nicht großartig ist, aber besser als Repository-Korruption.\n\nMit dem Release von Git 2.53 funktioniert geometrisches Repacking jetzt mit Partial-Clone-Repositories. Bei einem geometrischen Repack werden Promisor-Packfiles separat behandelt, um die Promisor-Markierung zu erhalten, und nach einer separaten geometrischen Progression neu gepackt. Mit diesem Fix rückt die geometrische Strategie näher daran, die Standard-Repacking-Strategie zu werden. Für weitere Informationen schau dir den entsprechenden [Mailing-List-Thread](https://lore.kernel.org/git/20260105-pks-geometric-repack-with-promisors-v1-0-c4660573437e@pks.im/) an.\n\nDieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.\n\n## git-fast-import(1) hat gelernt, nur gültige Signaturen zu erhalten\n\nIn unserem [Git 2.52 Release-Artikel](https://about.gitlab.com/de-de/blog/whats-new-in-git-2-52-0/) haben wir signatur-bezogene Verbesserungen an git-fast-import(1) und git-fast-export(1) behandelt. Schau dir diesen Post unbedingt an für eine detailliertere Erklärung dieser Befehle, wie sie verwendet werden und welche Änderungen in Bezug auf Signaturen vorgenommen werden.\n\nUm es kurz zusammenzufassen: git-fast-import(1) bietet ein Backend zum effizienten Importieren von Daten in ein Repository und wird von Tools wie [git-filter-repo(1)](https://github.com/newren/git-filter-repo) verwendet, um die History eines Repositorys in großem Umfang neu zu schreiben. Im Git 2.52 Release hat git-fast-import(1) die Option `--signed-commits=\u003Cmode>` gelernt, ähnlich wie die gleiche Option in git-fast-export(1). Mit dieser Option wurde es möglich, Signaturen von Commits/Tags ohne Bedingung beizubehalten oder zu entfernen.\n\nIn Situationen, in denen nur ein Teil der Repository-History neu geschrieben wurde, wird jede Signatur für neu geschriebene Commits/Tags ungültig. Das bedeutet, dass git-fast-import(1) darauf beschränkt ist, entweder alle Signaturen zu entfernen oder alle Signaturen zu behalten, selbst wenn sie ungültig geworden sind. Aber ungültige Signaturen zu behalten, macht nicht viel Sinn, daher führt das Neuschreiben der History mit git-filter-repo(1) dazu, dass alle Signaturen entfernt werden, selbst wenn der zugrunde liegende Commit/Tag nicht neu geschrieben wurde. Das ist schade, denn wenn der Commit/Tag unverändert ist, ist seine Signatur noch gültig, und es gibt daher keinen wirklichen Grund, sie zu entfernen. Was wirklich benötigt wird, ist eine Möglichkeit, Signaturen für unveränderte Objekte zu erhalten, aber ungültige zu entfernen.\n\nMit dem Release von Git 2.53 hat die Option `--signed-commits=\u003Cmode>` von git-fast-import(1) einen neuen Modus `strip-if-invalid` gelernt, der, wenn angegeben, nur Signaturen von Commits entfernt, die durch das Neuschreiben ungültig werden. Mit dieser Option wird es also möglich, einige Commit-Signaturen bei der Verwendung von git-fast-import(1) zu erhalten. Das ist ein entscheidender Schritt zur Bereitstellung der Grundlage für Tools wie git-filter-repo(1), um gültige Signaturen zu erhalten und schließlich ungültige Signaturen neu zu signieren.\n\nDieses Projekt wurde von [Christian Couder](https://gitlab.com/chriscool) geleitet.\n\n## Mehr Daten in git-repo-structure gesammelt\n\nIm Git 2.52 Release wurde der „structure\"-Subcommand zu git-repo(1) eingeführt. Die Absicht dieses Befehls war es, Informationen über das Repository zu sammeln und schließlich ein nativer Ersatz für Tools wie [git-sizer(1)](https://github.com/github/git-sizer) zu werden. Bei GitLab hosten wir einige extrem große Repositories, und Einblicke in die allgemeine Struktur eines Repositorys sind entscheidend, um seine Performance-Charakteristiken zu verstehen. In diesem Release sammelt der Befehl jetzt auch Informationen zur Gesamtgröße von erreichbaren Objekten in einem Repository, um die Gesamtgröße des Repositorys zu verstehen. In der folgenden Ausgabe kannst du sehen, dass der Befehl jetzt sowohl die gesamten Inflated- als auch Disk-Größen von erreichbaren Objekten nach Objekttyp sammelt.\n\n```shell\n\n$ git repo structure\n\n| Repository structure | Value      |\n| -------------------- | ---------- |\n| * References         |            |\n|   * Count            |   1.78 k   |\n|     * Branches       |      5     |\n|     * Tags           |   1.03 k   |\n|     * Remotes        |    749     |\n|     * Others         |      0     |\n|                      |            |\n| * Reachable objects  |            |\n|   * Count            | 421.37 k   |\n|     * Commits        |  88.03 k   |\n|     * Trees          | 169.95 k   |\n|     * Blobs          | 162.40 k   |\n|     * Tags           |    994     |\n|   * Inflated size    |   7.61 GiB |\n|     * Commits        |  60.95 MiB |\n|     * Trees          |   2.44 GiB |\n|     * Blobs          |   5.11 GiB |\n|     * Tags           | 731.73 KiB |\n|   * Disk size        | 301.50 MiB |\n|     * Commits        |  33.57 MiB |\n|     * Trees          |  77.92 MiB |\n|     * Blobs          | 189.44 MiB |\n|     * Tags           | 578.13 KiB |\n\n```\n\nWer genau hinschaut, dem fällt vielleicht auch auf, dass die Größenwerte in der Tabellenausgabe jetzt auch benutzerfreundlicher mit angehängten Einheiten aufgelistet werden. In zukünftigen Releases hoffen wir, die Ausgabe dieses Befehls weiter zu erweitern, um zusätzliche Datenpunkte bereitzustellen, wie zum Beispiel die größten einzelnen Objekte im Repository.\n\nDieses Projekt wurde von [Justin Tobler](https://gitlab.com/justintobler) geleitet.\n\n## Mehr erfahren\n\nDieser Artikel hat nur einige der Beiträge von GitLab und der breiteren Git-Community für dieses neueste Release hervorgehoben. Du kannst mehr über diese aus der [offiziellen Release-Ankündigung](https://lore.kernel.org/git/xmqq4inz13e3.fsf@gitster.g/T/#u) des Git-Projekts erfahren. Schau dir auch unsere [früheren Git-Release-Blogposts](https://about.gitlab.com/blog/tags/git/) an, um andere vergangene Highlights von Beiträgen der GitLab-Teammitglieder zu sehen.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663087/Blog/Hero%20Images/git3-cover.png",[25,23,262],{"featured":33,"template":13,"slug":697},"whats-new-in-git-2-53-0",{"content":699,"config":708},{"title":700,"description":701,"authors":702,"heroImage":694,"date":705,"body":706,"category":9,"tags":707},"Was ist neu in Git 2.52.0?","Alles zum aktuellen Release, darunter der neue git-last-modified(1)-Befehl, Verbesserungen an History-Rewriting-Tools und eine neue Maintenance-Strategie.",[703,704,18],"Christian Couder","Toon Claes","2025-11-17","Das Git-Projekt hat kürzlich [Git 2.52](https://lore.kernel.org/git/xmqqh5usmvsd.fsf@gitster.g/) veröffentlicht. Nach einem relativ kurzen 8-Wochen-[Release-Zyklus für 2.51](https://about.gitlab.com/de-de/blog/what-s-new-in-git-2-51-0/), aufgrund des Sommers auf der Nordhalbkugel, ist dieses Release wieder beim üblichen 12-Wochen-Zyklus.\n\nSchauen wir uns einige Highlights an, darunter Beiträge vom GitLab Git-Team und der weiteren Git-Community.\n\n## Neuer git-last-modified(1)-Befehl\n\nViele Git-Forges wie GitLab zeigen Dateien in einer Tree-Ansicht wie dieser an:\n\n\n| Name        | Last commit                                             | Last update  |\n| ------------- | --------------------------------------------------------- | -------------- |\n| README.md   | README: *.txt -> *.adoc fixes                           | 4 months ago |\n| RelNotes    | Start 2.51 cycle, the first batch                       | 4 weeks ago  |\n| SECURITY.md | SECURITY: describe how to report vulnerabilities        | 4 years      |\n| abspath.c   | abspath: move related functions to abspath              | 2 years      |\n| abspath.h   | abspath: move related functions to abspath              | 2 years      |\n| aclocal.m4  | configure: use AC_LANG_PROGRAM consistently             | 15 years ago |\n| add-patch.c | pager: stop using `the_repository`                      | 7 months ago |\n| advice.c    | advice: allow disabling default branch name advice      | 4 months ago |\n| advice.h    | advice: allow disabling default branch name advice      | 4 months ago |\n| alias.h     | rebase -m: fix serialization of strategy options        | 2 years      |\n| alloc.h     | git-compat-util: move alloc macros to git-compat-util.h | 2 years ago  |\n| apply.c     | apply: only write intents to add for new files          | 8 days ago   |\n| archive.c   | Merge branch 'ps/parse-options-integers'                | 3 months ago |\n| archive.h   | archive.h: remove unnecessary include                   | 1 year       |\n| attr.h      | fuzz: port fuzz-parse-attr-line from OSS-Fuzz           | 9 months ago |\n| banned.h    | banned.h: mark `strtok()` and `strtok_r()` as banned    | 2 years      |\n\n\n\u003Cbr>\u003C/br>\n\nNeben den Dateien selbst zeigen wir auch an, welcher Commit jede jeweilige Datei zuletzt geändert hat. Diese Information lässt sich einfach aus Git extrahieren, indem du folgenden Befehl ausführst:\n\n```shell\n\n$ git log --max-count=1 HEAD -- \u003Cfilename>\n\n```\n\nObwohl schön und einfach, hat das einen erheblichen Haken: Git hat keine Möglichkeit, diese Information für jede dieser Dateien in einem einzigen Befehl zu extrahieren. Um also den letzten Commit für alle Dateien im Tree zu erhalten, müssten wir diesen Befehl für jede Datei separat ausführen. Das führt zu einer Befehlspipeline ähnlich der folgenden:\n\n```shell\n\n$ git ls-tree HEAD --name-only | xargs --max-args=1 git log --max-count=1 HEAD --\n\n```\n\nNatürlich ist das nicht sehr effizient:\n\n\n* Wir müssen für jede Datei einen neuen Git-Befehl starten.\n\n\n* Git muss die History für jede Datei separat durchlaufen.\n\n\n\nAls Konsequenz ist diese gesamte Operation ziemlich kostspielig und erzeugt erhebliche Last für GitLab.\n\n\n\nUm diese Probleme zu beheben, wurde ein neuer Git-Subcommand `git-last-modified(1)` eingeführt. Dieser Befehl gibt den Commit für jede Datei eines gegebenen Commits zurück:\n\n```shell\n\n$ git last-modified HEAD\n\n\ne56f6dcd7b4c90192018e848d0810f091d092913        add-patch.c\n373ad8917beb99dc643b6e7f5c117a294384a57e        advice.h\ne9330ae4b820147c98e723399e9438c8bee60a80        advice.c\n5e2feb5ca692c5c4d39b11e1ffa056911dd7dfd3        alloc.h\n954d33a9757fcfab723a824116902f1eb16e05f7        RelNotes\n4ce0caa7cc27d50ee1bedf1dff03f13be4c54c1f        apply.c\n5d215a7b3eb0a9a69c0cb9aa43dcae956a0aa03e        archive.c\nc50fbb2dd225e7e82abba4380423ae105089f4d7        README.md\n72686d4e5e9a7236b9716368d86fae5bf1ae6156        attr.h\nc2c4138c07ca4d5ffc41ace0bfda0f189d3e262e        archive.h\n5d1344b4973c8ea4904005f3bb51a47334ebb370        abspath.c\n5d1344b4973c8ea4904005f3bb51a47334ebb370        abspath.h\n60ff56f50372c1498718938ef504e744fe011ffb        banned.h\n4960e5c7bdd399e791353bc6c551f09298746f61        alias.h\n2e99b1e383d2da56c81d7ab7dd849e9dab5b7bf0        SECURITY.md\n1e58dba142c673c59fbb9d10aeecf62217d4fc9c        aclocal.m4\n\n```\n\n\n\nDer Vorteil davon ist offensichtlich, dass wir jetzt nur noch einen einzigen Git-Prozess ausführen müssen, um all diese Informationen abzuleiten. Aber noch wichtiger ist, dass wir die History nur einmal für alle Dateien zusammen durchlaufen müssen, anstatt sie mehrmals durchlaufen zu müssen. Dies wird wie folgt erreicht:\n\n\n1. Beginne damit, die History vom angegebenen Commit aus zu durchlaufen.\n\n\n2. Für jeden Commit:\n\n\n\n   1. Wenn er keinen der Pfade ändert, an denen wir interessiert sind, fahren wir mit dem nächsten Commit fort.\n   2. Wenn er es tut, geben wir die Commit-ID zusammen mit dem Pfad aus. Außerdem entfernen wir den Pfad aus der Menge der interessanten Pfade.\n\n\n\n3. Wenn die Liste der interessanten Pfade leer wird, stoppen wir.\n\n\n\nGitaly wurde bereits angepasst, um den neuen Befehl zu verwenden, aber die Logik ist noch hinter einem Feature-Flag geschützt. Vorläufige Tests haben gezeigt, dass `git-last-modified(1)` in den meisten Situationen mindestens doppelt so schnell ist wie die Verwendung von `git log --max-count=1`.\n\n\n\n*Diese Änderungen wurden [ursprünglich geschrieben](https://github.com/ttaylorr/git/tree/tb/blame-tree) von mehreren Entwicklern von GitHub und wurden [upstream](https://lore.kernel.org/git/20250805093358.1791633-1-toon@iotcl.com/) in Git von [Toon Claes](https://gitlab.com/toon) integriert.*\n\n\n\n## Signatur-bezogene Verbesserungen für git-fast-export(1) und git-fast-import(1)\n\n\n\nDie Befehle `git-fast-export(1)` und `git-fast-import(1)` sind dafür konzipiert, hauptsächlich von Interoperabilitäts- oder History-Rewriting-Tools verwendet zu werden. Das Ziel von Interoperabilitäts-Tools ist es, Git problemlos mit anderer Software interagieren zu lassen, normalerweise einem anderen Versionskontrollsystem, das Daten in einem anderen Format als Git speichert. Zum Beispiel ist [hg-fast-export.sh](https://github.com/frej/fast-export) ein „Mercurial-zu-Git-Konverter, der git-fast-import verwendet.\"\n\n\n\nAlternativ lassen History-Rewriting-Tools Benutzer – normalerweise Admins – Änderungen an der History ihrer Repositories vornehmen, die Versionskontrollsysteme nicht zulassen. Zum Beispiel sagt [reposurgeon](http://www.catb.org/esr/reposurgeon/) in seiner [Einführung](https://gitlab.com/esr/reposurgeon/-/blob/master/repository-editing.adoc?ref_type=heads#introduction), dass sein Zweck ist, „riskante Operationen zu ermöglichen, die Versionskontrollsysteme dich nicht durchführen lassen wollen, wie zum Beispiel (a) Bearbeitung vergangener Kommentare und Metadaten, (b) Entfernung von Commits, (c) Zusammenführung und Aufteilung von Commits, (d) Entfernung von Dateien und Subtrees aus der Repo-History, (e) Zusammenführung oder Verknüpfung von zwei oder mehr Repos und (f) Aufteilung eines Repos in zwei durch Durchtrennung einer Parent-Child-Verbindung, wobei die Branch-Struktur beider Child-Repos erhalten bleibt.\"\n\n\n\nInnerhalb von GitLab verwenden wir [git-filter-repo](https://github.com/newren/git-filter-repo), um Admins einige riskante Operationen an ihren Git-Repositories durchführen zu lassen. Leider haben bis Git 2.50 (veröffentlicht im letzten Juni) sowohl `git-fast-export(1)` als auch `git-fast-import(1)` kryptografische Commit-Signaturen überhaupt nicht behandelt. Obwohl `git-fast-export(1)` also eine Option `--signed-tags=\u003Cmode>` hatte, die es Benutzern ermöglicht zu ändern, wie kryptografische Tag-Signaturen behandelt werden, wurden Commit-Signaturen einfach ignoriert.\n\n\n\nKryptografische Signaturen sind sehr fragil, weil sie auf den exakten Commit- oder Tag-Daten basieren, die signiert wurden. Wenn sich die signierten Daten oder irgendetwas von ihrer vorhergehenden History ändert, wird die kryptografische Signatur ungültig. Dies ist eine fragile, aber notwendige Anforderung, um diese Signaturen nützlich zu machen.\n\n\n\nAber im Kontext des Neuschreibens der History ist das ein Problem:\n\n\n\n* Wir möchten vielleicht kryptografische Signaturen sowohl für Commits als auch für Tags behalten, die nach dem Neuschreiben noch gültig sind (z.B. weil sich die History, die zu ihnen führt, nicht geändert hat).\n\n\n* Wir möchten vielleicht neue kryptografische Signaturen für Commits und Tags erstellen, bei denen die vorherige Signatur ungültig geworden ist.\n\n\n\nWeder `git-fast-import(1)` noch `git-fast-export(1)` erlauben diese Anwendungsfälle jedoch, was einschränkt, was Tools wie [git-filter-repo](https://github.com/newren/git-filter-repo) oder [reposurgeon](http://www.catb.org/esr/reposurgeon/) erreichen können.\n\n\n\nWir haben einige erhebliche Fortschritte gemacht:\n\n\n\n* In Git 2.50 haben wir eine Option `--signed-commits=\u003Cmode>` zu `git-fast-export(1)` hinzugefügt, um Commit-Signaturen zu exportieren, und Unterstützung in `git-fast-import(1)`, um sie zu importieren.\n\n\n* In Git 2.51 haben wir das Format verbessert, das zum Exportieren und Importieren von Commit-Signaturen verwendet wird, und wir haben es für `git-fast-import(1)` möglich gemacht, sowohl eine Signatur zu importieren, die auf der SHA-1-Objekt-ID des Commits gemacht wurde, als auch eine, die auf seiner SHA-256-Objekt-ID gemacht wurde.\n\n\n* In Git 2.52 haben wir die Optionen `--signed-commits=\u003Cmode>` und `--signed-tags=\u003Cmode>` zu `git-fast-import(1)` hinzugefügt, sodass der Benutzer Kontrolle darüber hat, wie signierte Daten zum Zeitpunkt des Imports behandelt werden.\n\n\n\nEs gibt noch mehr zu tun. Wir müssen die Fähigkeit hinzufügen:\n\n\n\n* Nur die Commit-Signaturen beizubehalten, die noch gültig sind, zu `git-fast-import(1)`.\n\n\n* Daten neu zu signieren, bei denen die Signatur ungültig wurde.\n\n\n\nWir arbeiten bereits an diesen nächsten Schritten, und erwarten, dass dies in Git 2.53 landet. Sobald das erledigt ist, werden Tools wie `git-filter-repo(1)` endlich beginnen, kryptografische Signaturen eleganter zu handhaben. Wir werden dich in unserem nächsten Git-Release-Blogpost auf dem Laufenden halten.\n\n\n\n*Dieses Projekt wurde von [Christian Couder](https://gitlab.com/chriscool) geleitet.*\n\n\n\n## Neue und verbesserte git-maintenance(1)-Strategien\n\n\n\nGit-Repositories benötigen regelmäßige Wartung, um sicherzustellen, dass sie gut funktionieren. Diese Wartung führt eine Reihe verschiedener Aufgaben aus: Referenzen werden optimiert, Objekte werden komprimiert und veraltete Daten werden bereinigt.\n\n\n\nBis Git 2.28 wurden diese Wartungsaufgaben von `git-gc(1)` durchgeführt. Das Problem mit diesem Befehl war, dass er nicht mit Blick auf Anpassbarkeit entwickelt wurde: Während bestimmte Parameter konfiguriert werden können, ist es nicht möglich zu kontrollieren, welche Teile eines Repositorys optimiert werden sollen. Das bedeutet, dass es möglicherweise nicht für alle Anwendungsfälle gut geeignet ist. Noch wichtiger ist, dass es sehr schwer wurde, darüber zu iterieren, wie genau Git Repository-Wartung durchführt.\n\n\n\nUm dieses Problem zu beheben und uns wieder iterieren zu lassen, hat [Derrick Stolee](https://github.com/derrickstolee) `git-maintenance(1)` eingeführt. Im Gegensatz zu `git-gc(1)` ist es mit Blick auf Anpassbarkeit entwickelt und ermöglicht es dem Benutzer zu konfigurieren, welche Aufgaben speziell in einem bestimmten Repository ausgeführt werden sollen. Dieses neue Tool wurde in Git 2.29 zum Standard für Gits automatisierte Wartung gemacht, aber standardmäßig verwendet es immer noch `git-gc(1)`, um die Wartung durchzuführen.\n\n\n\nWährend diese Standard-Wartungsstrategie in kleinen oder sogar mittelgroßen Repositories gut funktioniert, ist sie im Kontext großer Monorepos problematisch. Der größte limitierende Faktor ist, wie `git-gc(1)` Objekte neu packt: Immer wenn es mehr als 50 Packfiles gibt, wird das Tool alle zusammen in ein einziges Packfile zusammenführen. Diese Operation ist ziemlich CPU-intensiv und verursacht viele I/O-Operationen, sodass diese Operation für große Monorepos leicht viele Minuten oder sogar Stunden dauern kann.\n\n\n\nGit weiß bereits, wie diese Repacks durch „geometrisches Repacking\" minimiert werden können. Die Idee ist einfach: Die Packfiles, die im Repository existieren, müssen einer geometrischen Progression folgen, bei der jedes Packfile mindestens doppelt so viele Objekte enthalten muss wie das nächstkleinere. Dies ermöglicht es Git, die Anzahl der erforderlichen Repacks zu amortisieren und gleichzeitig sicherzustellen, dass es insgesamt nur eine relativ kleine Anzahl von Packfiles gibt. Dieser Modus wurde von [Taylor Blau](https://github.com/ttaylorr) in Git 2.32 eingeführt, aber er wurde nicht als Teil der automatisierten Wartung eingebunden.\n\n\n\nAlle Teile existieren, um die Repository-Wartung für große Monorepos viel skalierbarer zu machen: Wir haben das flexible `git-maintenance(1)`-Tool, das erweitert werden kann, um eine neue Wartungsstrategie zu haben, und wir haben einen besseren Weg, Objekte neu zu packen. Alles, was getan werden muss, ist, diese beiden zu kombinieren.\n\n\n\nUnd genau das haben wir mit Git 2.52 getan! Wir haben eine neue „geometrische\" Wartungsstrategie eingeführt, die du in deinen Git-Repositories konfigurieren kannst. Diese Strategie ist als vollständiger Ersatz für die alte Strategie basierend auf `git-gc(1)` gedacht. Hier ist der Config-Code, den du benötigst:\n\n\n```shell\n\n$ git config set maintenance.strategy geometric\n\n```\n\n\n\nAb jetzt verwendet Git geometrisches Repacking verwenden, um deine Objekte zu optimieren. Das sollte zu weniger Churn führen und gleichzeitig sicherstellen, dass deine Objekte in einem besser optimierten Zustand sind, besonders in großen Monorepos.\n\n\n\nIn Git 2.53 wollen wir dies zur Standard-Strategie machen. Also bleib dran!\n\n\n\n*Dieses Projekt wurde von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) geleitet.*\n\n\n\n## Neuer Subcommand für git-repo(1) zur Anzeige von Repository-Metriken\n\n\n\nDie Performance von Git-Operationen in einem Repository hängt oft von bestimmten Eigenschaften seiner zugrunde liegenden Struktur ab. Bei GitLab hosten wir einige extrem große Repositories, und Einblicke in die allgemeine Struktur eines Repositorys sind entscheidend, um die Performance zu verstehen. Während es möglich ist, verschiedene Git-Befehle und andere Tools zusammenzusetzen, um bestimmte Repository-Metriken zu ermitteln, fehlt Git eine Möglichkeit, Informationen über die Form/Struktur eines Repositorys über einen einzigen Befehl zu liefern. Dies hat zur Entwicklung anderer externer Tools geführt, wie [git-sizer(1)](https://github.com/github/git-sizer), um diese Lücke zu füllen.\n\n\n\nMit dem Release von Git 2.52 wurde ein neuer „structure\"-Subcommand zu git-repo(1) hinzugefügt mit dem Ziel, Informationen über die Struktur eines Repositorys zu liefern. Derzeit zeigt er Informationen über die Anzahl der Referenzen und Objekte im Repository in der folgenden Form an:\n\n```shell\n\n$ git repo structure\n\n\n| Repository structure | Value  |\n| -------------------- | ------ |\n| * References         |        |\n|   * Count            |   1772 |\n|     * Branches       |      3 |\n|     * Tags           |   1025 |\n|     * Remotes        |    744 |\n|     * Others         |      0 |\n|                      |        |\n| * Reachable objects  |        |\n|   * Count            | 418958 |\n|     * Commits        |  87468 |\n|     * Trees          | 168866 |\n|     * Blobs          | 161632 |\n|     * Tags           |    992 |\n\n```\n\n\n\nIn zukünftigen Releases hoffen wir, dies zu erweitern und andere interessante Datenpunkte bereitzustellen, wie die größten Objekte im Repository.\n\n\n\n*Dieses Projekt wurde von [Justin Tobler](https://gitlab.com/justintobler) geleitet.*\n\n\n\n## Verbesserungen im Zusammenhang mit dem Google Summer of Code 2025\n\n\n\nWir hatten drei erfolgreiche Projekte mit dem Google Summer of Code.\n\n\n\n### Refactoring zur Reduzierung von Gits globalem Status\n\n\n\nGit enthält mehrere globale Variablen, die in der gesamten Codebasis verwendet werden. Dies erhöht die Komplexität des Codes und verringert die Wartbarkeit. Als Teil dieses Projekts hat [Ayush Chandekar](https://ayu-ch.github.io/) daran gearbeitet, die Verwendung der globalen Variable `the_repository` durch eine Reihe von Patches zu reduzieren.\n\n\n\n*Das Projekt wurde betreut von [Christian Couder](https://gitlab.com/chriscool) und [Ghanshyam Thakkar](https://in.linkedin.com/in/ghanshyam-thakkar).*\n\n\n\n### Maschinenlesbares Repository-Informations-Abfrage-Tool\n\n\n\nGit fehlt ein zentraler Weg, um Repository-Informationen abzurufen, was Benutzer zwingt, sie aus verschiedenen Befehlen zusammenzusetzen. Während `git-rev-parse(1)` zum De-facto-Tool für den Zugriff auf viele dieser Informationen geworden ist, liegt dies außerhalb seines Hauptzwecks.\n\n\n\nAls Teil dieses Projekts hat [Lucas Oshiro](https://lucasoshiro.github.io/en/) einen neuen Befehl eingeführt, `git-repo(1)`, der alle Repository-Level-Informationen beherbergen wird. Benutzer können jetzt `git repo info` verwenden, um Repository-Informationen zu erhalten:\n\n```shell\n\n$ git repo info layout.bare layout.shallow object.format references.format\n\nlayout.bare=false\nlayout.shallow=false\nobject.format=sha1\nreferences.format=reftable\n\n```\n\n\n\n*Das Projekt wurde betreut von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) und [Karthik Nayak](https://gitlab.com/knayakgl).*\n\n\n\n### Konsolidierung ref-bezogener Funktionalität in git-refs\n\n\n\nGit bietet mehrere Befehle zur Verwaltung von Referenzen, nämlich `git-for-each-ref(1)`, `git show-ref(1)`, `git-update-ref(1)` und `git-pack-refs(1)`. Das macht sie schwerer zu entdecken und erzeugt sich überschneidende Funktionalität. Um dies anzugehen, haben wir den Befehl `git-refs(1)` eingeführt, um diese Operationen unter einer einzigen Schnittstelle zu konsolidieren. Als Teil dieses Projekts hat [Meet Soni](https://inosmeet.github.io/) den Befehl durch Hinzufügen der folgenden Subcommands erweitert:\n\n\n\n* `git refs optimize` zur Optimierung des Reference-Backends\n\n\n* `git refs list` zum Auflisten aller Referenzen\n\n\n* `git refs exists` zur Überprüfung der Existenz einer Referenz\n\n\n\n*Das Projekt wurde betreut von [Patrick Steinhardt](https://gitlab.com/pks-gitlab) und [shejialuo](https://luolibrary.com/).*\n\n\n\n## Was kommt als Nächstes?\n\n\n\nBereit, diese Verbesserungen zu erleben? Aktualisiere auf Git 2.52.0 und fang an, `git last-modified` zu verwenden.\n\n\n\nBei GitLab werden wir natürlich sicherstellen, dass all diese Verbesserungen schließlich in einer GitLab-Instanz in deiner Nähe landen!\n\n\n\nErfahre mehr in den [offiziellen Git 2.52.0 Release Notes](https://lore.kernel.org/git/xmqqh5usmvsd.fsf@gitster.g/) und erkunde unser [vollständiges Archiv der Git-Entwicklungs-Berichterstattung](https://about.gitlab.com/blog/tags/git/).",[25,23,262],{"featured":33,"template":13,"slug":709},"whats-new-in-git-2-52-0",{"promotions":711},[712,726,739],{"id":713,"categories":714,"header":716,"text":717,"button":718,"image":723},"ai-modernization",[715],"ai-ml","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":719,"config":720},"Get your AI maturity score",{"href":721,"dataGaName":722,"dataGaLocation":244},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":724},{"src":725},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":727,"categories":728,"header":731,"text":717,"button":732,"image":736},"devops-modernization",[729,730],"product","devsecops","Are you just managing tools or shipping innovation?",{"text":733,"config":734},"Get your DevOps maturity score",{"href":735,"dataGaName":722,"dataGaLocation":244},"/assessments/devops-modernization-assessment/",{"config":737},{"src":738},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":740,"categories":741,"header":743,"text":717,"button":744,"image":748},"security-modernization",[742],"security","Are you trading speed for security?",{"text":745,"config":746},"Get your security maturity score",{"href":747,"dataGaName":722,"dataGaLocation":244},"/assessments/security-modernization-assessment/",{"config":749},{"src":750},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"header":752,"blurb":753,"button":754,"secondaryButton":759},"Beginne noch heute, schneller zu entwickeln","Entdecke, was dein Team mit der intelligenten Orchestrierungsplattform für DevSecOps erreichen kann.\n",{"text":755,"config":756},"Kostenlosen Test starten",{"href":757,"dataGaName":50,"dataGaLocation":758},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":52,"config":760},{"href":54,"dataGaName":55,"dataGaLocation":758},1772652052157]