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

202

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

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

Я знаю, как перечислять все мои локальные ветки, и я знаю, как удалить одну ветку, но мне было интересно, есть ли команда 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) -release
GNU grep 2.5.4

Показать ещё 2 комментария
Теги:
grep
version-control

15 ответов

34
Лучший ответ

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

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

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

  • 0
    Наконец-то простой и прагматичный вариант. Мне нравится: D
  • 2
    Это не будет работать, если у вас есть упакованные ссылки, или даже если вы иногда клонировали с удаленного сервера (который предоставит вам упакованные файлы). Если ваши refs упакованы, то они не будут сохранены в .git / refs /head, они будут сохранены в файле с именем "pack-refs". Смотрите git-scm.com/docs/git-pack-refs .
Показать ещё 3 комментария
262

Подкоманда '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).
  • 0
    Эта команда по-прежнему сообщает о тех же ошибках, что и упомянутые в комментариях к ответу ниже. error:branch 'STORY-123-Short-Description' not found. для каждой из перечисленных веток.
  • 0
    Работает для меня; см. выше с добавленными деталями.
Показать ещё 6 комментариев
120

Я нашел более приятный способ в комментарии по этой проблеме в github:

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

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

  • 0
    Наконец, решение, которое мне было нужно
  • 1
    Я пробовал это, но продолжаю получать error: branch 'my-branch-name' not found. для каждой отрасли. Использование git версии 1.8.3.4 (Apple Git-47). Есть идеи почему?
Показать ещё 5 комментариев
61

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

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

должен сказать о сценариях вокруг git branch output

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

Ответы, предлагающие вручную редактировать файлы в каталоге .git (например,.git/refs/heads), также проблематичны (refs могут быть в .git/упакованные-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
  • 0
    git branch --no-color 2>/dev/null ?
  • 5
    Это улучшение наверняка. У вас всегда будет проблема необходимости отфильтровывать *, и это делает забавные вещи, если кто-то запускает его из отстраненной головы. Основная проблема, однако, заключается в том, что git branch - это фарфоровая команда, и нет никакой гарантии, что выходные данные не изменятся в какой-либо будущей версии git.
Показать ещё 6 комментариев
40

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

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, похоже, не нравятся предоставленные имена веток ...
  • 0
    хммм. чтобы помочь в устранении неполадок, было бы полезно увидеть некоторые примеры выходных данных из git branch --merged
Показать ещё 5 комментариев
32

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

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

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

  • 5
    Вы возродили вековую старую ветку и опубликовали практически идентичный ответ на существующий, который содержит ошибки и пропускает изменения безопасности, которые у него были. Это не очень хороший ответ.
  • 5
    Этот ответ ясен в конвейерном выводе из ветви git, его изменении и передаче в ветку git -D. Не нужно быть злым.
24

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

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

Что это.

  • 4
    Потрясающие! Это работает для Windows ! большое спасибо
  • 0
    Я не думаю, что вы можете удалить ветку, на которой вы стоите.
Показать ещё 1 комментарий
14

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

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

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

  1. перечислите все ветки
  2. Из списка проигнорируйте главную ветку и возьмите остальные ветки
  3. удалить ветку
  • 3
    Я бы использовал git branch | grep -v "master" | xargs git branch -d сначала, поэтому я не удаляю неотправленные ветки, просто для безопасности. Но хороший ответ!
  • 2
    Вот версия ,@(git branch | Select-String -Pattern "[^(*?)\s? master]") | ForEach-Object{$_.Line.Trim()} | %{git branch -D $_}
Показать ещё 1 комментарий
11

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

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-форматировании.
  • 0
    это круто
7

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

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

Это приведет к удалению каждой локальной ветки, кроме основной ветки. Поскольку ваши восходящие ветки хранятся в .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

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

  • 0
    Здорово. Визуальное удаление :)
4

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

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

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

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

0

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

Первая git branch выведет список всех локальных веток.

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

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

0

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

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

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

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

Изображение 3907

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

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

Основываясь на других ответах на этот вопрос, я написал для себя быстрый bash script. Я назвал его "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] 
Сообщество Overcoder
Наверх
Меню