Удалить отслеживание веток больше не на удаленном - PullRequest
851 голосов
/ 11 октября 2011

Существует ли простой способ удалить все ветви отслеживания, удаленный эквивалент которых больше не существует?

Пример:

Филиалы (локальные и удаленные)

  • master
  • origin / master
  • origin / bug-fix-a
  • origin / bug-fix-b
  • origin / bug-fix-c

Локально, у меня только основная ветка.Теперь мне нужно работать над bug-fix-a , поэтому я проверяю его, работаю над ним и отправляю изменения на пульт.Затем я делаю то же самое с bug-fix-b .

Филиалы (локальные и удаленные)

  • master
  • bug-fix-a
  • bug-fix-b
  • origin / master
  • origin / bug-fix-a
  • origin / bug-fix-b
  • origin / bug-fix-c

Теперь у меня есть локальные ветви master , bug-fix-a , bug-fix-b .Главный администратор веток объединит мои изменения в master и удалит все уже объединенные ветви.

Итак, текущее состояние теперь:

Ветви (локальные и удаленные)

  • master
  • bug-fix-a
  • bug-fix-b
  • origin / master
  • origin / bug-fix-c

Теперь я хотел бы вызвать некоторую команду для удаления веток (в данном случае bug-fix-a , bug-fix-b ), которые больше не представлены в удаленном хранилище.

Это будет что-то вроде существующей команды git remote prune origin, но больше похоже на git local prune origin.

Ответы [ 26 ]

964 голосов
/ 11 февраля 2015

git remote prune origin удаляет ветви отслеживания, не находящиеся на пульте.

git branch --merged перечисляет ветви, которые были объединены в текущую ветвь.

xargs git branch -d удаляет ветви, перечисленные в стандартном вводе.

Будьте осторожны, удаляя ветки, перечисленные git branch --merged.Список может включать master или другие ветви, которые вы предпочитаете не удалять.

Чтобы дать себе возможность редактировать список перед удалением веток, вы можете сделать следующее в одной строке:

git branch --merged >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

421 голосов
/ 05 ноября 2015

После команды

git fetch -p

удаляет удаленные ссылки, когда вы запускаете

git branch -vv

будет отображаться «ушел» в качестве удаленного статуса. Например,

$ git branch -vv
  master                 b900de9 [origin/master: behind 4] Fixed bug
  release/v3.8           fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
  release/v3.9           0d680d0 [origin/release/v3.9: behind 2] Updated comments
  bug/1234               57379e4 [origin/bug/1234: gone] Fixed bug

Таким образом, вы можете написать простой скрипт для удаления локальных веток, которые прошли удаленно:

git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
247 голосов
/ 15 июля 2016

Большинство из этих ответов на самом деле не отвечают на первоначальный вопрос.Я много копал, и это было самым чистым решением, которое я нашел.Вот несколько более точная версия этого ответа:

  1. Проверьте ветку по умолчанию.Обычно git checkout master
  2. Выполнить git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

Объяснение:

Работает, обрезая ветви отслеживания и удаляя локальные, которые показываютони «пропали» в git branch -vv.

Примечания:

Если для вашего языка установлено значение, отличное от английского, вам нужно будет изменить gone наподходящее словоФилиалы, которые являются только локальными, не будут затронуты.Ветви, которые были удалены на удаленном компьютере, но не были объединены, будут отображать уведомление, но не будут удалены на локальном компьютереЕсли вы хотите удалить их, измените -d на -D.

124 голосов
/ 22 декабря 2017

Я бы обычно не отвечал на вопрос, в котором уже есть 16 ответов, но все остальные ответы неверны, а правильный ответ очень прост.В вопросе говорится: «Есть ли простой способ удалить все ветви отслеживания, удаленный эквивалент которых больше не существует?»

Если «простой» означает удаление их всех за один раз, не хрупкое, не опасное и не зависящееЧто касается инструментов, которые есть не у всех читателей, то правильный ответ: нет.

Некоторые ответы просты, но они не выполняют то, что просили.Другие делают то, что просили, но не все просто: все полагаются на синтаксический анализ выходных данных Git с помощью команд манипулирования текстом или языков сценариев, которые могут отсутствовать в каждой системе.Кроме того, в большинстве предложений используются фарфоровые команды, выходные данные которых не предназначены для анализа сценарием («фарфор» относится к командам, предназначенным для работы с человеком; в сценариях должны использоваться низкоуровневые команды «слесарного дела»).

Дополнительное чтение:


Если вы хотите сделать это безопасно, для рассматриваемого варианта использования (ветви отслеживания сбора мусора, которыебыли удалены на сервере, но все еще существуют как локальные ветви), и только с помощью команд Git высокого уровня необходимо

  • git fetch --prune (или git fetch -p, который является псевдонимом, или git prune remote origin, которая делает то же самое без извлечения, и, вероятно, не то, что вы хотите большую часть времени).
  • Обратите внимание на все удаленные ветки, которые отмечены как удаленные.Или, чтобы найти их позже, git branch -v (любая потерянная ветвь отслеживания будет помечена как «[ушел]»).
  • git branch -d [branch_name] в каждой потерянной ветке отслеживания

(это то, что предлагают другие ответы).

Если вы хотите написать сценарий решения, тогда for-each-ref является вашей отправной точкой, как в Отметьте ответ Лонгаира здесь и этот ответ на другой вопрос , но я не вижу способа использовать его без написания цикла сценария оболочки или использования xargs или чего-то еще.


Фоновое объяснение

Чтобы понять, что происходит, нужно понимать, что в ситуации отслеживания веток у вас есть не одна ветка, а три.(И помните, что «ветвь» означает просто указатель на коммит.)

При наличии отслеживающей ветки feature/X удаленный репозиторий (сервер) будет иметь эту ветвь и будет вызывать ее feature/X.Ваш локальный репозиторий имеет ветку remotes/origin/feature/X, что означает: «Это то, что удаленный сообщил мне, что это была его особенность / ветвь X, когда мы говорили в прошлый раз», и, наконец, локальный репозиторий имеет ветку feature/X, которая указывает на ваш последнийcommit и настроен на «отслеживание» remotes/origin/feature/X, что означает, что вы можете тянуть и нажать, чтобы сохранить их выравнивание.

В какой-то момент кто-то удалил feature/X на пульте.С этого момента у вас останется ваш локальный feature/X (который вам, вероятно, больше не нужен, так как работа над функцией X предположительно завершена), и ваш remotes/origin/feature/X, который, безусловно, бесполезен, потому что его единственной целью было запомнитьсостояние ветви сервера.

И Git позволит вам автоматически очистить избыточный remotes/origin/feature/X - это то, что делает git fetch --prune - но по какой-то причине он не позволяет автоматически удалять вашивладеть feature/X ... даже если ваш feature/X по-прежнему содержит потерянные данные отслеживания, поэтому он содержит информацию для идентификации бывших отслеживающих ветвей, которые были полностью объединены.(В конце концов, он может дать you информацию, которая позволит вам выполнить операцию вручную.)

48 голосов
/ 23 августа 2015

Я нашел ответ здесь: Как я могу удалить все ветки git, которые были объединены?

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

Убедитесь, что мы держим хозяина

Вы можете убедиться, что master или любая другая ветка в этом отношении не будет удалена, добавив еще одну grep после первой. В этом случае вы бы пошли:

git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d

Итак, если мы хотим сохранить master, develop и staging, например, мы бы пошли:

git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d

Сделать это псевдонимом

Поскольку он немного длинный, вы можете добавить псевдоним к .zshrc или .bashrc. Шахта называется gbpurge (для git branches purge):

alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'

Затем перезагрузите ваш .bashrc или .zshrc:

. ~/.bashrc

или

. ~/.zshrc
48 голосов
/ 07 января 2013

Кажется, решение здесь - https://stackoverflow.com/a/1072178/133986

Короче говоря, git remote prune делает волшебство

28 голосов
/ 11 декабря 2014

Удалите все ветви, которые были объединены с мастером, но не пытайтесь удалить сам мастер:

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

или добавьте псевдоним:

alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"

Объяснение:

git checkout master главная ветка извлечения

git pull origin master убедиться, что локальная ветвь объединяет все удаленные изменения

git fetch -p удалить ссылкив удаленные ветви, которые были удалены

git branch -d $(git branch master --merged | grep master -v) удалить все ветви, которые были объединены в мастер, но не пытайтесь удалить сам мастер

26 голосов
/ 01 марта 2018

Windows Solution

Для Microsoft Windows Powershell:

git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}

Объяснение

git checkout master переключается на главную ветвь

git remote update origin --prune удаляет удаленные ветви

git branch -vv получает подробный вывод всех ветвей ( git reference )

Select-String -Pattern ": gone]" получает только те записи, в которых они находятсябыл удален из удаленного.

% { $_.toString().Trim().Split(" ")[0]} получить имя ветви

% {git branch -d $_} удаляет ветку

17 голосов
/ 24 января 2018

Сравнение с шаблоном "ушел" в большинстве других решений было для меня немного страшным. Чтобы быть более безопасным, здесь используется флаг --format для получения статуса отслеживания восходящего направления каждой ветви.

Мне нужна была версия для Windows, поэтому она удаляет все ветки, которые перечислены как «пропавшие» с помощью Powershell:

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }

В первой строке указано название локальных ветвей, у которых вышестоящая ветвь "ушла". Следующая строка удаляет пустые строки (которые выводятся для ветвей, которые не "пропали"), затем имя ветви передается команде для удаления ветви.

16 голосов
/ 17 октября 2014
git fetch -p

Это удалит все ветви, которые не отслеживаются удаленно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...