Close

Git prune

Der Befehl git prune ist ein internes Housekeeping-Dienstprogramm, das unerreichbare oder "verwaiste" Git-Objekte aufräumt. Unerreichbare Objekte sind solche, auf die keine Refs zugreifen können. Jeder Commit, auf den nicht über einen Branch oder ein Tag zugegriffen werden kann, wird als nicht erreichbar betrachtet. git prune wird im Allgemeinen nicht direkt ausgeführt. Prune wird als Befehl zur Speicherbereinigung betrachtet und ist ein untergeordneter Befehl des Befehls git gc.


git prune im Überblick


Um die Auswirkungen von git prune zu verstehen, müssen wir ein Szenario simulieren, in dem ein Commit nicht mehr erreichbar ist. Im Folgenden findest du eine Abfolge von Befehlszeilenausführungen, die diese Erfahrung simulieren.

~ $ cd git-prune-demo/
~/git-prune-demo $ git init .
Initialized empty Git repository in /Users/kev/Dropbox/git-prune-demo/.git/
~/git-prune-demo $ echo "hello git prune" > hello.txt
~/git-prune-demo $ git add hello.txt
~/git-prune-demo $ git commit -am "added hello.txt"

Die vorhergehende Befehlssequenz erstellt ein neues Repository in einem Verzeichnis namens git-prune-demo. Ein Commit, der aus einer neuen Datei hello.text besteht, wird dem Repository mit dem Grundinhalt von "hello git prune" hinzugefügt. Als Nächstes modifizieren wir hello.txt und erstellen aus diesen Änderungen einen neuen Commit.

~/git-prune-demo $ echo "this is second line txt" >> hello.txt
~/git-prune-demo $ cat hello.txt
hello git prune
this is second line txt
~/git-prune-demo $ git commit -am "added another line to hello.txt"
[main 5178bec] added another line to hello.txt
1 file changed, 1 insertion(+)
Datenbanken
Zugehöriges Material

Verschieben eines vollständigen Git-Repositorys

Bitbucket-Logo
Lösung anzeigen

Git kennenlernen mit Bitbucket Cloud

Wir haben in diesem Demo-Repository jetzt einen Verlauf mit zwei Commits. Wir können dies überprüfen, indem wir git log verwenden:

~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

        added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

In der git log-Ausgabe werden die zwei Commits und die entsprechenden Commit-Meldungen über die an hello.txt vorgenommenen Änderungen angezeigt. Als Nächstes machen wir einen der Commits unerreichbar. Hierfür verwenden wir den Befehl git reset. Wir setzen den Status des Repositorys auf den ersten Commit ("added hello.txt") zurück.

~/git-prune-demo $ git reset --hard 994b122045cf4bf0b97139231b4dd52ea2643c7e
HEAD is now at 994b122 added hello.txt

Wenn wir jetzt mit git log den Status des Repositorys untersuchen, sehen wir nur einen Commit.

~/git-prune-demo $ git log
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

Das Demo-Repository befindet sich jetzt in einem Zustand, der einen losgelösten Commit enthält. Der zweite Commit, den wir mit der Nachricht "added another line to hello.txt" erstellt haben, wird nicht mehr in der git log-Ausgabe angezeigt und ist jetzt losgelöst. Es mag den Anschein haben, als hätten wir den Commit verloren oder gelöscht, aber Git achtet sehr darauf, den Verlauf nicht zu löschen. Wir können bestätigen, dass er noch verfügbar, aber losgelöst ist, indem wir git checkout verwenden, um ihn direkt aufzurufen:

~/git-prune-demo $ git checkout 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Note: checking out '5178becc2ca965e1728554ce1cb8de2f2c2370b1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

      git checkout -b <new-branch-name>

HEAD is now at 5178bec... added another line to hello.txt
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

      added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

      added hello.txt

Wenn wir uns den losgelösten Commit ansehen, zeigt Git eine detaillierte Meldung an, dass wir uns in einem losgelösten Zustand befinden. Im Protokoll sehen wir, dass der Commit "added another line to hello.txt" jetzt wieder in der Protokollausgabe steht. Nachdem wir jetzt wissen, dass sich das Repository mit einem losgelösten Commit in einem guten Simulationszustand befindet, können wir die Verwendung von git prune üben. Kehren wir jedoch zunächst mit git checkout zurück zum main-Branch.

~/git-prune-demo $ git checkout main
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

      5178bec added another line to hello.txt

If you want to keep it by creating a new branch, this may be a good time
to do so with:

     git branch <new-branch-name> 5178bec

Switched to branch 'main'

Bei der Rückkehr zum Main-Branch mit git checkout teilt uns Git wieder mit, dass wir einen losgelösten Commit verlassen. Jetzt ist es an der Zeit, den losgelösten Commit mit "prune" zu löschen. Als Nächstes führen wir git prune aus, aber wir müssen unbedingt einige Optionen hinzufügen. Mit --dry-runn und --verbose wird in der Ausgabe angegeben, was mit "prune" gelöscht werden soll, ohne dies tatsächlich zu tun.

~/git-prune-demo $ git prune --dry-run --verbose

Dieser Befehl wird höchstwahrscheinlich eine leere Ausgabe zurückgeben. Eine leere Ausgabe bedeutet, dass der Prune-Befehl nichts wirklich löscht. Warum geschieht dies? Nun, der Commit ist höchstwahrscheinlich nicht vollständig losgelöst. Irgendwo bewahrt Git immer noch einen Verweis darauf. Dies ist ein Paradebeispiel dafür, warum git prune nicht eigenständig außerhalb von git gc verwendet werden darf. Dies ist auch ein gutes Beispiel dafür, wie schwierig es ist, Daten in Git vollständig zu verlieren.

Höchstwahrscheinlich speichert Git einen Verweis auf unseren losgelösten Commit im Reflog. Dies können wir untersuchen, indem wir git reflog ausführen. Hiermit wird eine Ausgabe mit der Reihenfolge der Aktionen zurückgegeben, die wir durchgeführt haben, um hierher zu gelangen. Weitere Informationen zu git reflog findest du auf der git reflog-Seite. Zusätzlich zum Bewahren des Verlaufs im Reflog verfügt Git über interne Ablaufdaten, an denen losgelöste Commits mit "prune" gelöscht werden. Nochmals: Dies sind alles Implementierungsdetails, die git gc handhabt und weswegen git prune nicht eigenständig verwendet werden sollte.

Um unsere Demo zur git prune-Simulation abzuschließen, müssen wir den Reflog löschen.

~/git-prune-demo $ git reflog expire --expire=now --expire-unreachable=now --all

Der obige Befehl erzwingt das Ablaufen aller Einträge im Reflog, die älter als jetzt sind. Dies ist ein schonungsloser und gefährlicher Befehl, den du als Gelegenheitsbenutzer von Git niemals verwenden solltest. Wir führen diesen Befehl aus, um eine erfolgreiche Ausführung von git prune zu demonstrieren. Da der Reflog vollständig gelöscht ist, können wir jetzt git prune ausführen.

~/git-prune-demo $ git prune --dry-run --verbose --expire=now
1782293bdfac16b5408420c5cb0c9a22ddbdd985 blob
5178becc2ca965e1728554ce1cb8de2f2c2370b1 commit
a1b3b83440d2aa956ad6482535cbd121510a3280 commit
f91c3433eae245767b9cd5bdb46cd127ed38df26 tree

Dieser Befehl sollte eine Liste von Git SHA-Objektreferenzen ausgeben, die wie oben abgebildet aussehen.

Anwendung von "git rebase"


git prune hat eine kurze Liste von Optionen, die wir im Übersichtsbereich behandelt haben.

-n --dry-run

Der Prune-Befehl wird nicht ausgeführt. Es wird nur angezeigt, was bei der Ausführung des Befehls geschehen würde.

-v --verbose

Die Ausgabe zeigt alle Objekte und Aktionen an, die vom Prune-Befehl ausgeführt wurden.

--progress

Die Ausgabe zeigt den Fortschritt des Prune-Befehls an.

--expire <time>

Erzwingt das Ablaufen von Objekten, deren Fälligkeitsdatum erreicht wurde.

<head>…

Durch die Angabe eines <head> werden alle Optionen aus dieser HEAD-Ref beibehalten.

Diskussion


Wie unterscheiden sich Git Prune, Git Fetch --prune und Git Remote Prune?

git remote prune und git fetch --prune machen dasselbe: Sie löschen die Referenzen in Branches, die im Remote nicht existieren. Dies ist sehr wünschenswert, wenn du in einem Team-Workflow arbeitest, in dem Remote-Branches nach dem Merge mit main gelöscht werden. Der zweite Befehl, git fetch --prune, stellt eine Verbindung zum Remote her und ruft vor dem Pruning den neuesten Remote-Status ab. Im Wesentlichen ist dies eine Kombination von Befehlen:

git fetch --all && git remote prune

Der generische Befehl git prune ist völlig anders. Wie im Übersichtsabschnitt erläutert, löscht Git Prune lokal losgelöste Commits.

Wie bereinige ich veraltete Branches?

git fetch --prune ist das beste Dienstprogramm zum Bereinigen veralteter Branches. Es stellt eine Verbindung zu einem gemeinsamen Remote-Repository her und ruft alle Remote-Branch-Refs ab. Anschließend werden Remote-Refs gelöscht, die nicht mehr im Remote-Repository verwendet werden.

Löscht Git Remote Prune Origin den lokalen Branch?

Nein. git remote prune origin löscht nur die Referenzen auf Remote-Branches, die nicht mehr existieren. Git speichert sowohl lokale als auch Remote-Referenzen. Ein Repository verfügt über die Referenzsammlungen local/origin und remote/origin. git remote prune origin entfernt nur die Refs in remote/origin. Dadurch ist die lokale Arbeit in local/origin in Sicherheit.

Git Prune zusammengefasst


Der Befehl git prune soll als untergeordneter Befehl für git gc aufgerufen werden. Es ist höchst unwahrscheinlich, dass du als Softwareentwickler git prune jemals im Alltag aufrufen musst. Um die Auswirkungen von git prune zu verstehen, sind weitere Befehle erforderlich. Einige in diesem Artikel verwendete Befehle waren git log, git reflog und git checkout.


Diesen Artikel teilen
Nächstes Thema

Lesenswert

Füge diese Ressourcen deinen Lesezeichen hinzu, um mehr über DevOps-Teams und fortlaufende Updates zu DevOps bei Atlassian zu erfahren.

Mitarbeiter arbeiten mit unzähligen Tools zusammen

Bitbucket-Blog

Abbildung: DevOps

DevOps-Lernpfad

Demo Den: Feature-Demos mit Atlassian-Experten

So funktioniert Bitbucket Cloud mit Atlassian Open DevOps

Melde dich für unseren DevOps-Newsletter an

Thank you for signing up