Auflistung jedes Zweigs und des Datums seiner letzten Überarbeitung in Git

138

Ich muss alte und nicht gepflegte Zweige aus unserem Remote-Repository löschen. Ich versuche einen Weg zu finden, wie die Remote-Zweige nach ihrem letzten Änderungsdatum aufgelistet werden können, und ich kann nicht.

Gibt es eine einfache Möglichkeit, Remote-Zweige auf diese Weise aufzulisten?

Roni Yaniv
quelle
3
Die Antworten auf: stackoverflow.com/questions/5188320/… sind alle besser als die Antworten hier
Software Engineer

Antworten:

172

commandlinefu hat 2 interessante Vorschläge:

for k in `git branch | perl -pe s/^..//`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

oder:

for k in `git branch | sed s/^..//`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k --`\\t"$k";done | sort

Dies gilt für lokale Zweige in einer Unix-Syntax. Mit git branch -rkönnen Sie auf ähnliche Weise entfernte Zweige anzeigen:

for k in `git branch -r | perl -pe 's/^..(.*?)( ->.*)?$/\1/'`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

Michael Forrest erwähnt in den Kommentaren, dass zsh Escapezeichen für den sedAusdruck benötigt:

for k in git branch | perl -pe s\/\^\.\.\/\/; do echo -e git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1\\t$k; done | sort -r 

Kontinuität fügt in den Kommentaren hinzu :

Wenn Sie es Ihrem zshrc hinzufügen möchten, ist das folgende Escape erforderlich.

alias gbage='for k in `git branch -r | perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r'

In mehreren Zeilen:

alias gbage='for k in `git branch -r | \
  perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; \
  do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | \
     head -n 1`\\t$k; done | sort -r'

Hinweis: Die Antwort von n8tr basiert auf sauberer. Und schneller . Siehe auch " Nur Name Option für ? "git for-each-ref refs/heads
git branch --list

Im Allgemeinen erinnert uns Tripleee in den Kommentaren :

  • Bevorzugen Sie moderne $(command substitution)Syntax gegenüber veralteter Backtick-Syntax.

(Ich habe diesen Punkt 2014 mit " Was ist der Unterschied zwischen $(command)und `command`in der Shell-Programmierung? " Illustriert. )

  • Lies keine Zeilen mitfor .
  • Wechseln Sie wahrscheinlich zu git for-each-ref refs/remote, um Remote-Zweigstellennamen in maschinenlesbarem Format abzurufen
VonC
quelle
1
@hansen j: interessant, nicht wahr? Es wurde einige Monate nach der Veröffentlichung von Stack Overflow ( codeinthehole.com/archives/… ) veröffentlicht und war etwas von SO inspiriert. Siehe auch commandlinefu.com/commands/tagged/67/git für mehr git commandlinefu;)
VonC
Diese Antwort schlägt stackoverflow.com/questions/5188320/… in den Arsch. :)
Spundun
@SebastianG nicht sicher: das wäre eine gute Frage für sich.
VonC
+1 Ziemlich großartig, wie Sie /jsonam Ende einer beliebigen commandlinefu.com- URL hinzufügen können und alle Befehle als JSON erhalten.
Noah Sussman
1
@tripleee Danke. Ich habe die Antwort bearbeitet und Ihre Kommentare für mehr Sichtbarkeit eingefügt.
VonC
120

Folgendes benutze ich:

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads

Dies ist die Ausgabe:

2014-01-22 11:43:18 +0100       refs/heads/master
2014-01-22 11:43:18 +0100       refs/heads/a
2014-01-17 12:34:01 +0100       refs/heads/b
2014-01-14 15:58:33 +0100       refs/heads/maint
2013-12-11 14:20:06 +0100       refs/heads/d/e
2013-12-09 12:48:04 +0100       refs/heads/f

Verwenden Sie für entfernte Zweige einfach "refs / remotes" anstelle von "refs / Heads":

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/remotes

Aufbauend auf der Antwort von n8tr können Sie Folgendes verwenden , wenn Sie auch an dem letzten Autor in der Branche interessiert sind und das Tool "Spalte" zur Verfügung haben:

git for-each-ref --sort='-committerdate:iso8601' --format='%(committerdate:relative)|%(refname:short)|%(committername)' refs/remotes/ | column -s '|' -t

Welches wird Ihnen geben:

21 minutes ago  refs/remotes/a        John Doe
6 hours ago     refs/remotes/b        Jane Doe
6 days ago      refs/remotes/master   John Doe

Möglicherweise möchten Sie vorher "git fetch --prune" aufrufen, um die neuesten Informationen zu erhalten.

Okroquette
quelle
5
Gute Verwendung für jede Referenz und die Formatoptionen. +1. Klingt einfacher als die Befehle, auf die ich in meiner eigenen Antwort verweise.
VonC
2
ein wenig optimieren: ------- git for-each-ref --sort = '- authordate: iso8601' --format = '% (authordate: relative)% 09% (refname: short)' refs / Heads ------- gibt Ihnen ein relatives Datum und beseitigt die Schiedsrichter / Köpfe
n8tr
1
Für diejenigen, denen es nicht sofort klar ist, denke ich, dass dies Informationen zeigt. ausschließlich für lokale Niederlassungen.
hBrent
@hBrent du hast recht, es hat nicht genau die Frage beantwortet. Ich habe meine Antwort entsprechend bearbeitet.
Okroquette
Dies sortiert und listet die Zweige nach authordate(was scheint zu sein, als der Zweig zum ersten Mal erstellt wurde?). Wenn Sie ändern , authordateum committerdatedann in jedem Zweig begehen werden Sie die Daten der jüngsten zu sehen. Wie so:git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads
Logan Besecker
23

Aufbauend auf Olivier Croquette verwende ich gerne ein relatives Datum und kürze den Filialnamen folgendermaßen :

git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads

Welches gibt Ihnen Ausgabe:

21 minutes ago  nathan/a_recent_branch
6 hours ago        master
27 hours ago    nathan/some_other_branch
29 hours ago    branch_c
6 days ago      branch_d

Ich empfehle, eine Bash-Datei zu erstellen, um alle Ihre Lieblings-Aliase hinzuzufügen und das Skript dann an Ihr Team weiterzugeben. Hier ist ein Beispiel, um nur dieses hinzuzufügen:

#!/bin/sh

git config --global alias.branches "!echo ' ------------------------------------------------------------' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------'"

Dann können Sie dies einfach tun, um eine gut formatierte und sortierte lokale Zweigstellenliste zu erhalten:

git branches
n8tr
quelle
20

Um den Kommentar von @VonC zu ergänzen, nehmen Sie Ihre bevorzugte Lösung und fügen Sie sie der Einfachheit halber Ihrer Alias-Liste ~ / .gitconfig hinzu:

[alias]  
    branchdate = !git for-each-ref --sort='-authordate' --format='%(refname)%09%(authordate)' refs/heads | sed -e 's-refs/heads/--'

Dann druckt ein einfaches "Git Branchdate" die Liste für Sie ...

yngve
quelle
3
+1 für die Verwendung mit .gitconfig! Außerdem habe ich die Formatzeichenfolge in: geändert, --format='%(authordate)%09%(objectname:short)%09%(refname)'wodurch auch der kurze Hash jedes Zweigs abgerufen wird .
Noah Sussman
Nett. Ich würde am Ende "| tac" hinzufügen, um es in umgekehrter Reihenfolge zu sortieren, damit die kürzlich berührten Zweige schnell sichtbar sind.
Ben
1
Sie müssen nicht | tac, nur --sort='authordate'statt-authordate
Kristján
4

Hier ist, was ich mir ausgedacht habe, nachdem ich dies ebenfalls überprüft habe .

for REF in $(git for-each-ref --sort=-committerdate --format="%(objectname)" \
    refs/remotes refs/heads)
do
    if [ "$PREV_REF" != "$REF" ]; then
        PREV_REF=$REF
        git log -n1 $REF --date=short \
            --pretty=format:"%C(auto)%ad %h%d %s %C(yellow)[%an]%C(reset)"
    fi
done

Die PREV_REFÜberprüfung besteht darin, Duplikate zu entfernen, wenn mehr als ein Zweig auf dasselbe Commit verweist. (Wie in einem lokalen Zweig, der auch in der Fernbedienung vorhanden ist.)

Beachten Sie, dass gemäß der OP-Anforderung git branch --mergedund git branch --no-mergednützlich sind, um zu identifizieren, welche Zweige leicht gelöscht werden können.

[ https://git-scm.com/docs/git-branch]

go2null
quelle
3

Sortierte Remote- Zweige und das letzte Festschreibungsdatum für jeden Zweig.

for branch in `git branch -r | grep -v HEAD`;do echo -e `git show --format="%ci %cr" $branch | head -n 1` \\t$branch; done | sort -r
Shweta
quelle
1
Vielen Dank, dass Sie die OP-Frage zu Remote beantwortet haben.
Arcseldon
1

Ich habe zwei Varianten gemacht, basierend auf VonCs Antwort .

Meine erste Variante:

for k in `git branch -a | sed -e s/^..// -e 's/(detached from .*)/HEAD/'`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`;done | sort | column -t -s "|"

Dies behandelt lokale und entfernte Zweige ( -a), behandelt den Status des getrennten Kopfes (der längere Befehl sed, obwohl die Lösung etwas grob ist - er ersetzt nur die Informationen des getrennten Zweigs durch das Schlüsselwort HEAD), fügt das Festschreibungssubjekt hinzu (% s ) und fügt Dinge über Literal-Pipe-Zeichen in der Formatzeichenfolge in Spalten ein und übergibt das Endergebnis an column -t -s "|". (Sie können alles als Trennzeichen verwenden, solange Sie dies im Rest der Ausgabe nicht erwarten.)

Meine zweite Variante ist ziemlich hackig, aber ich wollte wirklich etwas, das immer noch einen Indikator für "Dies ist der Zweig, in dem Sie sich gerade befinden" hat, wie es der Befehl branch tut.

CURRENT_BRANCH=0
for k in `git branch -a | sed -e 's/\*/CURRENT_BRANCH_MARKER/' -e 's/(detached from .*)/HEAD/'`
do
    if [ "$k" == 'CURRENT_BRANCH_MARKER' ]; then
        # Set flag, skip output
        CURRENT_BRANCH=1
    elif [ $CURRENT_BRANCH == 0 ]; then
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`
    else
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset* %Cgreen$k%Creset |%s" $k --`
        CURRENT_BRANCH=0
    fi
done | sort | column -t -s "|"

Dadurch wird der *, der den aktuellen Zweig markiert, in ein Schlüsselwort umgewandelt. Wenn der Schleifenkörper das Schlüsselwort sieht, setzt er stattdessen ein Flag und gibt nichts aus. Das Flag gibt an, dass für die nächste Zeile eine alternative Formatierung verwendet werden soll. Wie ich schon sagte, es ist total hacky, aber es funktioniert! (Meistens. Aus irgendeinem Grund wird meine letzte Spalte in der aktuellen Zweigleitung veraltet.)

benkc
quelle
Leider sind die Informationen in VonCs Antwort keine gute Grundlage für Skripte. Siehe hier git-blame.blogspot.com/2013/06/…
Andrew C
Hmm. Dies zeigt eine Möglichkeit, den Namen des aktuellen Zweigs abzurufen, wenn dieser einen Namen hat. Gibt es eine [bevorzugte] Möglichkeit, eine maschinenfreundliche Liste von Filialen zu erhalten? (Und eine Möglichkeit, den aktuellen Zweig zu unterscheiden, entweder direkt von dieser Ausgabe oder durch die Frage, ob git "ist dies der gleiche
Verweis
git for-each-refist die skriptfreundliche Methode zur Verarbeitung von Zweigen. Sie müssten die symbolische Referenz einmal ausführen, um den aktuellen Zweig zu erhalten.
Andrew C
+1 für die Anstrengung, aber das war in der Tat eine alte Antwort von mir. stackoverflow.com/a/16971547/6309 oder (vollständiger) stackoverflow.com/a/19585361/6309 kann weniger "sed" beinhalten.
VonC
1

Ich habe einen einfachen Alias ​​erstellt, nicht sicher, ob dies genau gefragt ist, aber es ist einfach

Ich tat dies, weil ich alle Zweige auflisten wollte, nicht nur meine lokalen Zweige, was die obigen Befehle nur tun

alias git_brs="git fetch && git branch -av --format='\''%(authordate)%09%(authordate:relative)%09%(refname)'\'"

Sie können oben pfeifen grep origin, um nur Ursprünge zu erhalten

Dies listet alle Zweige zusammen mit dem letzten Änderungsdatum auf und hilft mir bei der Entscheidung, welchen ich für die neueste Version ziehen soll

Dies führt zu der folgenden Art der Anzeige

Wed Feb 4 23:21:56 2019 +0230   8 days ago      refs/heads/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/heads/master
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/heads/bar
Wed Feb 11 16:34:00 2019 +0230  2 days ago      refs/heads/xyz
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/HEAD
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/remotes/origin/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/master
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/bar
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/xyz

Versuchen Sie und lassen Sie mich wissen, ob es geholfen hat, fröhliches Gitting

Basav
quelle
Schön und einfach. Keine spezielle Sauce.
MrMas
0

Oder Sie können mein PHP-Skript https://gist.github.com/2780984 verwenden

#!/usr/bin/env php
<?php
    $local = exec("git branch | xargs $1");
    $lines = explode(" ", $local);
    $limit = strtotime("-2 week");
    $exclude = array("*", "master");
    foreach ($exclude as $i) {
        $k = array_search($i, $lines);
        unset($lines[$k]);
    }
    $k = 0;
    foreach ($lines as $line) {
        $output[$k]['name'] = $line;
        $output[$k]['time'] = exec('git log '.$line.' --pretty=format:"%at" -1');
        if ($limit>$output[$k]['time']) {
            echo "This branch should be deleted $line\n";
            exec("git branch -d $line");
        }
        $k++;
    }
?>
Ladislav Prskavec
quelle
0

Hier ist eine Funktion, die Sie Ihrem bash_profile hinzufügen können, um dies zu vereinfachen.

Verwendung in einem Git-Repository:

  • branch druckt alle lokalen Filialen
  • branch -r druckt alle entfernten Zweige

Funktion:

branch() {
   local pattern="s/^..//"
   local arg=""
   if [[ $@ == "-r" ]]; then
      pattern="s/^..(.*?)( ->.*)?$/\1/"
      arg=" -r "
      echo '-r provided'
   fi
   for k in $(git branch $arg | perl -pe "$pattern"); do
      echo -e $(git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1)\\t$k
   done | sort -r
}
Enderland
quelle
0

In PowerShell werden im Folgenden Zweige auf der Fernbedienung angezeigt, die bereits zusammengeführt wurden und mindestens zwei Wochen alt sind (das author:relativeFormat zeigt Wochen statt Tage nach zwei Wochen an):

$safeBranchRegex = "origin/(HEAD|master|develop)$";
$remoteMergedBranches = git branch --remote --merged | %{$_.trim()};
git for-each-ref --sort='authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/remotes | ?{$_ -match "(weeks|months|years) ago" -and $_ -notmatch "origin/(HEAD|master|qa/)"} | %{$_.substring($_.indexof("origin/"))} | ?{$_ -in $remoteMergedBranches}
Dave Neeley
quelle