Удалить все локальные ветки Git


325

Я следую процессу разработки, где я создаю новую локальную ветвь для каждой новой функции или истории. По окончании я объединяю ветку с мастером и затем нажимаю.

Что происходит со временем из-за сочетания лени или забывчивости, так это то, что я получаю большой список локальных ветвей, некоторые из которых (например, шипы), возможно, не были объединены.

Я знаю, как составить список всех моих локальных веток, и я знаю, как удалить одну ветку, но мне было интересно, есть ли команда git, которая позволяет мне удалять все мои локальные ветви?

Ниже приведен вывод git branch --mergedкоманды.

user@machine:~/projects/application[master]$ git branch --merged
  STORY-123-Short-Description
  STORY-456-Another-Description
  STORY-789-Blah-Blah
* master

Все попытки удалить ветки, перечисленные с grep -v \*(согласно ответам ниже), приводят к ошибкам:

error: branch 'STORY-123-Short-Description' not found.
error: branch 'STORY-456-Another-Description' not found.
error: branch 'STORY-789-Blah-Blah' not found.

Я использую:
git 1.7.4.1
ubuntu 10.04
GNU bash, версия 4.1.5 (1) -релиз
GNU grep 2.5.4


7
Прошу вас принять ответ @ Andrew!
Роберт Симер


@GiulioCaccin Этот вопрос также относится к ветвям, которые, возможно, не были объединены, и я обновил вопрос, чтобы явно отразить это.
Louth

Ответы:


386

Подкоманда git branch -d может удалить более одной ветви. Итак, упростим ответ @ sblom, но добавим критический xargs:

git branch -D `git branch --merged | grep -v \* | xargs`

или, дополнительно упрощенный до:

git branch --merged | grep -v \* | xargs git branch -D 

Важно отметить, что, как отмечает @AndrewC, использование git branchсценариев не рекомендуется. Чтобы избежать этого, используйте что-то вроде:

git for-each-ref --format '%(refname:short)' refs/heads | grep -v master | xargs git branch -D

Осторожно при удалении!

$ mkdir br
$ cd br; git init
Initialized empty Git repository in /Users/ebg/test/br/.git/
$ touch README; git add README; git commit -m 'First commit'
[master (root-commit) 1d738b5] First commit
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README
$ git branch Story-123-a
$ git branch Story-123-b
$ git branch Story-123-c
$ git branch --merged
  Story-123-a
  Story-123-b
  Story-123-c
* master
$ git branch --merged | grep -v \* | xargs
Story-123-a Story-123-b Story-123-c
$ git branch --merged | grep -v \* | xargs git branch -D
Deleted branch Story-123-a (was 1d738b5).
Deleted branch Story-123-b (was 1d738b5).
Deleted branch Story-123-c (was 1d738b5).

Эта команда по-прежнему сообщает о тех же ошибках, что и упомянутые в комментариях к ответу ниже. error:branch 'STORY-123-Short-Description' not found.для каждой из перечисленных веток.
Louth

1
Работает для меня; см. выше с добавленными деталями.
GoZoner

1
Итак, с помощью git 1.7.10 вы решили свою проблему или предпочитаете работать непосредственно в репозитории .git?
GoZoner

1
Если вы получаете сообщение error:branch 'STORY-123-Short-Description' not found.об ошибке, возможно, это связано с настройками цвета git. Это сработало для меня (обратите внимание на --no-colorвариант):git branch --no-color --merged | grep -v \* | xargs git branch -D
Marcok

3
Единственный ответ на SO, который я нашел, что работает. Спасибо!
Кевин Саттл

140

Я нашел более хороший способ в комментарии по этому вопросу на GitHub :

git branch --merged master --no-color | grep -v master | grep -v stable | xargs git branch -d

редактировать: добавлена ​​опция без цвета и исключение стабильной ветви (добавьте другие ветви по мере необходимости в вашем случае)


2
Наконец, решение, в котором я нуждался
Code Whisperer,

1
Я пробовал это, но продолжаю получать error: branch 'my-branch-name' not found.для каждой ветви. Использование git версии 1.8.3.4 (Apple Git-47). Есть идеи почему?
Wheresrhys

try 'git branch - объединенный мастер | grep -v мастер | xargs echo 'для отладки, что именно он пытается удалить? нет лучших идей ...
mBardos

2
Так. git for-each-ref --format '%(refname:short)' refs/heads/ | grep -v master | xargs git branch -d
Павел Тявин

1
Изучил использование xargs вместе с этим. Спасибо
Volem

105

Анализ выходных данных git branchне рекомендуется и не является хорошим ответом для будущих читателей о переполнении стека.

  1. git branchэто то, что известно как команда фарфора. Команды фарфора не предназначены для синтаксического анализа, и выходные данные могут меняться в разных версиях Git.
  2. Существуют параметры конфигурации пользователя, которые изменяют вывод git branchтаким образом, который затрудняет анализ (например, цветность). Если пользователь установил, color.branchвы получите управляющие коды в выводе, это приведет к тому, error: branch 'foo' not found.что вы попытаетесь передать его в другую команду. Вы можете обойти это с --no-colorфлагомgit branch , но кто знает, какие другие пользовательские конфигурации могут сломать вещи.
  3. git branch может делать другие вещи, которые надоедают анализировать, например ставить звездочку рядом с проверенной веткой

Сопровождающим мерзавец это сказать о сценарии вокруг git branchвыхода

Чтобы узнать, какова текущая ветка, случайные / неосторожные пользователи могли писать сценарии вокруг git ветки, что неправильно. Мы активно противодействуем использованию в сценариях любой команды Porcelain, включая ветку git, поскольку выходные данные этой команды могут быть изменены, чтобы помочь случаю использования человеком.

Ответы, которые предполагают ручное редактирование файлов в .gitкаталоге (например, .git / refs /head), также проблематичны (вместо этого ссылки могут быть в .git / pack-refs, или Git может изменить свою внутреннюю разметку в будущем).

Git предоставляет for-each-refкоманду для получения списка ветвей.

Git 2.7.X представит эту --mergedопцию, чтобы вы могли сделать что-то вроде ниже, чтобы найти и удалить все ветви, объединенные вHEAD

for mergedBranch in $(git for-each-ref --format '%(refname:short)' --merged HEAD refs/heads/)
do
    git branch -d ${mergedBranch}
done

Git 2.6.X и старше, вам нужно будет перечислить все локальные ветви и затем проверить их по отдельности, чтобы увидеть, были ли они объединены (что будет значительно медленнее и немного сложнее).

for branch in $(git for-each-ref --format '%(refname:short)' refs/heads/)
do
    git merge-base --is-ancestor ${branch} HEAD && git branch -d ${branch}
done

git branch --no-color 2>/dev/null?
Нобар

5
Это улучшение наверняка. У вас всегда будет проблема необходимости отфильтровывать *, и это делает забавные вещи, если кто-то запускает его из отстраненной головы. Основная проблема, однако, git branchзаключается в команде фарфора, и нет никакой гарантии, что вывод не изменится в какой-то будущей версии git.
Андрей C

Спасибо @AndrewC - это как ответ на вопрос о таинственных ошибках "ветка не найдена", так и предоставление рабочего решения с использованием более подходящей команды! J
Джейсон

2
Как определяются команды GIT «Фарфор» и «Не Фарфор»?
GoZoner

1
Возможно, было бы полезным расширением, чтобы исключить «dev» и «master» по умолчанию?
PandaWood

66

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

git branch | grep -v "develop" | grep -v "master" | xargs git branch -D

очень полезно !


8
Вы возродили вековую старую ветку и опубликовали практически идентичный ответ на существующий, который содержит ошибки и пропускает изменения безопасности, которые у него были. Это не хороший ответ.
Андрей C

6
Этот ответ ясен в конвейерном выводе из ветви git, его изменении и передаче в ветку git -D. Не нужно быть злым.
Пэм

Это решение сработало для меня. Удалил все местные филиалы.
Прад

1
Это не удалит ни одну ветку, содержащую слово Develop или Master, например, «velop_feature »или« master_feature ».
Джанго

ЭТО ОТВЕТ, КОТОРЫЙ Я ИЩУ 👆🏻
Конрад Г.

62

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

for b in `git branch --merged | grep -v \*`; do git branch -D $b; done

Я бы рекомендовал изменения git branch -D $bк echo $bпервым несколько раз , чтобы убедиться , что она удаляет ветвь , которые вы собираетесь.


1
с помощью этой команды я понимаю, error:branch 'a_branch_name' not found.что вы пытаетесь сделать, и я играл с этой командой, но по какой-то причине git, похоже, не нравятся предоставленные имена веток ...
Louth

хммм. Чтобы помочь в устранении неполадок, было бы полезно увидеть пример выходных данныхgit branch --merged
sblom

мои названия ветвей имеют форматSTORY-123-Short-Description
Louth

и когда вы запускаете git branch --merged, вы получаете список с одним из них на каждой строке?
СБЛОМ

1
это буквально говорит error:branch 'a_branch_name' not found.? Или он жалуется на одно из названий веток из вашего git branchвывода выше?
СБЛОМ

52

Приведенная ниже команда удалит все локальные ветви, кроме главной ветви.

git branch | grep -v "master" | xargs git branch -D

Вышеуказанная команда

  1. перечислите все ветви
  2. Из списка проигнорируйте главную ветку и возьмите остальные ветви
  3. удалить ветку

4
Я бы использовал git branch | grep -v "master" | xargs git branch -dсначала, чтобы я не удалял неразбитые ветви, просто чтобы быть в безопасности. Но хороший ответ!
Джонас Ломхольдт

3
Вот версия ,@(git branch | Select-String -Pattern "[^(*?)\s? master]") | ForEach-Object{$_.Line.Trim()} | %{git branch -D $_}
PowerShell

1
@baklazan это будет работать только в командной строке Windows 10, если у вас установлены некоторые инструменты. У вас, вероятно, есть MINGW или что-то подобное, и вы этого не знаете.
KthProg

42

Просто замечание, я бы обновился до git 1.7.10. Вы можете получить ответы здесь, которые не будут работать на вашей версии. Я предполагаю, что вы должны префикс имени ветви с refs/heads/.

ВНИМАНИЕ, переходите к следующему, только если вы сделали копию своей рабочей папки и каталога .git.

Иногда я просто удаляю ветки, которые мне не нужны .git/refs/heads. Все эти ветви представляют собой текстовые файлы, содержащие 40 символов ша-1 коммита, на который они указывают. У вас будет посторонняя информация, .git/configесли для какого-либо из них было настроено специальное отслеживание. Вы также можете удалить эти записи вручную.


Наконец-то простой и прагматичный вариант. Мне это нравится: D
Melvyn

2
Это не будет работать, если у вас есть упакованные ссылки, или даже если вы иногда клонировали с удаленного сервера (который предоставит вам упакованные файлы). Если вы refs упакованы, то они не будут сохранены в .git / refs /head, они будут сохранены в файле с именем "pack-refs". Смотрите git-scm.com/docs/git-pack-refs .
Александр Берд

1
Кажется плохой идеей удалить ветку, которую вы проверили на данный момент
Моберг

@Moberg Просто зарегестрируй коммит заранее, и твоя отдельная ГЛАВА будет плавать нормально.
RomainValeri

34

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

git branch | grep -v "master" | xargs git branch -D

Объяснение:

  • 🛒 Получить все ветви с помощью git branch | grep -v "master"команды
  • 👇 Выберите каждую ветку с помощью xargsкоманды
  • Branch Удалить ветку с xargs git branch -D

3
Хотя это может быть правильный ответ. Одна строка кода не очень полезна без объяснения того, что и как решает исходный вопрос. Пожалуйста, подробно опишите свой ответ.
RyanNerd

28

Чтобы удалить все локальные ветки в Linux, кроме той, на которой вы находитесь

// hard delete

git branch -D $(git branch)

2
Это безопаснее, чем заходить в Git и убирать вещи.
Нельсонтруран

25

Мне было проще использовать текстовый редактор и оболочку.

  1. Введите git checkout <TAB>в оболочке. Покажут все местные филиалы.
  2. Скопируйте их в текстовый редактор, удалите те, которые вам нужно сохранить.
  3. Замените разрывы строк пробелами. (В SublimeText это очень просто.)
  4. Откройте оболочку, наберите git branch -D <PASTE THE BRANCHES NAMES HERE>.

Вот и все.


Я не думаю, что вы можете удалить ветку, на которой вы стоите.
Донг Тханг

@ Донг * Рядом с этой веткой есть *, так что вы просто удалите его из скопированного списка!
Мелани

12

У меня была похожая ситуация, и недавно я нашел следующую команду полезной.

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep>/) printf "%s", $0 }'`

Если вы хотите сохранить несколько веток, то

git branch -D `git branch | awk '{ if ($0 !~ /<Branch_You_Want_to_Keep1>|<Branch_You_Want_to_Keep2>/) printf "%s", $0 }'`

надеюсь, это поможет кому-то.


1
Хороший, но мне нужны были кавычки, чтобы заставить его работать - На git branch -D `git branch | awk '{ if ($0 !~ /master/) printf "%s", $0 }'` самом деле, я думаю, что они у вас были изначально, но они потерялись в SO форматировании.
Тассинари

10

Из командной строки Windows удалите все, кроме текущей извлеченной ветви, используя:

for /f "tokens=*" %f in ('git branch ^| find /v "*"') do git branch -D %f

7

Если вам не нужен сам Git, вы также можете удалить заголовки в .git / refs /head вручную или программно. Следующее должно работать с минимальной настройкой под Bash:

shopt -s extglob
rm -rf .git/refs/heads/!(master)

Это удалит все локальные ветви, кроме вашей основной ветви. Так как ваши ветки upstream хранятся в .git / refs / remotes , они останутся нетронутыми.

Если вы не используете Bash или хотите использовать сразу несколько Git-репозиториев, вы можете сделать что-то похожее с GNU find:

find . \
    -path remotes -path logs -prune -o \
    -wholename \*.git/refs/heads/\* \! -name master -print0 |
xargs -0 rm -rf

Решение find, вероятно, более переносимо, но обрезка путей и имен файлов сложна и потенциально более подвержена ошибкам.


Прохладно. Визуальное удаление :)
сандал

5

Ни один из ответов полностью не удовлетворил мои потребности, так что здесь мы идем:

git branch --merged | grep -E "(feature|bugfix|hotfix)/" | xargs git branch -D && git remote prune origin

Это удалит все локальные ветви, которые объединены и начинаются с feature/, bugfix/или hotfix/. После этого пульт дистанционного управленияorigin (возможно, вам придется ввести пароль).

Работает на Git 1.9.5.


5

Основываясь на комбинации нескольких ответов здесь - если вы хотите сохранить все ветки, которые существуют на удаленном компьютере, но удалить остальные , следующий oneliner сделает свое дело:

git for-each-ref --format '%(refname:short)' refs/heads | grep -Ev `git ls-remote --quiet --heads origin | awk '{print substr($2, 12)}'| paste -sd "|" -` | xargs git branch -D

3

Хотя это не решение для командной строки, я удивлен, что Git GUI еще не предлагался.

Я использую командную строку в 99% случаев, но в этом случае это либо слишком медленно (отсюда исходный вопрос), либо вы не знаете, что собираетесь удалить, прибегая к длительным, но умным манипуляциям с оболочкой.

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

В пользовательском интерфейсе перейдите в « Ветвь» -> «Удалить» и нажмите Ctrl + клик по веткам, которые вы хотите удалить, чтобы они были выделены. Если вы хотите убедиться, что они объединены в ветвь (например, dev), в разделе « Только удаление», если «Объединить в» установите « Локальная ветвь» в dev. В противном случае установите значение Всегда, чтобы игнорировать эту проверку.

GitUI: удалить локальные филиалы


1

Для powershell это будет работать:

git branch --format '%(refname:lstrip=2)' --merged `
    | Where-Object { $_ -ne 'master' } `
    | ForEach-Object { git branch -d $_ }

0

Следующий скрипт удаляет ветки. Используйте его и модифицируйте на свой страх и риск и т. Д.

Основываясь на других ответах в этом вопросе, я написал для себя быстрый скрипт bash. Я назвал его «gitbd» (git branch -D), но если вы используете его, вы можете переименовать его так, как вам хочется.

gitbd() {
if [ $# -le 1 ]
  then
    local branches_to_delete=`git for-each-ref --format '%(refname:short)' refs/heads/ | grep "$1"`
    printf "Matching branches:\n\n$branches_to_delete\n\nDelete? [Y/n] "
    read -n 1 -r # Immediately continue after getting 1 keypress
    echo # Move to a new line
    if [[ ! $REPLY == 'N' && ! $REPLY == 'n' ]]
      then
        echo $branches_to_delete | xargs git branch -D
    fi
else
  echo "This command takes one arg (match pattern) or no args (match all)"
fi
}

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

Это немного глупо - если нет веток, соответствующих шаблону, он не осознает этого.

Пример выходного прогона:

$ gitbd test
Matching branches:

dummy+test1
dummy+test2
dummy+test3

Delete? [Y/n] 

0

Я написал сценарий оболочки, чтобы удалить все локальные ветви, кроме develop

branches=$(git branch | tr -d " *")
output=""
for branch in $branches 
do
  if [[ $branch != "develop" ]]; then
    output="$output $branch"
  fi
done
git branch -d $output

0

Над ответами работает отлично. Вот другой подход, когда у нас много веток в локальном репо, и нам нужно удалить много веток, кроме тех, которые лежат на локальной машине.

Сначала git branchперечислим все местные филиалы.

Чтобы преобразовать столбец с именами ветвей в одну строку в файле, запустите команду unix.
git branch > sample.txt
Это сохранит его в файле sample.txt . И беги
awk 'BEGIN { ORS = " " } { print }' sample.txt
команду в оболочке. Это преобразует столбец в строку и копирует список названий ветвей в одну строку.

А потом беги
git branch -D branch_name(s).
Это удалит все перечисленные ветви, присутствующие в локальном


0

Самый прагматичный способ: убедитесь, что у вас нет незафиксированной работы master, выполните коммит / push, если необходимо, клонируйте свежую копию хранилища и удалите старую.


0

Для этого вы можете использовать git-extras

$ git delete-merged-branches
Deleted feature/themes (was c029ab3).
Deleted feature/live_preview (was a81b002).
Deleted feature/dashboard (was 923befa).

0

У меня нет grep или другого unix на моем компьютере, но это работает с терминала VSCode:

git branch -d $(git branch).trim()

Я использую строчную букву d, чтобы она не удаляла неразделенные ветви.

Я также был на мастере, когда сделал это, поэтому * masterне существует, поэтому он не пытался удалить мастер.


Подтверждено: если masterэта команда не включена, эта команда БУДЕТ удалена master.
Бретт Роуберри

-1

Убедитесь, что вы делаете это первым

git fetch

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

 git branch -a | grep -v "master" | grep remotes | sed 's/remotes\/origin\///g' | xargs git push origin --delete
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.