585 Stimmen

Kann "git pull --all" alle meine lokalen Zweige aktualisieren?

Ich habe oft mindestens 3 Remote-Zweige: Master, Staging und Production. Ich habe 3 lokale Zweige, die diese entfernten Zweige verfolgen.

Die Aktualisierung aller meiner lokalen Zweigstellen ist mühsam:

git fetch --all
git rebase origin/master
git checkout staging
git rebase origin/staging
git checkout production
git rebase origin/production

Ich würde gerne einfach ein "git pull -all" machen, aber ich habe es nicht zum Laufen gebracht. Es scheint ein "fetch --all" zu machen, dann aktualisiert es den aktuellen Arbeitszweig (vorspulen oder zusammenführen), aber nicht die anderen lokalen Zweige.

Ich muss immer noch manuell zu jedem lokalen Zweig wechseln und ihn aktualisieren.

9 Stimmen

Möchten Sie die automatische Aktualisierung der lokalen Verfolgungszweige nur im Schnelldurchlauf? Das sollten Sie, denn bei der Zusammenführung können Konflikte auftreten, die Sie lösen müssen...

45 Stimmen

Geht man von einem konservativen Betrag von 300 Dollar für die Beratungszeit aus, um damit herumzuspielen, so hat diese eine Ausgabe die Unternehmen 23.242.800 Dollar gekostet, wenn man von 77.476 Besuchern ausgeht. Betrachten Sie nun diese Frage stackoverflow.com/questions/179123/ und all die anderen. Wow.

0 Stimmen

Auch hier gibt es eine gute Antwort stackoverflow.com/a/10312587/1254718

19voto

quornian Punkte 8508

Es gibt hier viele Antworten, aber keine, die die git-fetch um die lokale Referenz direkt zu aktualisieren, was viel einfacher ist als das Auschecken von Zweigen und sicherer als git-update-ref .

Hier verwenden wir git-fetch zur Aktualisierung nicht aktueller Zweige und git pull --ff-only für den aktuellen Zweig. Es:

  • Erfordert keine Überprüfung von Filialen
  • Aktualisiert Zweige nur, wenn sie vorgespult werden können
  • Wird sich melden, wenn der Schnellvorlauf nicht funktioniert

und hier ist sie:

#!/bin/bash
currentbranchref="$(git symbolic-ref HEAD 2>&-)"
git branch -r | grep -v ' -> ' | while read remotebranch
do
    # Split <remote>/<branch> into remote and branchref parts
    remote="${remotebranch%%/*}"
    branchref="refs/heads/${remotebranch#*/}"

    if [ "$branchref" == "$currentbranchref" ]
    then
        echo "Updating current branch $branchref from $remote..."
        git pull --ff-only
    else
        echo "Updating non-current ref $branchref from $remote..."
        git fetch "$remote" "$branchref:$branchref"
    fi
done

Aus der Manpage für git-fetch :

   <refspec>
       The format of a <refspec> parameter is an optional plus +, followed by the source ref <src>,
       followed by a colon :, followed by the destination ref <dst>.

       The remote ref that matches <src> is fetched, and if <dst> is not empty string, the local ref
       that matches it is fast-forwarded using <src>. If the optional plus + is used, the local ref is
       updated even if it does not result in a fast-forward update.

Durch die Angabe von git fetch <remote> <ref>:<ref> (ohne jegliche + ) erhalten wir einen Fetch, der den lokalen Ref nur dann aktualisiert, wenn er vorgespult werden kann.

Nota : Dies setzt voraus, dass der lokale und der entfernte Zweig denselben Namen haben (und dass Sie alle Zweige verfolgen wollen), aber eigentlich sollte es Informationen darüber verwenden, welche lokalen Zweige Sie haben und was sie verfolgen sollen.

1 Stimmen

"Aktualisierte Zweige nur, wenn sie vorgespult werden können" - Welche Bedeutung hat der Schnellvorlauf? Wenn ich die neuesten Quellen in allen meinen Filialen haben möchte, warum sollte ich mich dann für einen schnellen Vorlauf interessieren? Es sind Dinge wie diese, die mich über Git und seine Fanboi's lachen lassen. Man kann das nicht mit einem einzigen Befehl machen. Stattdessen müssen Sie Folgendes ausführen *_`cn_** Schritte (statt 1), wobeiceine bestimmte Anzahl von wiederholten Befehlen ist undn` ist die Anzahl der Verzweigungen.

0 Stimmen

@jww Es hilft nicht, "über Git und seine Fanboi's zu lachen" [sic], wenn es das VCS ist, das der Großteil der Welt benutzt. Aber ich schweife ab... Ich denke, dass es im Zusammenhang mit dieser Art von "global pull" Skript klug ist, nicht zu versuchen, Änderungen an nicht-aktuellen Zweigen vorzunehmen, wenn sie Merge-Konflikte haben.

1 Stimmen

Das war sehr hilfreich, vielen Dank. Das Einzige, was mir nicht gefiel, war, dass für jeden entfernten Zweig (einschließlich derer, an denen ich nicht interessiert bin) ein lokaler Zweig erstellt wurde, also habe ich git branch -r | grep -v ' -> ' | while read remotebranch a git branch -r | grep -v ' -> ' | grep -f <(git branch | cut -c 3- | awk '{print "\\S*/"$0"$"}') | while read remotebranch um sie auf Zweige zu beschränken, die ich bereits lokal habe. Außerdem habe ich eine git fetch --prune am Anfang, um die Liste der entfernten Zweige zu aktualisieren, bevor Sie etwas tun, was einige Warnungen vermeidet.

14voto

Jakub Narębski Punkte 286531

Dieses Problem ist (noch) nicht gelöst, zumindest nicht einfach / ohne Skripting: siehe diese Stelle auf der Git-Mailingliste von Junio C Hamano, der die Situation erklärt und eine einfache Lösung vorschlägt.

Das Hauptargument ist, dass Sie das nicht brauchen sollten:

Mit Git, das nicht uralt ist (d.h. v1.5.0 oder neuer), gibt es keinen Grund für einen lokalen "dev" zu haben, der lediglich die entfernte Version verfolgt. Wenn Sie nur sehen wollen, können Sie den entfernten Tracking-Zweig direkt auschecken auf einem abgetrennten HEAD mit " git checkout origin/dev ".

Das bedeutet, dass die einzigen Fälle, in denen wir es für die Benutzer bequem machen müssen lokale Zweige zu handhaben, die entfernte Zweige "verfolgen", wenn Sie lokale Änderungen haben, oder wenn Sie planen, welche zu haben.

Wenn Sie lokale Änderungen auf "dev" haben, die so markiert sind, dass sie das Entfernen von "dev" zu verfolgen, und wenn Sie sich auf einem anderen Zweig als "dev" befinden, dann sollten wir nicht nach "" nichts tun. git fetch " aktualisiert die Fernverfolgung "dev". Es wird sowieso nicht vorgespult

Die Forderung nach einer Lösung war eine Option oder ein externes Skript, um Pflaume lokale Zweige, die jetzt auf die ferngesteuerten Zweige folgen, anstatt sie durch schnelles Vorspulen auf dem neuesten Stand zu halten, wie es der ursprüngliche Poster gefordert hatte.

Wie wäre es also mit " git branch --prune --remote=<upstream> ", die über lokale Zweige durchläuft, und wenn

(1) es ist nicht der aktuelle Zweig; und
(2) es ist markiert, um einen Zweig aus dem <upstream> zu verfolgen; und
(3) es hat keine eigenen Commits;

dann diesen Zweig entfernen? " git remote --prune-local-forks <upstream> " ist auch in Ordnung; es ist mir egal, welcher Befehl die Funktion implementiert viel.

Nota: Seit Git 2.10 gibt es keine solche Lösung mehr. Beachten Sie, dass die git remote prune und den Unterbefehl git fetch --prune geht es darum, den Zweig zu entfernen, der auf dem entfernten Rechner nicht mehr existiert, und nicht darum, den lokalen Zweig zu entfernen, der dem entfernten Zweig folgt (für den der entfernte Zweig der Upstream-Zweig ist).

0 Stimmen

Anstatt nur Links zu posten, bitte aktuelle Inhalte veröffentlichen, indem Sie

0 Stimmen

@michael_n: erweitert... hmm, jetzt sehe ich, dass es in dem Beitrag nicht genau um die gewünschte Lösung ging, sondern um das Problem (unter der Annahme eines XY-Problemfalls).

0 Stimmen

Hmm, das Peeken mit abgetrenntem Kopf sollte einfacher gemacht werden, vor allem sollte es nützliche Informationen im Status anzeigen und erlauben, den Arbeitsbereich mit etwas Feedback (wie die gezogenen Commits) vorzuspulen. Dann wäre es ein Ersatz für schreibgeschützte lokale Zweige.

10voto

michael Punkte 7677

Hier gibt es viele akzeptable Antworten, aber einige der Abläufe sind für Uneingeweihte vielleicht etwas undurchsichtig. Hier ist ein viel einfacheres Beispiel, das leicht angepasst werden kann:

$ cat ~/bin/git/git-update-all
#!/bin/bash
# Update all local branches, checking out each branch in succession.
# Eventually returns to the original branch. Use "-n" for dry-run.
git_update_all() {
  local run br
  br=$(git name-rev --name-only HEAD 2>/dev/null)
  [ "$1" = "-n" ] && shift && run=echo

  for x in $( git branch | cut -c3- ) ; do
     $run git checkout $x && $run git pull --ff-only || return 2
  done

  [ ${#br} -gt 0 ] && $run git checkout "$br"
}

git_update_all "$@"

Wenn Sie Folgendes hinzufügen ~/bin/git zu Ihrem PATH (vorausgesetzt, die Datei ist ~/bin/git/git-update-all ), können Sie einfach weglaufen:

$ git update-all

1 Stimmen

Danke dafür, ich habe es mit Git-Bash unter Windows versucht, aber Git hat sich beschwert und gesagt git: 'update-all' is not a git command. See 'git --help'. Kennt jemand den Ort, um die Erweiterung unter Git-Bash zu registrieren?

0 Stimmen

Según atlassian.com/git/articles/extending-git überall auf dem Weg ist es möglich. Ich habe ~/bin erstellt und es dorthin kopiert und jetzt scheint es zu funktionieren, also danke :)

7voto

Francisco Neto Punkte 71

Ich bin auf die gleiche Frage gestoßen...

Als ich mich darüber wunderte, habe ich eine kleine Alias-Funktion innerhalb meiner .bashrc Datei:

gitPullAll() {
    for branch in `git branch | sed -E 's/^\*/ /' | awk '{print $1}'`; do
        git checkout $branch
        git pull -p
        printf "\n"
    done
    echo "Done"
}

Hat bei mir funktioniert (:

7voto

milkovsky Punkte 8314

Hier ist eine gute Antwort: Wie man alle Git-Zweige abruft

for remote in `git branch -r`; do git branch --track $remote; done
git pull --all

0 Stimmen

Warum schlagen Sie vor, die git fetch y git pull anstelle von nur git pull ?

0 Stimmen

Danke. Es scheint, dass pull alle Zweige von allen Remotes holt. Geändert

9 Stimmen

Damit werden alle Remotes geholt, aber es wird nur der aktuelle Zweig zusammengeführt. Wenn Sie 10 Fernbedienungen haben, müssen Sie jede einzelne manuell auschecken und zusammenführen.

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