Есть ли простой способ удалить все ветви отслеживания, удаленный эквивалент которых больше не существует?
Пример:
Филиалы (местные и удаленные)
- мастер
- Происхождение / мастер
- Происхождение / ошибка затруднительного-а
- Происхождение / ошибка затруднительного-б
- Происхождение / ошибка затруднительного-с
Локально у меня только мастер ветка. Теперь мне нужно поработать над bug-fix-a , поэтому я проверяю его, работаю над ним и отправляю изменения на пульт. Затем я делаю то же самое с bug-fix-b .
Филиалы (местные и удаленные)
- мастер
- ошибка-фикс-а
- ошибка затруднительного-б
- Происхождение / мастер
- Происхождение / ошибка затруднительного-а
- Происхождение / ошибка затруднительного-б
- Происхождение / ошибка затруднительного-с
Теперь у меня есть мастер локальных веток , bug-fix-a , bug-fix-b . Мастер веток Мастер объединит мои изменения в мастер и удалит все ветви, которые он уже слил.
Итак, текущее состояние сейчас:
Филиалы (местные и удаленные)
- мастер
- ошибка-фикс-а
- ошибка затруднительного-б
- Происхождение / мастер
- Происхождение / ошибка затруднительного-с
Теперь я хотел бы вызвать некоторую команду для удаления веток (в данном случае bug-fix-a , bug-fix-b ), которые больше не представлены в удаленном репозитории.
Это было бы что-то вроде существующей команды git remote prune origin
, но больше похоже git local prune origin
.
источник
* master
в моей системе. У меня сработала следующая команда:git branch -d $(git branch --merged |tail -n +2)
develop
тоgit branch --merged
включаетmaster
! Вы вероятно (определенно!) Не хотите удалять это. Также я думаю, что это должно бытьgit branch -d
там, где строчные буквы-d
означают «безопасное удаление», например, удаление только в случае объединения.git branch --merged | grep -v "master" >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
После команды
удаляет удаленные ссылки при запуске
он покажет «ушел» как удаленный статус. Например,
Таким образом, вы можете написать простой скрипт для удаления локальных веток, которые прошли удаленно:
Обратите внимание, что вышеприведенное использует команду "фарфор"
git branch
для получения статуса восходящего потока.Другой способ получить это состояние - использовать команду «plumbing»
git for-each-ref
с интерполяционной переменной%(upstream:track)
, которая будет такой[gone]
же, как и выше.Этот подход несколько безопаснее, потому что нет риска случайного сопоставления части сообщения фиксации.
источник
git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
awk '/: gone]/{if ($1!="*") print $1}'
. Теперь это работает, как и ожидалось.test = "!git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
Большинство из этих ответов на самом деле не отвечают на первоначальный вопрос. Я много копал, и это было самое чистое решение, которое я нашел. Вот немного более полная версия этого ответа:
git checkout master
git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d
Объяснение:
Работает, обрезая ваши ветви отслеживания, затем удаляя локальные, которые показывают, что они "пропали"
git branch -vv
.Ноты:
Если ваш язык настроен на что-то отличное от английского, вам нужно будет перейти
gone
на соответствующее слово. Только локальные ветви не будут затронуты. Ветви, которые были удалены на удаленном компьютере, но не были объединены, будут отображать уведомление, но не будут удалены на локальном компьютере. Если вы хотите удалить их, также измените-d
на-D
.источник
git checkout master && ...
в начале команды.git branch -vv
начнется со звездочки, что в итоге приведет к выполнениюgit branch -d *
. Вот исправленная версия, которая будет игнорировать строки со звездочкой:git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
Обычно я не отвечаю на вопрос, в котором уже есть 16 ответов, но все остальные ответы неверны, а правильный ответ очень прост. Вопрос говорит: «Есть ли простой способ удалить все ветви отслеживания, удаленный эквивалент которых больше не существует?»
Если «простой» означает удаление их всех за один раз, не хрупкое, не опасное и не зависящее от инструментов, которые есть не у всех читателей, то правильный ответ: нет.
Некоторые ответы просты, но они не делают то, что просили. Другие делают то, что просили, но они не просты: все полагаются на синтаксический анализ выходных данных Git с помощью команд манипулирования текстом или языков сценариев, которые могут отсутствовать в каждой системе. Кроме того, в большинстве предложений используются фарфоровые команды, выходные данные которых не предназначены для анализа сценарием («фарфор» относится к командам, предназначенным для работы с человеком; сценарии должны использовать низкоуровневые команды «слесарного дела»).
Дальнейшее чтение:
git branch
вывод в скрипте .git remote prune
,git prune
,git fetch --prune
Если вы хотите сделать это безопасно, для рассматриваемого варианта использования (ветви отслеживания сбора мусора, которые были удалены на сервере, но все еще существуют как локальные ветви) и только с командами 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
которая означает: «Это то, что удаленный сообщил мне, что его ветвь feature / X была, когда мы говорили в прошлый раз», и, наконец, локальный репозиторий имеет ветку,feature/X
которая указывает на ваш последний коммит, и настроен на «отслеживать»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
все еще содержит потерянные данные отслеживания, поэтому он содержит информацию идентифицировать бывшие ветви отслеживания, которые были полностью объединены. (В конце концов, он может дать вам информацию, которая позволит вам выполнить операцию вручную.)источник
xargs
). Существует такжеgit alias
упрощение ряда случаев.xargs
или bash, и они, вероятно, здесь не ищут проблему микрокодирования, так как быстрый ответ они могут безопасно применить, не отвлекая себя от их реальной цели ,Я нашел ответ здесь: Как я могу удалить все ветви git, которые были объединены?
Убедитесь, что мы держим хозяина
Вы можете убедиться, что
master
или любая другая ветка в этом отношении не будет удалена, добавив другуюgrep
после первой. В этом случае вы бы пошли:Так что, если бы мы хотели сохранить
master
,develop
и,staging
например, мы бы пошли:Сделайте этот псевдоним
Так как это немного долго, вы можете добавить псевдоним в ваш
.zshrc
или.bashrc
. Шахта называетсяgbpurge
(дляgit branches purge
):Затем перезагрузите ваш
.bashrc
или.zshrc
:или
источник
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 $_}
Explaination
git checkout master
переключается на главную веткуgit remote update origin --prune
чернослив удаленные ветвиgit branch -vv
получает подробный вывод всех ветвей ( ссылка на git )Select-String -Pattern ": gone]"
получает только записи, где они были удалены из удаленного.% { $_.toString().Trim().Split(" ")[0]}
получить название филиала% {git branch -d $_}
удаляет веткуисточник
.Trim()
после.toString()
, чтобы удалить два пробела перед именем ветви.git branch -d
чтобыgit branch -D
я еще получаю ошибку ветвь не полностью слита.git branch -D
это разрушительное и удалить локальную работу , которую вы еще не нажаты.-d
всегда безопасно, просто будьте осторожны с-D
.Сопоставление с шаблоном «ушел» в большинстве других решений было для меня немного страшным. Чтобы быть более безопасным, этот
--format
флаг используется для извлечения статуса отслеживания восходящего направления каждой ветви .Мне нужна была версия, удобная для Windows, поэтому она удаляет все ветви, которые перечислены как «пропавшие» с помощью Powershell:
Первая строка перечисляет названия локальных ветвей, чья ветвь вверх по течению «ушла». Следующая строка удаляет пустые строки (которые выводятся для ветвей, которые не «пропали»), затем имя ветви передается команде для удаления ветви.
источник
--format
Вариант , кажется, довольно новый; Мне нужно было обновить git с 2.10. До 2.16.3, чтобы получить его. Это моя модификация для систем Linux-ish:git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
refname:short
. Тогда вы можете удалить строку% { $_ -replace '^refs/heads/', '' }
git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ }
Также, вероятно, хорошая идея использовать-d
вместо-D
. Принудительное удаление не должно быть необходимым для филиалов, которые больше не находятся на удаленном компьютере.Удалите все ветви, которые были объединены с мастером, но не пытайтесь удалить сам мастер:
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)
удалить все ветви, которые были объединены в мастер, но не пытайтесь удалить сам мастеристочник
git branch -D
командуgit branch -d
которые должны выдавать предупреждение о неперекачиваемых ветвях.Это удалит все ветви, которые больше не существуют на пульте.
источник
X
; тыgit checkout X
; теперь ваш репозиторий имеет (локальную) ветвь отслеживанияX
и удаленную веткуorigin/X
; удаленный репозиторий удаляетX
; тыgit fetch-p
; в вашем локальном хранилище не только,origin/X
но иX
были удалены. Это то, что вы говорите?И еще один ответ на кучу, в значительной степени основанный на ответе Патрика (который мне нравится, потому что кажется, что он устраняет любую двусмысленность в отношении того, где
gone]
будут совпадатьgit branch
результаты), но с добавлением * nix bent.В простейшем виде:
У меня есть это в
git-gone
сценарии на моем пути:NB -
--format
вариант кажется довольно новым; Мне нужно было обновить git с 2.10. До 2.16.3, чтобы получить его.РЕДАКТИРОВАТЬ: настроить, чтобы включить предложение
refname:short
от Бенджамина В.NB2 - я только проверял
bash
, отсюда хэшбэнг, но, вероятно, переносимsh
.источник
sed
часть, используя%(refname:short)
в первой строке?--format
. Другой способ пропуститьsed
часть состоит в том, чтобы использоватьgit update-ref -d
. Обратите внимание, что это, вероятно, несколько небезопасно, использованиеgit for-each-ref
здесь безопаснее (дано--shell
).--format
сделать это сам. Только один вопрос: почему#!bash
? Все здесь выглядит портативнымsh
для меня.Может быть полезно для некоторых, простая одна строка, чтобы очистить все локальные ветви, кроме мастер и развития
источник
'git branch | grep -v "master" | grep -v "develop"
такими вещами, прежде чем добавлять к удаленной части команды. FinЭто удалит все объединенные локальные ветви, кроме локальной главной ссылки и той, которая используется в настоящее время:
И это удалит все ветви, уже удаленные из удаленного репозитория, на которые ссылается « origin », но которые все еще доступны локально в « remotes / origin ».
источник
git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d
Объяснение: Я предпочитаю заменять наgit branch --merged
,git branch -vv
чтобы показать статус (ушел), потому что предыдущийgit branch --merged
может также показать мастерЯ не думаю, что есть встроенная команда, чтобы сделать это, но это безопасно сделать следующее:
Когда вы используете
-d
, git откажется от удаления ветки, если она не будет полностью объединена сHEAD
веткой удаленного отслеживания в восходящем направлении. Таким образом, вы всегда можете просмотреть цикл выводаgit for-each-ref
и попытаться удалить каждую ветвь. Проблема с этим подходом состоит в том, что я подозреваю, что вы, вероятно, не хотите,bug-fix-d
чтобы его удаляли только потому, что онorigin/bug-fix-d
содержит его историю. Вместо этого вы можете создать скрипт примерно так:Предупреждение: я не проверял этот скрипт - используйте только осторожно ...
источник
TL; DR:
Удалить ВСЕ локальные ветви, которые не находятся на удаленном
Удалите ВСЕ локальные ветви, которые не находятся на удаленном И полностью объединены И не используются, как сказано во многих ответах ранее.
объяснение
git fetch -p
удалит все ветви, которые больше не существуют на удаленномgit branch -vv
распечатает локальные ветви, а обрезанные ветви будут помеченыgone
grep ': gone]'
выбирает только те ветви, которые ушлиawk '{print $1}'
отфильтруйте вывод, чтобы отобразить только название ветокxargs git branch -D
будет перебирать все линии (ветви) и принудительно удалять эту веткуПочему
git branch -D
и нет уgit branch -d
вас будет для филиалов, которые не полностью объединены.источник
Вы могли бы сделать это:
источник
Основываясь на информации выше, это сработало для меня:
Удаляет все локальные ветки с
': gone] '
удаленно.источник
gone
где-либо в своем имени.Приведенная выше команда может использоваться для извлечения веток, которые объединены и удалены в удаленном режиме, и удаляет локальную ветвь, которая больше не доступна в удаленном
источник
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -D
чтобы заставить удалить всеgone
любом месте (напримерusingonefunction
).Ничто из этого не было действительно правильным для меня. Я хотел что-то, что очистило бы все локальные ветви, которые отслеживали удаленную ветвь, там
origin
, где удаленная ветвь была удалена (gone
). Я не хотел удалять локальные ветви, которые никогда не были настроены для отслеживания удаленной ветви (т.е. мои локальные ветви разработки). Также я хотел простой однострочник, который просто используетgit
, или другие простые инструменты CLI, вместо того, чтобы писать собственные сценарии. Я использовал немногоgrep
иawk
сделал эту простую команду.Это в конечном итоге то, что закончилось в моем
~/.gitconfig
:Вот
git config --global ...
команда для простого добавления этого какgit prune-branches
:ПРИМЕЧАНИЕ. В команде config я использую
-d
опциюgit branch
вместо-D
, как в реальной конфигурации. Я использую,-D
потому что я не хочу слышать, как Гит жалуется на неразделенные ветви. Вы можете также хотеть эту функциональность. Если это так, просто используйте-D
вместо-d
в конце этой команды конфигурации.источник
git branch -vv
а что делать,: gone]
а не делатьgit branch -v
и делать[gone]
?v
. Еслиgit branch -v | grep '[gone]'
работает для вас, пойти на это. Это кажется немного чище.Основанный на Git Tip: Удаление старых локальных веток , который похож на решение jason.rickman, я реализовал специальную команду для этой цели под названием git, используя Bash:
git gone -pn
объединяет обрезку и перечисление «пропавших» веток:Затем вы можете нажать на курок, используя
git gone -d
илиgit gone -D
.Ноты
"$BRANCH/.*: gone]"
где$BRANCH
обычно будетorigin
. Это, вероятно, не сработает, если ваш вывод Git локализован на французский и т. Д.источник
git gone
выглядит как псевдоним дляgit branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d
, который решает проблему ОП.Рисунок сильно от числа из других ответов здесь, я в конечном итоге со следующими (мерзавца 2,13 и выше только, я считаю), который должен работать на любой UNIX-подобные оболочки:
Это, в частности, использует
for-each-ref
вместоbranch
(какbranch
команда «фарфор», предназначенная для удобочитаемого вывода, а не для машинной обработки) и использует свой--shell
аргумент для получения правильно экранированного вывода (это позволяет нам не беспокоиться о каком-либо символе в имени ссылки).источник
[ ! -z "$ref" ]
значит. Я думаю, что мультилинер уже помог бы. Но все равно спасибо за ваш вклад!Еще один ответ, потому что ни одно из решений не отвечает моим потребностям в элегантности и кроссплатформенности:
Команда для удаления локальных веток не на удаленных:
Чтобы интегрировать его с gitconfig, чтобы его можно было запустить с
git branch-prune
:удар
PowerShell
(Нужна помощь в поиске универсальной команды для PowerShell и Bash)
Почему этот ответ самый лучший?
git branch-prune
команду в ваш мерзавецgit for-each-ref
--filter
без внешних зависимостей.Объяснение:
~\.gitconfig
. После выполнения этого вы можете просто сделатьgit branch-prune
--prune
флагом, который «удаляет удаленные ветви отслеживания больше не на удаленном»git for-each-ref
и--filter
, чтобы получить список филиалов[gone]
(без удаленного)источник
Я придумал этот скрипт bash. Она всегда держать ветви
develop
,qa
,master
.источник
Я использую короткий метод, чтобы сделать трюк, я рекомендую вам сделать то же самое, так как это может сэкономить несколько часов и дать вам больше видимости
Просто добавьте следующий фрагмент в ваш .bashrc (.bashprofile на macos).
Вам нужно отредактировать регулярное выражение grep, чтобы оно соответствовало вашим потребностям (здесь это предотвращает удаление master, preprod и dmz)
источник
git fetch --all --prune
сделал свое дело. Спасибо!Это сработало для меня:
источник
Я не уверен, как долго, но сейчас я использую git-up, который позаботится об этом.
я делаю
git up
и он начинает отслеживать новые ветви и удаляет старые.Просто чтобы прояснить, это не готовая команда git - https://github.com/aanand/git-up
Кстати, он также прячет грязное дерево и делает перебазировки еще только с
git up
.Надеюсь, это будет кому-то полезно
источник
Вот решение, которое я использую для раковины рыбы. Испытано на
Mac OS X 10.11.5
,fish 2.3.0
иgit 2.8.3
.Несколько заметок:
Убедитесь в правильности установки
base_branch
. В этом случае я используюdevelop
в качестве базовой ветви, но это может быть что угодно.Эта часть очень важна
grep -v "\(master\|$base_branch\|\*\)"
. Это гарантирует, что вы не удалите master или вашу базовую ветку.Я использую
git branch -d <branch>
в качестве дополнительной меры предосторожности, чтобы не удалять ветви, которые не были полностью объединены с вышестоящими или текущими заголовками.Простой способ испытания заменить
git branch -d $f
сecho "will delete $f"
.Я полагаю, я должен также добавить: ИСПОЛЬЗУЙТЕ НА СВОЙ СТРАХ И РИСК!
источник
Я написал скрипт Python, используя GitPython для удаления локальных веток, которые не существуют на удаленном компьютере.
Надеюсь, кто-то найдет это полезным, пожалуйста, добавьте комментарии, если я что-то пропустил.
источник
Если вы используете
zsh
оболочку сOh My Zsh
установленным, то самый простой способ сделать это безопасно - использовать встроенное автозаполнение.Сначала определите, какие ветви вы хотите удалить:
это покажет вам список уже слитых веток
После того, как вы знаете несколько, которые хотите удалить, введите:
Все, что вам нужно сделать, это нажать [tab], и он покажет вам список местных отделений. Используйте табуляцию или просто нажмите [tab] еще раз, и вы можете переключаться между ними, чтобы выбрать ветку с помощью [enter].
Вкладка Выберите ветки снова и снова, пока у вас не появится список ветвей, которые вы хотите удалить:
Теперь просто нажмите Enter, чтобы удалить свою коллекцию веток.
Если вы не используете zsh на своем терминале ... Получите это здесь.
источник
Мне нравится использовать каналы, потому что это облегчает чтение команды.
Это моё решение, если вы хотите удалить все ветки, кроме master.
Чтобы удалить другие ветви, которые соответствуют вашим критериям, измените первый и второй блок.
источник
Вот простой ответ, который работал для меня, используя клиент git:
Удалите хранилище полностью с вашего компьютера, а затем проверьте снова.
Никаких шуток с рискованными сценариями.
источник