Перелік кожної гілки та дата останньої редакції у Git


138

Мені потрібно видалити старі і незбережені гілки з нашого віддаленого сховища. Я намагаюся знайти спосіб перерахування віддалених гілок за останньою зміненою датою, і не можу.

Чи існує простий спосіб перерахувати віддалені гілки таким чином?



3
Відповіді на: stackoverflow.com/questions/5188320/… - всі кращі, ніж відповіді тут
Програмний інженер

Відповіді:


172

commandlinefu є 2 цікаві пропозиції:

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

або:

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

Це для місцевих гілок, у синтаксисі Unix. Використовуючи git branch -r, ви можете аналогічно показати віддалені гілки:

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

Майкл Форрест згадує в коментарях , що ЗШ вимагає пагонів для sedвираження:

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 

постійність додає в коментарях :

Якщо ви хочете додати його в свій zshrc, потрібна наступна версія.

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'

У кількох рядках:

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'

Примітка: n8tr «s відповідь , заснований на git for-each-ref refs/headsчистіше. І швидше .
Дивіться також " Опція лише для імені git branch --list? "

Більш загально, трійка нагадує нам у коментарях :

  • Віддайте перевагу сучасному $(command substitution)синтаксису над застарілим синтаксисом backtick.

(Я проілюстрував цю точку в 2014 році за допомогою " Яка різниця між програмуванням оболонки $(command)та `command`в програмі оболонки? ")


1
@hansen j: цікаво, чи не так? Він був запущений через кілька місяців після публічного випуску Stack Overflow ( codeinthehole.com/archives/… ) і був дещо натхненний SO. Дивіться також commandlinefu.com/commands/tagged/67/git для більше git
commandlinefu

Ця відповідь стусани stackoverflow.com/questions/5188320 / ... дупи «s. :)
Spundun

@SebastianG не впевнений: це було б добре питання.
VonC

+1 Досить дивовижно, як ви можете додати /jsonдо кінця будь-яку URL-адресу commandlinefu.com, і ви отримаєте всі команди як JSON.
Ной Суссман

1
@tripleee Дякую Я відредагував відповідь і включив ваші коментарі для більшої наочності.
VonC

121

Ось що я використовую:

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

Це вихід:

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

Для віддалених відділень просто використовуйте "refs / remote" замість "refs / heads":

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

Спираючись на відповідь n8tr , якщо вас також цікавить останній автор на гілці, і якщо у вас є інструмент "стовпець", ви можете використовувати:

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

Що дасть вам:

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

Ви можете зателефонувати "git fetch --prune" раніше, щоб отримати останню інформацію.


5
Добре використовувати параметри для кожного перегляду та форматування. +1. Звучить простіше, ніж команди, на які я посилаюсь у власній відповіді.
VonC

2
трохи налаштувати: ------- git for-every-ref --sort = '- authordate: iso8601' --format = '% (авторизація: відносна)% 09% (refname: короткий)' ref / head ------- надає відносну дату та усуває відповідні /
голоси

1
Для тих, кому це не відразу очевидно, я думаю, що це показує інформацію. суворо для місцевих відділень.
hBrent

@hBrent Ви праві, це не відповіло точно на запитання. Я відповідно відредагував свою відповідь.
окрокет

Це сортує та перераховує гілки за authordate(що здається, коли гілка була створена вперше?). Якщо ви перейдете authordateна, committerdateви побачите дати останнього комітету у кожному відділенні. git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads
Ось

23

Будуючи за Олів'є Крокетт , мені подобається використовувати відносну дату та скорочувати назву гілки так:

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

Що дає результат:

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

Я рекомендую створити файл Bash для додавання всіх улюблених псевдонімів, а потім поділитися сценарієм зі своєю командою. Ось приклад для додавання саме цього:

#!/bin/sh

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

Тоді ви можете просто зробити це, щоб отримати добре відформатований і відсортований список місцевих відділень:

git branches

20

Просто для додання коментаря від @VonC, візьміть бажане рішення та додайте його до списку псевдонімів ~ / .gitconfig для зручності:

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

Тоді простий "git branchdate" друкує список для вас ...


3
+1 для показу, як його використовувати з .gitconfig! Також fwiw я змінив рядок формату на: --format='%(authordate)%09%(objectname:short)%09%(refname)'що також отримує короткий хеш кожної гілки.
Ной Суссман

Приємно. Я б додав "| tac" до кінця, щоб сортувати його у зворотному порядку, так що недавно торкнуті гілки швидко видно.
Бен

1
Вам не потрібно | tac, лише --sort='authordate'замість-authordate
Kristján

4

Ось, що я придумав, також переглянувши це .

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

PREV_REFПеревірка видалити дублікати , якщо більш ніж одна гілка вказує на те передай. (Як і в локальній гілці, яка існує і у віддаленій.)

Зверніть увагу, що за запитом на ОП git branch --mergedі git branch --no-mergedвони корисні при визначенні, які гілки можна легко видалити.

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


3

Відсортовано віддалені гілки та останню дату фіксації для кожної гілки.

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

1
Дякуємо за відповідь на питання щодо ОП щодо віддаленого.
arcseldon

1

Я зробив два варіанти на основі відповіді VonC .

Мій перший варіант:

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 "|"

Це обробляє локальні та віддалені гілки ( -a), обробляє стан відстороненої головки (довша команда sed, хоча рішення є настільки сирим - він просто замінює відокремлену інформацію гілки ключовим словом HEAD), додає у темі фіксації (% s ), і додає речі в стовпці через буквальні символи труби в рядку формату і передає кінцевий результат в column -t -s "|". (Ви можете використовувати що-небудь як роздільник, якщо це щось, чого ви не очікуєте в решті результатів.)

Мій другий варіант є досить хитким, але я дуже хотів щось, що все ще має індикатор "це гілка, на якій ти зараз", як це робить команда гілки.

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 "|"

Це перетворює те, *що позначає поточну гілку в ключове слово, і коли тіло циклу бачить ключове слово, воно замість цього встановлює прапор і нічого не видає. Прапор використовується для вказівки, що для наступного рядка слід використовувати альтернативне форматування. Як я вже казав, це абсолютно хакі, але це працює! (Здебільшого, чомусь мій останній стовпець викреслюється в поточній лінії гілки.)


На жаль, інформація у відповіді VonCs не є чудовою основою для сценаріїв. Дивіться тут git-blame.blogspot.com/2013/06/…
Андрій C

Хм. Це показує спосіб отримати назву поточної гілки, якщо вона має назву. Чи існує [кращий] спосіб отримати машинознавчий список філій? (І якимось чином відрізнити поточну гілку, або від цього виводу безпосередньо, або через якийсь запит git "це те саме, що і HEAD?")
benkc

git for-each-refє зручним для сценарію способом обробки гілок. Вам потрібно буде запустити символ-ref один раз, щоб отримати поточну гілку.
Ендрю С

+1 за зусилля, але це була справді моя стара відповідь. stackoverflow.com/a/16971547/6309 або (більш повна) stackoverflow.com/a/19585361/6309 може містити менше "sed".
VonC

1

Я зробив простий псевдонім, не впевнений, чи це саме те, про що питали, але це просто

Я зробив це так, як хотів перерахувати всі гілки, а не лише мої локальні гілки, які виконуються лише над командами

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

Ви можете подати трубу вище, grep originщоб отримати лише джерела

У цьому списку перелічено всі гілки разом із останньою зміненою датою, що допомагає мені вирішити, яку саме я слід витягнути для останньої версії

Це призводить до нижнього типу дисплея

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

Спробуйте і дайте мені знати, чи допомогло це, радісно виступивши


Приємно і просто. Ніякого спеціального соусу.
MrMas

0

Або ви можете використовувати мій скрипт PHP, https://gist.github.com/2780984

#!/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++;
    }
?>

0

Ось функція, яку ви можете додати до свого bash_profile, щоб зробити це простіше.

Використання в сховищі Git:

  • branch друкує всі місцеві відділення
  • branch -r друкує всі віддалені гілки

Функція:

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
}

0

У PowerShell наступне відображає гілки на пульті, які вже об'єднані та мають принаймні два тижні ( author:relativeформат починає відображати тижні замість днів на два тижні):

$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}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.