Как я могу удалить все ветки Git, которые были объединены? - PullRequest
1655 голосов
/ 25 мая 2011

У меня много веток Git. Как удалить ветви, которые уже были объединены? Есть ли простой способ удалить их все вместо того, чтобы удалять их по одному?

Ответы [ 40 ]

2714 голосов
/ 25 мая 2011

ОБНОВЛЕНИЕ:

Вы можете добавить другие ветви для исключения, такие как master и dev, если ваш рабочий процесс имеет их в качестве возможного предка.Обычно я разветвляюсь от тега «sprint-start», а master, dev и qa не являются предками.

Сначала перечислите все ветви, которые были объединены в удаленном.

git branch --merged

Возможно, выувидеть несколько веток, которые вы не хотите удалять.мы можем добавить несколько аргументов, чтобы пропустить важные ветви, которые мы не хотим удалять, как master или development.Следующая команда пропустит основную ветку и все, что содержит dev.

git branch --merged| egrep -v "(^\*|master|dev)"

Если вы хотите пропустить, вы можете добавить ее в команду egrep, как показано ниже.Ветка skip_branch_name не будет удалена.

git branch --merged| egrep -v "(^\*|master|dev|skip_branch_name)"

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

git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d

Вы можете видеть, что master и dev исключены, если они являются предками.


Вы можете удалить объединенную локальную ветвь с помощью:

git branch -d branchname

Если она не объединена, используйте:

git branch -D branchname

Чтобы удалить ее с пульта встарые версии Git используют:

git push origin :branchname

В более поздних версиях Git используют:

git push --delete origin branchname

Как только вы удалите ветку с пульта, вы можете обрезать, чтобы избавиться от удаленного отслеживанияветви с:

git remote prune origin

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

git branch -dr branchname

Надеюсь, это поможет.

395 голосов
/ 09 августа 2013

Чтобы удалить все удаленные ветви, которые уже объединены:

git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin

В более свежих версиях Git

git branch -r --merged | grep -v master | sed 's/origin\///' | xargs -n 1 git push --delete origin
165 голосов
/ 18 февраля 2014

Просто немного расширив ответ Адама:

Добавьте это в свою конфигурацию Git, запустив git config -e --global

[alias]
    cleanup = "!git branch --merged | grep  -v '\\*\\|master\\|develop' | xargs -n 1 git branch -d"

И тогда вы можете удалить все локальные объединенные ветви, выполнив простое git cleanup.

79 голосов
/ 07 февраля 2013

Это также работает для удаления всех объединенных ветвей, кроме главной.

70 голосов
/ 03 июля 2014

Вы хотите исключить ветви master & develop из этих команд.

Local git clear:

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

Удаленный git clear:

git branch -r --merged | grep -v '\*\|master\|develop' | sed 's/origin\///' | xargs -n 1 git push --delete origin

Синхронизация локального реестра удаленных филиалов:

git fetch -p
43 голосов
/ 10 июня 2014

Для тех из вас, кто работает в Windows и предпочитает скрипты PowerShell, вот тот, который удаляет локальные объединенные ветви:

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}
27 голосов
/ 20 июля 2018

Я использовал ответ Адама уже много лет.Тем не менее, есть некоторые случаи, когда он не вел себя так, как я ожидал:

  1. ветви, которые содержали , слово "master" игнорировалось, например, "notmaster" или "masterful ", а не только основная ветвь
  2. ветви, которые содержали слово" dev ", игнорировались, например," dev-test ", а не только ветка dev
  3. удаление ветвей, которые доступны из HEAD текущей ветви (то есть не обязательно главной)
  4. в отдельном состоянии HEAD, удаление каждой ветви, достижимой изТекущий коммит

1 & 2 был прост для адресации с простым изменением в регулярном выражении.3 зависит от контекста того, что вы хотите (т.е. удаляете только те ветки, которые не были объединены в master или с вашей текущей веткой).4 может привести к катастрофическим последствиям (хотя их можно восстановить с помощью git reflog), если вы непреднамеренно запустили это в отключенном состоянии HEAD.

Наконец, я хотел, чтобы все это было в одной строке, которая не требовалаотдельный (Bash | Ruby | Python) сценарий.

TL; DR

Создание "развертки" псевдонима git, который принимает необязательный флаг -f:

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

и вызовите его с помощью:

git sweep

или:

git sweep -f

Длинный подробный ответ

Мне было проще всего создать пример git-репо с некоторымиветки и коммиты для проверки правильности поведения:

Создание нового репозитория git с одним коммитом

mkdir sweep-test && cd sweep-test && git init
echo "hello" > hello
git add . && git commit -am "initial commit"

Создание нескольких новых веток

git branch foo && git branch bar && git branch develop && git branch notmaster && git branch masterful
git branch --list
  bar
  develop
  foo
* master
  masterful
  notmaster

Желаемое поведение: выберите все объединенные ветви, кроме: master, development или current

Исходное регулярное выражение пропускает ветви "masterful" и "notmaster":

git checkout foo
git branch --merged | egrep -v "(^\*|master|dev)"
  bar

С обновленным регулярным выражением (которое теперь исключает "развернуть", а не "dev"):

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
bar
masterful
notmaster

Переключиться на ветку foo, сделать новый коммит, а затем оформить новую ветку foobar на основе foo:

echo "foo" > foo
git add . && git commit -am "foo"
git checkout -b foobar
echo "foobar" > foobar
git add . && git commit -am "foobar"

My currentветвь - это foobar, и если я перезапущу приведенную выше команду для вывода списка ветвей, которые я хочу удалить, ветка "foo" будет включена, даже если она не была объединена с master:

git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  masterful
  notmaster

Однако, если я запускаю ту же команду на master, ветка "foo" не включается:

git checkout master && git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

И это простопотому что git branch --merged по умолчанию - HEAD текущей ветви, если не указано иное.По крайней мере, для моего рабочего процесса я не хочу удалять локальные ветви, если они не были объединены с master, поэтому я предпочитаю следующий вариант:

git checkout foobar
git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

DetachedСостояние HEAD

Использование поведения по умолчанию git branch --merged имеет еще более существенные последствия в состоянии отключенного HEAD:

git checkout foobar
git checkout HEAD~0
git branch --merged | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  foo
  foobar
  masterful
  notmaster

Это приведет к удалениюВетка у меня была только на «foobar» вместе с «foo», что почти наверняка не желаемый результат.Однако с нашей измененной командой:

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)"
  bar
  masterful
  notmaster

Одна строка, включая фактическое удаление

git branch --merged $(git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" | xargs git branch -d

Все, свернутые в свиток git alias "":

git config --global alias.sweep '!git branch --merged $([[ $1 != "-f" ]] \
&& git rev-parse master) | egrep -v "(^\*|^\s*(master|develop)$)" \
| xargs git branch -d'

Псевдоним принимает необязательный флаг -f.Поведение по умолчанию заключается в удалении только тех веток, которые были объединены в мастер, но флаг -f удалит ветки, которые были объединены в текущую ветку.

git sweep
Deleted branch bar (was 9a56952).
Deleted branch masterful (was 9a56952).
Deleted branch notmaster (was 9a56952).
git sweep -f
Deleted branch foo (was 2cea1ab).
21 голосов
/ 04 февраля 2013

Git Sweep отлично справляется с этой задачей.

16 голосов
/ 14 сентября 2015

Использование Git версии 2.5.0:

git branch -d `git branch --merged`
13 голосов
/ 08 июля 2014

Вы можете добавить коммит к опции --merged.Таким образом, вы можете быть уверены, что удаляете только те ветви, которые объединены, то есть origin / master

Следующая команда удалит объединенные ветви из вашего источника.быть удален заменив git push origin --delete с echo

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
...