469 Stimmen

Was sind die Unterschiede zwischen git remote prune, git prune, git fetch --prune usw.?

Meine Situation ist folgende... jemand, der am selben Repository arbeitet, hat einen Branch aus seinem lokalen und Remote-Repository gelöscht...

Die meisten Menschen, die dieses Problem auf Stack Overflow oder anderen Websites gefragt haben, haben das Problem, dass die Branches immer noch in ihrer Liste der Remote-Tracking-Branches git branch -a unten angezeigt werden:

* master
  develop
  feature_blah
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah
  remotes/origin/random_branch_I_want_deleted

In MEINER Situation ist der Branch, der nicht da sein sollte, lokal:

* master
  develop
  feature_blah
  random_branch_I_want_deleted
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah

Wenn ich eines der folgenden mache, wird es nicht lokal entfernt:

$ git prune

Ich habe auch versucht:

$ git remote prune origin
$ git fetch --prune

Weitere nützliche Informationen: Wenn ich git remote show origin überprüfe, sieht es so aus:

* remote origin
Fetch URL: utilities:homeconnections_ui.git
Push  URL: utilities:homeconnections_ui.git
HEAD branch: master
Remote branches:
 master                        tracked
 develop                       tracked
 feature_blah                  tracked
 other123                      tracked
 other444                      tracked
 other999                      tracked
Local branches configured for 'git pull':
 develop                      merges with remote develop
 feature_blah                 merges with remote other999
 master                       merges with remote master
 random_branch_I_want_deleted merges with remote random_branch_I_want_deleted
Local refs configured for 'git push':
 develop         pushes to develop     (local out of date)
 master          pushes to master      (up to date)
 feature_blah    pushes to feature_blah(up to date)

Beachten Sie, dass dies nur im Abschnitt mit dem Titel Lokale Branches konfiguriert für 'git pull': der Fall ist.

Warum?

873voto

John Szakmeister Punkte 42207

Ich kann verstehen, dass du darüber frustriert bist. Der beste Weg, darauf zu schauen, ist folgender: Es gibt potenziell drei Versionen von jedem Remote-Zweig:

  1. Der tatsächliche Zweig im Remote-Repository
    (z. B., Remote-Repository unter https://example.com/repo.git, refs/heads/master)
  2. Dein lokaler Schnappschuss dieses Zweigs (gespeichert unter refs/remotes/...)
    (z. B., lokales Repository, refs/remotes/origin/master)
  3. Und ein lokaler Zweig, der möglicherweise den Remote-Zweig verfolgt
    (z. B., lokales Repository, refs/heads/master)

Beginnen wir mit git prune. Dies entfernt Objekte, auf die nicht mehr verwiesen wird, es entfernt keine Referenzen. In deinem Fall hast du einen lokalen Zweig. Das bedeutet, dass es eine Referenz namens random_branch_I_want_deleted gibt, die auf einige Objekte verweist, die die Historie dieses Zweigs darstellen. Also wird git prune random_branch_I_want_deleted nicht entfernen. Tatsächlich ist git prune ein Weg, um Daten zu löschen, die sich in Git angesammelt haben, aber von nichts referenziert werden. Im Allgemeinen beeinflusst es nicht deine Ansicht von irgendwelchen Zweigen.

git remote prune origin und git fetch --prune operieren beide auf Referenzen unter refs/remotes/... (ich werde diese als Remote-Referenzen bezeichnen). Das betrifft nicht lokale Zweige. Die Version von git remote ist nützlich, wenn du nur Remote-Referenzen unter einem bestimmten Remote entfernen möchtest. Ansonsten tun beide genau dasselbe. Also, kurz gesagt, git remote prune und git fetch --prune operieren auf Nummer 2 oben. Zum Beispiel, wenn du einen Zweig über die Git-Web-GUI gelöscht hast und nicht möchtest, dass er in deiner Liste lokaler Zweige erscheint (git branch -r), dann ist das der Befehl, den du verwenden solltest.

Um einen lokalen Zweig zu entfernen, solltest du git branch -d verwenden (oder -D, wenn er nirgendwo zusammengeführt wurde). Übrigens gibt es keinen Git-Befehl, um automatisch die lokalen Tracking-Zweige zu entfernen, wenn ein Remote-Zweig verschwindet.

80voto

CharlesB Punkte 80104

git remote prune und git fetch --prune tun dasselbe: Löschen der Verweise auf die Branches, die auf dem Remote nicht existieren, wie du gesagt hast. Der zweite Befehl verbindet sich mit dem Remote und holt seine aktuellen Branches, bevor er abschneidet.

Allerdings berührt es nicht die lokalen Branches, die du ausgecheckt hast, die du einfach löschen kannst mit

git branch -d  random_branch_I_want_deleted

Ersetze -d durch -D, wenn der Branch anderswo nicht gemerged ist

git prune macht etwas anderes, es bereinigt unerreichbare Objekte, diese Commits, die in keinem Branch oder Tag erreichbar sind und somit nicht mehr benötigt werden.

17voto

Pomme.Verte Punkte 1732

Falls jemand interessiert ist, hier ist ein schnelles Shell-Skript, das alle lokalen Branches entfernt, die nicht fernverfolgt werden. Ein Wort der Warnung: Dies wird sich aller Branches entledigen, die nicht fernverfolgt werden, unabhängig davon, ob sie gemergt wurden oder nicht.

Wenn ihr irgendwelche Probleme seht, lasst es mich bitte wissen und ich werde es beheben (usw. usw.)

Speichert es in einer Datei namens git-rm-ntb (nennt es wie ihr wollt) auf PATH und führt aus:

git-rm-ntb ...

clean()
{
  REMOTES="$@";
  if [ -z "$REMOTES" ]; then
    REMOTES=$(git remote);
  fi
  REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
  RBRANCHES=()
  while read REMOTE; do
    CURRBRANCHES=($(git ls-remote $REMOTE | awk '{print $2}' | grep 'refs/heads/' | sed 's:refs/heads/::'))
    RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
  done < <(echo "$REMOTES" )
  [[ $RBRANCHES ]] || exit
  LBRANCHES=($(git branch | sed 's:\*::' | awk '{print $1}'))
  for i in "${LBRANCHES[@]}"; do
    skip=
    for j in "${RBRANCHES[@]}"; do
      [[ $i == $j ]] && { skip=1; echo -e "\033[32m Behalte $i \033[0m"; break; }
    done
    [[ -n $skip ]] || { echo -e "\033[31m $(git branch -D $i) \033[0m"; }
  done
}

clean $@

15voto

VonC Punkte 1117238

Bitte beachten Sie, dass ein Unterschied zwischen git remote --prune und git fetch --prune behoben wird, mit Commit 10a6cc8, von Tom Miller (tmiller) (für git 1.9/2.0, Q1 2014):

Wenn wir bereits einen Remote-Tracking-Zweig namens "frotz/nitfol" von einem vorherigen Abruf haben, und der Upstream jetzt einen Zweig namens "frotz" hat, würde fetch mit "git fetch --prune" vom Upstream "frotz/nitfol" nicht entfernen.
git würde den Benutzer informieren, "git remote prune" zu verwenden, um das Problem zu beheben.

Also: wenn ein Upstream-Repo einen Zweig ("frotz") mit demselben Namen wie eine Zweighierarchie ("frotz/xxx", eine mögliche Zweigbenennungskonvention), hatte git remote --prune Erfolg (beim Bereinigen des Remote-Tracking-Zweigs von Ihrem Repo), aber git fetch --prune scheiterte.

Nicht mehr:

Ändern Sie die Art und Weise, wie "fetch --prune" funktioniert, indem Sie die Bereinigungsoperation vor die Abrufoperation verschieben.
Auf diese Weise wird anstelle einer Benachrichtigung des Benutzers über einen Konflikt, dieser automatisch behoben.


Ein weiterer Unterschied:

Mit Git 2.39 (Q4 2022) könnte "git prune"(man) versuchen, über .git/objects/pack nach Mülldateien zu entfernen, und laut scheitern, wenn das Verzeichnis fehlt, was nicht notwendig ist.
Dem Befehl wurde beigebracht, ein solches Scheitern zu ignorieren.

... während git fetch --prune immer noch laut scheitern würde, wenn das Verzeichnis fehlt

Siehe Commit 6974765 (19 Nov 2022) von Eric Wong (ele828).
(Von Junio C Hamano -- gitster -- zusammengeführt in Commit 7d7ed48, 28 Nov 2022)

prune: kein ENOENT auf fehlende Verzeichnisse

Von Eric Wong unterzeichnet

$GIT_DIR/objects/pack könnte entfernt werden, um Inodes in gemeinsamen Repositories zu speichern.
Reduzieren Sie die Ausgabe von prune in Fällen, in denen entweder $GIT_DIR/objects oder $GIT_DIR/objects/pack nicht vorhanden sind, geben Sie aber den Systemfehler in anderen Fällen aus, um Benutzern zu helfen, Berechtigungsprobleme oder Ressourcenbeschränkungen zu diagnostizieren.

Also keine "Verzeichnis kann nicht geöffnet werden ..." für git prune, wenn $GIT_DIR/objects oder $GIT_DIR/objects/pack fehlt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X