Перелічіть усі локальні гілки без пульта


91

Проблема: я хочу спосіб видалення всіх локальних гілок у мене, які не мають пульта дистанційного керування. Досить просто перенести імена гілок у a git branch -D {branch_name}, але як я можу отримати цей список?

Наприклад:

Я створюю нову гілку без пульта:

$ git co -b no_upstream

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

$ git branch -a
master
* no_upstream
remotes/origin/HEAD -> origin/master
remotes/origin/master

Яку команду я можу запустити, щоб отримати no_upstreamвідповідь?

Я можу запустити, git rev-parse --abbrev-ref --symbolic-full-name @{u}і це покаже, що у нього немає пульта дистанційного керування:

$ git rev-parse --abbrev-ref --symbolic-full-name @{u}
error: No upstream configured for branch 'no_upstream'
error: No upstream configured for branch 'no_upstream'
fatal: ambiguous argument '@{u}': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Але оскільки це помилка, вона не дозволить мені використовувати її або передавати до інших команд. Я маю намір використовувати це як скрипт оболонки, що називається псевдонімом, git-delete-unbranchedабо, можливо, зробити супер простий камінникgit-branch-delete-orphans



Відповіді:


103

Нещодавно я виявив, git branch -vvяка "дуже багатослівна" версія git branchкоманди.

Він видає гілки разом із віддаленими гілками, якщо вони існують, у наступному форматі:

  25-timeout-error-with-many-targets    206a5fa WIP: batch insert
  31-target-suggestions                 f5bdce6 [origin/31-target-suggestions] Create target suggestion for team and list on save
* 54-feedback-link                      b98e97c [origin/54-feedback-link] WIP: Feedback link in mail
  65-digest-double-publish              2de4150 WIP: publishing-state

Отримавши цей чудово відформатований вивід, ви зможете легко його прокласти cutі awkотримати свій список:

git branch -vv | cut -c 3- | awk '$3 !~/\[/ { print $1 }'

Результати:

25-timeout-error-with-many-targets
65-digest-double-publish

Ця cutчастина просто нормалізує дані, видаливши перші два символи (включаючи *) з вихідних даних, перш ніж передати їх awk.

awkЧастина друкує перший стовпець , якщо немає квадратної дужки в третій колонці.

Бонус: Створіть псевдонім

Спростіть запуск, створивши псевдонім у вашому глобальному .gitconfigфайлі (або де завгодно):

[alias]
  local-branches = !git branch -vv | cut -c 3- | awk '$3 !~/\\[/ { print $1 }'

Важливо: зворотну скісну риску потрібно уникнути в псевдонімі, інакше у вас буде недійсний файл gitconfig.

Бонус: віддалена фільтрація

Якщо з якихось причин у вас є кілька пультів відстеження для різних гілок, досить просто вказати, на якому пульті ви хочете перевірити. Просто додайте ім'я віддаленого до шаблону awk. У моєму випадку це originтак , щоб я міг зробити це:

git branch -vv | cut -c 3- | awk '$3 !~/\[origin/ { print $1 }'

що це WIP:все одно ..? хіба не це створює команда схованки ..?
igrek

@igrek Це лише префікс, який я використав у повідомленні коміту. Нічого специфічного для git.
Джеремі Бейкер,

коли я це роблю git branch -vv, навіть якщо віддалена гілка існує і відповідає моїй локальній гілці, я не бачитиму [origin/branch-name]поряд із результатом. Мені довелося скласти diffдва списки філій, щоб насправді з’ясувати, що є лише місцевим.
ryantuck

git branch -vv | grep -v origin/мені цілком достатньо
не панікуйте

2
Хіба це не пропускає віддалених гілок, позначених gone?
Рід

36

git branch (без будь-яких параметрів) перераховує лише локальні гілки, але ви не знаєте, відстежують вони віддалену гілку чи ні.

Зазвичай ці локальні гілки слід видаляти після об’єднання master(як видно з цього випуску git-sweep ):

git branch --merged master | grep -v master | xargs git branch -d

Це не так повно, як ви хочете, але це початок.

З --merged, будуть перераховані лише гілки, об’єднані в іменований коміт (тобто гілки, коміти коміту яких доступні з іменованого коміту).


1
Щоб також включити віддалені гілки без локальної гілки, використовуйте git branch -a --merged.
Проникність

21

У мене схоже питання. Я хочу видалити всі локальні гілки, які відстежували віддалені гілки, які тепер видалено. Я виявив, що цього git remote prune originбуло недостатньо для видалення гілок, які я хочу відійти. Після того, як пульт буде видалено, я хочу, щоб місцевий також зник. Ось, що мені вдалося:

З мого ~/.gitconfig:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d

Ось git config --global ...команда для легкого додавання цього як git prune-branches:

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'

ПРИМІТКА . Я змінив значення -dна -Dу своїй фактичній конфігурації, оскільки не хочу чути, як Git скаржиться на нез’єднані гілки. Можливо, вам захочеться і ця функціональність. Якщо так, просто використовуйте -Dзамість -dкінця цієї команди.

Крім того, FWIW, ваш глобальний файл конфігурації майже завжди буде ~/.gitconfig.

(Виправлення OS X)

Як писалось, це не працює на OS X через використання xargs -r(дякую, Корні ).

Це -rдля запобігання xargsзапуску git branch -dбез імені гілки, що призведе до повідомлення про помилку " fatal: branch name required". Якщо ви не проти повідомлення про помилку, ви можете просто видалити -rаргумент xargsі все готово.

Однак, якщо ви не хочете бачити повідомлення про помилку (і насправді, хто може вас звинуватити), вам знадобиться щось інше, що перевіряє наявність порожньої труби. Якщо ви зможете використовувати ifne від moreutils . Ви вставляли б ifneраніше xargs, що не дозволить xargsзапускати порожні дані. ПРИМІТКА : ifneвважає що- небудь не порожнім, це включає порожні рядки, тому ви все одно можете побачити це повідомлення про помилку. Я не тестував це на OS X.

Ось такий git configрядок із ifne:

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | ifne xargs git branch -d'

1
Чи можна перетворити це на команду "git config --global ..."? З точки зору інструкції / як до wiki-for-dummies, його легко передати, замість сказати "Знайдіть свої файли конфігурації git, використовуйте редактор, щоб редагувати їх, а потім запускайте команди"
Kannan Ekanath,

Зверніть увагу, що xargs -r не працює на OSX
Корні,

Добре знати. Я не знаю, який варіант "не запускати, якщо порожньо" буде для OSX.
Karl Wilbur

18

Пізнє редагування:

Краще є

git for-each-ref  --format='%(refname:short) %(upstream)'  refs/heads \
| awk '$2 !~/^refs\/remotes/'

На GNU / що завгодно

for b in `git branch|sed s,..,,`; do
    git config --get branch.$b.remote|sed Q1 && echo git branch -D $b
done

Якби ймовірно було більше декількох гілок, були б кращі способи, використовуючи comm -23на виході git branch|sed|sortі git config -l|sed|sort.


1
@nmr s / git. * Q1 / test $ (git config --get branch. $ b.remote | sed q | wc -1) = 1 /
jthill

15

Це працює для мене:

git branch -vv | grep -v origin

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

Тут буде перелічено всі гілки, які не відстежують пульт, що схоже на те, що ви шукаєте.


2
Тут буде перелічено гілки, у яких раніше був пульт, але їх більше немає, навіть якщо ви працюєте git fetch --prune.
RusinaRange

2
ІМО, краще шукати ": gone]" замість того, щоб фільтрувати "походження"
fiorentinoing

4

Я синтезую власну команду Git, щоб отримати origin/***: goneгілки:

git remote prune origin && git branch -vv | cut -c 3- | grep ': gone]' | awk '{print $1}' | xargs -n1 -r echo git branch -d

git remote prune origin && git branch -vv буде друкувати гілки у багатослівному режимі.

cut -c 3- видалить найперші символи.

grep ': gone]'друкуватиме тільки пішли віддалені філії.

awk '{print $1}' надрукує назву гілки.

xargs -n1 -r echo git branch -dнадрукує git branch -dкоманду на видалення гілок (-n1 буде керувати однією командою за раз, -r щоб уникнути видачі команди, якщо гілки немає).

ПІДКАЗКА: видаліть команду "echo", щоб запускати команди замість лише друку, я залишив це в команді для перевірки команд перед тим, як видавати git.

ПОРАДА 2: видайте, git branch -Dякщо і тільки тоді, коли ви впевнені, що хочете видалити незлиті гілки


З цього я зробив мій особистий мерзотник пішов
fiorentinoing

1
Це , безумовно, найчистіше рішення, яке я знайшов, приємно! Я ніколи не витрачав час на навчання awk, я не знав, що ти можеш це зробити.
adamjc

2

Ось те, що я використав у PowerShell з коментарями, щоб пояснити, що він робить. Намагаючись пояснити, що відбувається, я не використовував жодних скорочених команд PowerShell (псевдонімів). Не соромтеся стискати його до бажаного рівня загадковості :)

$verboseList = @(git branch -vv)
foreach ($line in $verboseList)
{
    # Get the branch name
    $branch = [regex]::Match($line, "\s(\S+)\s").Captures.Groups[1].Value
    # Check if the line contains text to indicate if the remote is deleted
    $remoteGone = $line.Contains(": gone]")
    # Check if the line does not contain text to indicate it is a tracking branch (i.e., it's local)
    $isLocal = !($line.Contains("[origin/"))
    if ($remoteGone -or $isLocal)
    {
        # Print the branch name
        $branch
    }
}

0

Поєднуючи кілька існуючих відповідей:

[alias]
        branch-local = !git branch -vv | cut -c 3- | egrep '([0-9a-f]{7} [^[])|(: gone\\])' | sed -E 's/(^.+[0-9a-f]{7} (\\[.+\\])?).*$/\\1/'

Наприклад:

$ git branch-local
autogen_autoreconf      fcfb1c6 [github/autogen_autoreconf: gone]
autotools_documentation 72dc477 [github/autotools_documentation: gone]
cray-mpich-messy        2196f4b
epel-sphinx             cfda770
lammps                  07d96a7 [github/lammps: gone]
lark-error              9ab5d6c [github/lark-error: gone]
no-root2                c3894d1
openmpi-cray            69326cf [github/openmpi-cray: gone]
shellcheck-cleanup      40d90ec
travis-python36         cde072e
update_vagrant_default  4f69f47 [github/update_vagrant_default: gone]
web-docs                e73b4a8
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.