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

1936

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

Nyambaa
источник
46
Чтобы быть более конкретным, git branch -Dудаляет любую ветку, независимо от того, была ли она объединена или нет.
PhilT
12
Вы также можете сделать это прямо из GitHub, если зайдете в раздел «ветки» своего репо (например, github.com/<username>/<repo_name>/branches ). Должен быть список всех ваших веток с красным значком мусорной корзины на стороне, которая удалит выбранную ветку. Гораздо быстрее, чем делать это в терминале! Также покажет, как далеко впереди / позади masterкаждой ветви. Тем не менее, ваш локальный клиент будет по-прежнему перечислять старые ветви, если вы запустите git branch -a; используйте, git fetch --pruneчтобы удалить их (согласно этому ответу ).
user5359531
3
Сценарий для этого локально или удаленно - с проверками безопасности и предварительно настроенными «безопасными ветвями»: github.com/fatso83/dotfiles/tree/master/utils/… git delete-merged --doit origin илиgit delete-merged --doit --local
oligofren
Вы также можете использовать это приложение для автоматического удаления объединенных ветвей.
Sebass van Boxel
rm -fr work && git clone http://example.com/work.gitс годами стал самый простой способ выбраться из маринада с мерзавцем.
Reactgular

Ответы:

3118

ОБНОВИТЬ:

Вы можете добавить другие ветви для исключения, такие как 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 push --delete origin branchname

git push origin :branchname    # for really old git

После того как вы удалите ветку с пульта, вы можете удалить ветки удаленного отслеживания с помощью:

git remote prune origin

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

git branch -dr branchname

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

Адам Димитрук
источник
46
ВНИМАНИЕ: Если вы только что создали ветку, она также будет удалена. Убедитесь, что в списке нет только что созданной ветви, прежде чем запускать самую верхнюю команду.
Гэри Харан
154
ПРОТИВОПОКАЗАНИЕ: reflog спасет ваш бекон. Так что не волнуйся.
Адам Димитрук
33
Имейте в виду, что первая команда удаляет только локальные ветви, поэтому она не так «опасна», как указывали некоторые.
ifightcrime
79
Вариант PowerShell, чтобы я мог найти его здесь в следующий раз, когда я погуглил ответ:git branch --merged | %{$_.trim()} | ?{$_ -notmatch 'develop' -and $_ -notmatch 'master'} | %{git branch -d $_}
vorou
23
Это приводит к ошибке, fatal: branch name requiredесли у вас нет веток, которые должны быть удалены. Чтобы избежать этого, вы можете перейти -rк нему, xargsчтобы он не работал, git branch -dесли стандартный ввод пуст. (Это расширение GNU xargs, согласно man-странице).
Мариус Гедминас
457

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

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

ОБНОВЛЕНИЕ (от @oliver; поскольку не помещается в комментарии, но уже содержит достаточно ответов) : если вы находитесь в ветви ABC, то в результатах появится ABC, git branch -r --mergedпотому что ветка не указана, поэтому ветвь по умолчанию имеет текущую ветвь и ветвь всегда квалифицируется как объединенный с самим собой (поскольку нет различий между ветвью и самим собой!).

Так что либо укажите ветку:

git branch -r --merged master | grep -v master ...

ИЛИ первый мастер проверки:

git checkout master | git branch -r --merged | grep -v ...
kuboon
источник
18
Лучший ответ на сегодняшний день. Просто обратите внимание, моя главная ветка названа, devпоэтому мне пришлось это изменить
Дориан,
41
Я должен был добавить | grep originпосле, grep -v masterчтобы предотвратить подталкивание веток других пультов к источнику. Настоятельно рекомендуем предварительно проверить вывод, используяgit branch -r --merged | grep -v master | grep origin | sed 's/origin\//:/' | xargs -n 1 echo
L0LN1NJ4
9
Я немного изменил, чтобы исключить developветку. git branch -r --merged | grep -v master | grep -v develop | sed 's/origin\///' | xargs -n 1 git push --delete origin, Теперь это оказался мой псевдоним.
сарат
8
То, что сделало это лучшим ответом, который я когда-либо читал, - это -rаргумент, который я не видел нигде. Считается само собой разумеющимся, что только местные филиалы стоят того, чтобы заниматься уборкой. Но пульты тоже полны мусора.
Асбьёрн Ульсберг,
19
Осторожно - только что понял: это, очевидно, найдет ветви, объединенные с текущей веткой , а не с основной, так что если вы на myFeatureBranchней, то сотрете origin/myFeatureBranch. Наверное, лучше git checkout masterсначала.
jakub.g
190

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

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

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

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

real_ate
источник
11
не должна ли быть первая команда: git branch --merged masterтак как вы хотите посмотреть, что было объединено с главной, а не проверенной веткой?
Джо Филлипс
@JoePhilllips У некоторых людей основная ветвь не master, а вместо этого developили, devи в этом случае команда потерпит неудачу fatal: malformed object name, лучше иметь универсальную команду, и вы несете ответственность за ее запуск
Smohamed
1
@JoePhilllips смысл этого ответа состоит в том, чтобы упаковать ответ Адама (главный ответ на этот вопрос) в полезный псевдоним git. В ответе Адама нет того, что вы предлагаете, и так много людей сочли это полезным, поэтому я бы не стал менять свое. Я бы порекомендовал
начать
13
Добавление -rк xargsпредотвратит ненужные ошибки ( branch name required) при многократном запуске этого псевдонима или при отсутствии ветви, подлежащей удалению. Мой псевдоним выглядит так:cleanup = "!git branch --merged | grep -v -P '^\\*|master|develop' | xargs -n1 -r git branch -d"
spezifanta
1
Текущая команда не отфильтровывает основную и развивающую ветви
Андрей Ф.
83

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

git branch --merged | grep -v '^* master$' | grep -v '^  master$' | xargs git branch -d
Исмаэль Абреу
источник
3
Теперь он не удалит ни одну ветку с masterним. Попробуйте grep -v ^master$для середины.
wchargin
Я бы также позволил | grep -v '^\*'избежать удаления текущей ветки, если вы не на master
svassr
5
Это здорово, спасибо! Одно предостережение для тех, кто использует это: обратите внимание, что есть два пробела в grep -v '^ master$'. Если вы введете его в себя и пропустите один, вы удалите его, masterесли его нет.
Styger
3
@ Mr.Polywhirl Ваша правка нарушает команду, и вы должны отменить ее. Два пробела необходимы, так git branchкак каждое ветвь будет перечисляться в новой строке с двумя пробелами слева, если это не текущая извлеченная ветвь. Вы по сути гарантировали, что любой, кто запускает эту команду, удалит свою основную ветвь, если только она не является в настоящий момент извлеченной веткой.
Styger
79

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

Локальный мерзавец ясно:

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
Гидо Боуман
источник
3
+1 также для удаленной версии (но менее необходимой, поскольку у нас есть удаленный --prune). Также стоит отметить, что Thoose не будет работать со старой версией git
malko
4
git config --global --add fetch.prune trueавтоматически обрезать при извлечении или извлечении.
T3rm1
1
Имейте в виду, чернослив не то же самое, что удаленный очистить. Удаленная очистка фактически удаляет удаленные ветви, которые полностью объединены с вашей текущей веткой. Prune очищает только локальный реестр удаленных веток, которые уже удалены.
Гвидо Боуман
Слово полностью вводит в заблуждение, так как ветвь будет считаться объединенной, когда она была объединена ранее, но после объединения будут новые коммиты, которые не были объединены.
булочки
Чтобы удалить все git branch -r --merged | grep -v '\*\|master\|develop' | grep '^\s*origin/' | sed 's/origin\///' | tr "\n" " " | xargs git push --delete origin
исходные
48

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

function Remove-MergedBranches
{
  git branch --merged |
    ForEach-Object { $_.Trim() } |
    Where-Object {$_ -NotMatch "^\*"} |
    Where-Object {-not ( $_ -Like "*master" )} |
    ForEach-Object { git branch -d $_ }
}
Клас Меллборн
источник
13
Ради любопытства, это может быть сокращено до git branch --merged | ?{-not ($_ -like "*master")} | %{git branch -d $_.trim()}
Иэн Баллард
5
@IainBallard Конечно, я мог бы использовать псевдонимы. Это не рекомендуется, когда вы хотите максимизировать читабельность. github.com/darkoperator/PSStyleGuide/blob/master/English.md
Клас Мельбурн
1
конечно. Я нашел ваш ответ очень полезным :-) Однако иногда длинный синтаксис PowerShell мешает тому, что происходит в блоках. Но прежде всего я выдвигал что-то, что вы могли бы скопировать / вставить или напечатать как разовое. Еще раз спасибо.
Иан Баллард
4
Вот однострочная оболочка для Windows cmd, которая сохраняет master и вашу текущую ветку: for /f "usebackq" %B in (``git branch --merged^|findstr /v /c:"* " /c:"master"``) do @git branch -d %B(вздох, замените двойные
yoyo
42

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

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

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

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

TL; DR

Создайте псевдоним git «sweep», который принимает необязательный -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 repo с некоторыми ветками и коммитами для проверки правильности поведения:

Создать новый репозиторий 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"

Моя текущая ветка - это 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умолчанию используется заголовок текущей ветви, если не указано иное. По крайней мере, для моего рабочего процесса я не хочу удалять локальные ветви, если они не были объединены с master, поэтому я предпочитаю следующий вариант:

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

Отделенное состояние 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 "sweep":

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).
вихри
источник
Зачем вам нужно создать функцию? Разве не git configатомно?
Василий Новиков
Для того, чтобы иметь дело с ТИнструкция -f 'аргумент (если я правильно понимаю ваш вопрос)
завихрения
1
но как это поможет? Я имею в виду начало выражения !f(){ git branch .... Это объявление функции, верно? Почему бы не начать прямо с git branch ...?
Василий Новиков
1
Ты абсолютно прав. Отредактировал мой ответ соответственно. Спасибо за указатель!
вихри
Разве следующее не сделало бы то же самое, что и режим без применения силы? git checkout master && git branch -d `git branch --merged` && git checkout - За исключением того, что он будет удалять develop, но может быть более простой подход.
Гвидо Буман
18

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

git branch -d `git branch --merged`
drautb
источник
16
Это может удалить masterветку кстати!
Wazery
4
Правда. Я использую его только тогда, когда я уверен, что я включен master.
drautb
11
git branch -d $(git branch --merged | grep -v master)
alexg
1
Это опасно, если у вас есть поток, представьте, что у вас есть мастер <- stage <- dev. По-прежнему самое простое решение
Иосиф Бриггс
14

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

Следующая команда удалит объединенные ветви из вашего источника.

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

Вы можете проверить, какие ветви будут удалены, заменив git push origin --delete на echo

git branch -r --merged origin/master | grep -v "^.*master" | sed s:origin/:: |xargs -n 1 echo
Йорн Реймердес
источник
2
Мне нравится тестовый вариант
iwein
12

Я использую следующий скрипт Ruby для удаления уже слитых локальных и удаленных веток. Если я делаю это для репозитория с несколькими пультами и хочу удалить только с одного, я просто добавляю оператор выбора в список удаленных, чтобы получить только те пульты, которые мне нужны.

#!/usr/bin/env ruby

current_branch = `git symbolic-ref --short HEAD`.chomp
if current_branch != "master"
  if $?.exitstatus == 0
    puts "WARNING: You are on branch #{current_branch}, NOT master."
  else
    puts "WARNING: You are not on a branch"
  end
  puts
end

puts "Fetching merged branches..."
remote_branches= `git branch -r --merged`.
  split("\n").
  map(&:strip).
  reject {|b| b =~ /\/(#{current_branch}|master)/}

local_branches= `git branch --merged`.
  gsub(/^\* /, '').
  split("\n").
  map(&:strip).
  reject {|b| b =~ /(#{current_branch}|master)/}

if remote_branches.empty? && local_branches.empty?
  puts "No existing branches have been merged into #{current_branch}."
else
  puts "This will remove the following branches:"
  puts remote_branches.join("\n")
  puts local_branches.join("\n")
  puts "Proceed?"
  if gets =~ /^y/i
    remote_branches.each do |b|
      remote, branch = b.split(/\//)
      `git push #{remote} :#{branch}`
    end

    # Remove local branches
    `git branch -d #{local_branches.join(' ')}`
  else
    puts "No branches removed."
  end
end
mmrobins
источник
Не возражаете, если я украду этот кусок для маленькой библиотеки git helper? github.com/yupiq/git-branch-util
logan
1
Пойдите для этого, я не поместил бы это здесь, если бы заботился о людях, повторно использующих код некоторым образом
mmrobins
@mmrobins У вас есть дополнительный \/в начале оператора отклонения для remote_branchesстроки. Это опечатка или она служит цели?
Джаввад
@mmrobins, о, неважно, b.split(/\//)теперь я вижу черту
Jawwad
Если вы хотите сделать это в основном, но с помощью vanilla bash, а не ruby: stackoverflow.com/a/37999948/430128
Раман,
11

Как удалить объединенные ветви в консоли PowerShell

git branch --merged | %{git branch -d $_.Trim()}

Если вы хотите исключить master или любые другие имена веток, вы можете передать с помощью PowerShell Select-String, как это, и передать результат git branch -d:

git branch -d $(git branch --merged | Select-String -NotMatch "master" | %{$_.ToString().Trim()})
Константин Таркус
источник
1
Более высокие ответы предлагают фильтрацию мастера или других веток. Для тех, кто хочет сделать это в powershell: git branch --merged | findstr / v "мастер" | % {git branch -d $ _. trim ()}
Тредзко
@tredzko Хорошая мысль. FTR более высокий ответ - stackoverflow.com/questions/6127328/… - вы можете опубликовать свой комментарий со
ссылкой,
он также пытается удалить * master:)
iesen
9

В ответе kuboon пропущено удаление веток, в названии которых есть слово master. Следующий ответ улучшает его ответ:

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

Конечно, это не удаляет саму "главную" ветку :)

Paras
источник
8

В Git нет команды, которая сделает это автоматически. Но вы можете написать скрипт, который использует команды Git, чтобы дать вам то, что вам нужно. Это можно сделать разными способами в зависимости от используемой модели ветвления.

Если вам нужно знать, была ли ветка объединена с главной, следующая команда не выдаст выходных данных, если myTopicBranch был объединен (то есть вы можете удалить ее)

$ git rev-list master | grep $(git rev-parse myTopicBranch)

Вы можете использовать команду ветки Git, проанализировать все ветви в Bash и выполнить forцикл по всем веткам. В этом цикле вы проверяете вышеуказанной командой, можете ли вы удалить ветку или нет.

ralphtheninja
источник
7

Примечание : меня не устраивают предыдущие ответы (не работает на всех системах, не работает на удаленном компьютере, не указывает ветку --merged, не выполняется точная фильтрация). Итак, я добавляю свой ответ.

Есть два основных случая:

Местный

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

git branch --format "%(refname:short)" --merged master | grep -E -v '^master$|^feature/develop$' | xargs -n 1 git branch -d

Примечания :

  • git branch output --format «..» - убрать пробелы и разрешить точное соответствие grep
  • grep -E используется вместо egrep , поэтому он работает и в системах без egrep (то есть: git для windows).
  • grep -E -v '^master$|^feature/develop$' это указать локальные ветви, которые я не хочу удалять
  • xargs -n 1 git branch -d: выполнить удаление локальных веток (для удаленных не будет)
  • Конечно, вы получите сообщение об ошибке, если попытаетесь удалить ветку, которая в данный момент выписана. Итак, предлагаю заранее перейти на мастер.

Дистанционный пульт

Вы хотите удалить удаленные ветви , которые уже объединены с другой удаленной веткой . Во время удаления вы хотите сохранить некоторые важные ветки, такие как HEAD, master, релизы и т. Д.

git branch -r --format "%(refname:short)" --merged origin/master | grep -E -v '^*HEAD$|^*/master$|^*release' | cut -d/ -f2- | xargs -n 1 git push --delete origin

Ноты :

  • для удаленного мы используем -rопцию и предоставляем полное имя ветви :origin/master
  • grep -E -v '^*HEAD$|^*/master$|^*release' должен соответствовать удаленным ветвям, которые мы не хотим удалять.
  • cut -d/ -f2-: удалите ненужный префикс origin /, который в противном случае выводится git branchкомандой.
  • xargs -n 1 git push --delete origin : выполнить удаление удаленных веток.
psuzzi
источник
7

Если вы работаете в Windows, вы можете использовать Windows Powershell или Powershell 7 с Out-GridView, чтобы получить хороший список ветвей и выбрать мышью, какую из них вы хотите удалить:

git branch --format "%(refname:short)" --merged  | Out-GridView -PassThru | % { git branch -d $_ }

введите описание изображения здесь после нажатия OK Powershell передаст имена этих веток git branch -dкоманде и удалит их введите описание изображения здесь

Мариуш Павельски
источник
6

Вы можете использовать git-del-br инструмент .

git-del-br -a

Вы можете установить его с pipпомощью

pip install git-del-br

PS: я автор инструмента. Любые предложения / отзывы приветствуются.

tusharmakkar08
источник
1
@ stackoverflow.com/users/100297/martijn-pieters : Почему этот ответ был удален и лишен права голоса?
tusharmakkar08
1
Ваш ответ и инструмент не работают. Я провожу пару часов на этом. Ничего.
SpoiledTechie.com
@ SpoiledTechie.com: Можете ли вы сказать мне, с какой именно проблемой вы сталкиваетесь? Я использую это на регулярной основе.
tusharmakkar08
Я могу поделиться скриншотом, если вы хотите отключить это? Испорченные в этой вещи Google Mail. :)
SpoiledTechie.com
5

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

git branch --merged | grep -v \* | grep -v '^\s*master$' | xargs -t -n 1 git branch -d

Эта команда не повлияет на вашу текущую ветку или вашу основную ветку. Он также скажет вам, что он делает, прежде чем это сделать, используя флаг -t xargs.

chrismendis
источник
5

Я использую схему именования git-flow esque, поэтому она работает для меня очень безопасно:

git branch --merged | grep -e "^\s\+\(fix\|feature\)/" | xargs git branch -d

Он в основном ищет объединенные коммиты, которые начинаются со строки fix/или feature/.

Чад М
источник
4

Попробуйте следующую команду:

git branch -d $(git branch --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

С помощью git rev-parseполучит текущее название ветки , чтобы исключить его. Если вы получили ошибку, это означает, что нет локальных веток для удаления.

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

git push origin -vd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD) | cut -d/ -f2)

Если у вас несколько пультов, добавьте grep origin |перед, cutчтобы отфильтровать только origin.

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

git branch -rd $(git branch -r --merged | grep -vw $(git rev-parse --abbrev-ref HEAD))

Затем git fetchснова пульт и используйте предыдущийgit push -vd команду.

Если вы часто используете его, рассмотрите возможность добавления псевдонимов в свой ~/.gitconfig файл.

Если вы удалили несколько веток по ошибке, используйте, git reflogчтобы найти потерянные коммиты.

kenorb
источник
4

Основываясь на некоторых из этих ответов, я сделал свой собственный скрипт Bash, чтобы сделать это тоже !

Он использует git branch --mergedи git branch -dдля удаления слитых ветвей и запрашивает каждую ветку перед удалением.

merged_branches(){
  local current_branch=$(git rev-parse --abbrev-ref HEAD)
  for branch in $(git branch --merged | cut -c3-)
    do
      echo "Branch $branch is already merged into $current_branch."
      echo "Would you like to delete it? [Y]es/[N]o "
      read REPLY
      if [[ $REPLY =~ ^[Yy] ]]; then
        git branch -d $branch
      fi
  done
}
earlonrails
источник
4

Ниже запрос работает для меня

for branch in  `git branch -r --merged | grep -v '\*\|master\|develop'|awk 'NR > 0 {print$1}'|awk '{gsub(/origin\//, "")}1'`;do git push origin --delete $branch; done

и это отфильтрует любую ветвь в трубе grep.

Хорошо работает с http-клоном, но не очень хорошо для ssh-соединения.

user1460965
источник
4

По состоянию на 2018.07

Добавьте это в [alias]раздел вашего ~/.gitconfig:

sweep = !"f() { git branch --merged | egrep -v \"(^\\*|master|dev)\" || true | xargs git branch -d; }; f"

Теперь вы можете просто позвонить, git sweepчтобы выполнить необходимую очистку.

Сорин
источник
Для меня вызов git sweep перечисляет только те ветви, которые нужно очистить, но не удаляет их
Виктор Мораес
4

В Windows с установленным git bash egrep -v работать не будет

git branch --merged | grep -E -v "(master|test|dev)" | xargs git branch -d

где grep -E -vэквивалентноegrep -v

Используйте -dдля удаления уже слитых веток или -Dдля удаления не слитых веток

DevWL
источник
egrep -v у меня работает. Я использую gitbash из установщика gitextensions, хотя
Джо Филлипс
4

Я использовал следующий метод, чтобы удалить объединенные локальные и удаленные ветви в одном cmd.

У меня есть следующее в моем bashrcфайле:

function rmb {
  current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
  if [ "$current_branch" != "master" ]; then
    echo "WARNING: You are on branch $current_branch, NOT master."
  fi
  echo "Fetching merged branches..."
  git remote prune origin
  remote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")
  local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")
  if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
    echo "No existing branches have been merged into $current_branch."
  else
    echo "This will remove the following branches:"
    if [ -n "$remote_branches" ]; then
      echo "$remote_branches"
    fi
    if [ -n "$local_branches" ]; then
      echo "$local_branches"
    fi
    read -p "Continue? (y/n): " -n 1 choice
    echo
    if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
      # Remove remote branches
      git push origin `git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$" | sed 's/origin\//:/g' | tr -d '\n'`
      # Remove local branches
      git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
    else
      echo "No branches removed."
    fi
  fi
}

Оригинальный источник

Это не удаляет основную ветку, но удаляет объединенные локальные и удаленные ветви . Когда у вас есть это в вашем файле rc, просто запустите rmb, вам будет показан список объединенных ветвей, которые будут очищены, и будет запрошено подтверждение действия. Вы можете изменить код так, чтобы он не запрашивал подтверждения, но, вероятно, его стоит сохранить.

Prashant
источник
3

Напишите скрипт, в котором Git проверяет все ветви, которые были объединены с master.

Тогда делай git checkout master.

Наконец, удалите объединенные ветви.

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git checkout $branchnew
done

git checkout master

for k in $(git branch -ra --merged | egrep -v "(^\*|master)"); do
  branchnew=$(echo $k | sed -e "s/origin\///" | sed -e "s/remotes\///")
  echo branch-name: $branchnew
  git push origin --delete $branchnew
done
KOMU
источник
3

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

Если вы посмотрите на вывод, вы увидите что-то вроде

$ git branch --merged master -v
  api_doc                  3a05427 [gone] Start of describing the Java API
  bla                      52e080a Update wording.
  branch-1.0               32f1a72 [maven-release-plugin] prepare release 1.0.1
  initial_proposal         6e59fb0 [gone] Original proposal, converted to AsciiDoc.
  issue_248                be2ba3c Skip unit-for-type checking. This needs more work. (#254)
  master                   be2ba3c Skip unit-for-type checking. This needs more work. (#254)

Ветви blaи issue_248являются локальными ветвями, которые будут удалены без уведомления.

Но вы также можете увидеть слово [gone], которое указывает на ветви, которые были перенесены на удаленный (который теперь исчез) и, следовательно, обозначает, что ветви могут быть удалены.

Исходный ответ, таким образом, может быть изменен на (разделить на многострочный для более короткой строки)

git branch --merged master -v | \
     grep  "\\[gone\\]" | \
     sed -e 's/^..//' -e 's/\S* .*//' | \
      xargs git branch -d

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

Хайко Рупп
источник
3

Для меня git branch --mergedне показывает ветки, которые были объединены через GitHub PR. Я не уверен в причинах, но я использую следующую строку, чтобы удалить все локальные ветви, у которых нет удаленной ветви отслеживания :

diff <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | grep '<' | cut -c 3- | xargs git branch -D

Объяснение:

  • git branch --format "%(refname:short)" дает список местных филиалов
  • git branch -r | grep -v HEAD | cut -d/ -f2- выдает список удаленных веток, отфильтровывая HEAD
  • diff <(...) <(...) дает разницу вывода двух команд в скобках
  • grep '<' фильтрует ветки, которые существуют в первом списке, но не во втором
  • cut -c 3- дает строку, начинающуюся с 3-го символа, таким образом удаляя префикс <
  • xargs git branch -Dвыполняется git branch -Dпротив каждого имени ветви

В качестве альтернативы, вы можете избежать grep -v '<'так:

diff --old-line-format="%L" --new-line-format="" --unchanged-line-format="" <(git branch --format "%(refname:short)") <(git branch -r | grep -v HEAD | cut -d/ -f2-) | xargs git branch -D
Folex
источник