Видаліть усі локальні гілки git


323

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

Що, як правило, трапляється з часом через поєднання лінощів або забудькуватість, - це те, що я закінчую великим списком місцевих гілок, деякі з яких (наприклад, шипи), можливо, не були об'єднані.

Я знаю, як перерахувати всі мої локальні гілки, і мені відомо, як видалити одну гілку, але мені було цікаво, чи існує команда 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 Питання також стосується гілок, які, можливо, не були об'єднані, і я оновив питання, щоб явно це відобразити.
Південь

Відповіді:


384

Підкоманда '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.для кожної із зазначених галузей.
Листопад

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
Єдина відповідь на ТАК я знайшов, що працює. Дякую!
Кевін

140

Я знайшов приємніший спосіб у коментарі до цього питання на github :

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

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


2
Нарешті, потрібне мені рішення
Шепіт коду

1
Я спробував це, але продовжуйте отримувати error: branch 'my-branch-name' not found.для кожної гілки. Використання git версії 1.8.3.4 (Apple Git-47). Будь-яка ідея чому?
wheresrhys

спробуйте 'git branch --merged master | grep -v майстер | xargs echo ', щоб налагодити, що саме він намагається видалити? не мати кращих ідей ...
mBardos

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

1
Вивчили використання xargs разом із цим. Спасибі
Волем

105

Розбір результатів git branchне рекомендується, і це не є гарною відповіддю для майбутніх читачів на стеку Overflow.

  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 / heads), є аналогічними проблемами (refs можуть бути замість .git / packed-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?
nobar

5
Це поліпшення точно. У вас завжди буде проблема відфільтрувати *, і це робить забавні речі, якщо хтось запускає його з відірваної голови. Основна проблема, однак, git branch- це порцелянова команда, і немає гарантії, що вихід не зміниться в будь-якій майбутній версії git.
Ендрю С

Дякую @AndrewC - це обидві відповіді на питання про таємничі помилки "гілка не знайдена" та забезпечує робоче рішення за допомогою більш відповідної команди! 👍
Джейсон

2
Як ідентифікуються команди "Porcelain" та "non-Porcelain" GIT?
GoZoner

1
Можливо, було б корисним вдосконаленням, щоб виключити "dev" і "master" за замовчуванням?
PandaWood

66

Найпростіший спосіб видалення всіх гілок, але збереження інших, таких як "розвивати" та "майстер", полягає в наступному:

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

дуже корисний !


8
Ви воскресили стару тему для віків і опублікували практично ідентичну відповідь на існуючу, тобто помилку, і не вистачає змін безпеки, які вона мала. Це не є гарною відповіддю.
Ендрю С

6
Ця відповідь зрозуміла в констатуванні виводу з гілки git, її модифікації та переходу до гілки git -D. Не треба бути середнім.
Пам

Це рішення спрацювало на мене. Видалено всі місцеві відділення.
Прад

1
Це не видалить будь-яку гілку, що містить слово розробку або майстер, як-от "develo_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, ви отримуєте список з одним із тих, хто на кожному рядку?
sblom

1
це буквально говорить error:branch 'a_branch_name' not found.? Або скаржиться на одне із найменувань гілок з вашого git branchрезультату?
sblom

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 $_}
Йонас Ломхолдт

1
@baklazan, це буде працювати в командному рядку Windows 10, лише якщо у вас встановлені деякі інструменти. Напевно у вас є MINGW або якась інша така річ, і ви цього не знаєте.
KthProg

42

Лише зауваження, я би перейшов на git 1.7.10. Тут ви можете отримувати відповіді, які не працюватимуть на вашій версії. Я здогадуюсь, що вам доведеться встановити префікс ім'я гілки refs/heads/.

ПОПЕРЕДЖЕННЯ, виконайте такі дії лише в тому випадку, якщо ви зробили копію робочої папки та .git каталогу.

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


Нарешті простий і прагматичний варіант. Мені це подобається: D
Мельвін

2
Це не спрацює, якщо ви запакували refs або навіть якщо ви клонували з віддаленого сервера іноді (що надасть вам запаковані файли). Якщо ви будете запаковані, вони не зберігатимуться у .git / refs / heads, вони зберігатимуться у файлі під назвою "packed-refs". Див. Git-scm.com/docs/git-pack-refs .
Олександр Птах

1
Здається, погана ідея видалити гілку, яку ви перевірили на даний момент
Moberg

@Moberg Заздалегідь відмовтеся від фіксації, і ваша відокремлена ШОЛА буде плавати в порядку.
RomainValeri

34

Спробуйте виконати таку команду оболонки:

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

Пояснення:

  • 🛒 Отримати всі гілки за допомогою git branch | grep -v "master"команди
  • 👇 Виберіть кожну гілку за допомогою xargsкоманди
  • 💦 Видалити гілку за допомогою xargs git branch -D

3
Хоча це може бути правильною відповіддю. Один рядок коду не дуже корисний без пояснення того, що і як він вирішує вихідне питання. Будь ласка, надайте детальну інформацію у відповідь.
RyanNerd

28

Щоб видалити всі локальні гілки в Linux, крім тієї, на якій ви перебуваєте

// hard delete

git branch -D $(git branch)

2
Це відчуває себе безпечніше, ніж заходити у .git та видаляти речі.
nelsontruran

25

Мені було простіше просто використовувати текстовий редактор та оболонку.

  1. Тип git checkout <TAB> оболонку. Показуватимуть усі місцеві відділення.
  2. Скопіюйте їх у текстовий редактор, видаліть ті, що вам потрібно зберегти.
  3. Замініть розриви рядків пробілами. (У SublimeText це дуже просто.)
  4. Відкрита оболонка, тип git branch -D <PASTE THE BRANCHES NAMES HERE>.

Це воно.


Я не думаю, що ти можеш видалити гілку, на якій стоїш.
Донг Танг

@Dong Поруч із цією гілкою є *, тому просто видаліть його зі скопійованого списку!
Меланія

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.
tassinari

10

З командного рядка Windows видаліть усі, крім поточної перевіреної гілки, використовуючи:

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

7

Якщо вам не потрібно переглядати сам Git, ви також можете видалити голови під .git / refs / heads вручну або програму. Нижче слід працювати з мінімальними налаштуваннями під Bash:

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

Це видалить будь-яку локальну гілку, крім вашої головної гілки. Оскільки ваші гілки вище за течією зберігаються під .git / refs / remote , вони залишаться недоторканими.

Якщо ви не використовуєте Bash або хочете рекурсувати багато репозиторіїв Git одночасно, ви можете зробити щось подібне з GNU find:

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

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


Класно. Візуальне видалення :)
sandalone

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 .

Я використовую командний рядок 99% часу, але в цьому випадку його або далеко сповільнювати (звідси початковий питання), або ви не знаєте, що збираєтесь видалити, вдаючись до якоїсь тривалої, але розумної маніпуляції з оболонкою.

Користувацький інтерфейс вирішує цю проблему, оскільки ви можете швидко перевірити видалені гілки та нагадати про ті, які ви хочете зберегти, не вводячи команди для кожної гілки.

З інтерфейсу користувача перейдіть до Відділення -> Видалити та Ctrl + Клацніть гілки, які ви хочете видалити, щоб вони були виділені. Якщо ви хочете бути впевнені , що вони будуть об'єднані в галузі (наприклад , як dev), під Delete Тільки якщо злиті в набір місцевого відділення в dev. В іншому випадку встановіть його завжди, щоб ігнорувати цю перевірку.

GitUI: видалення місцевих гілок


1

Для повноважень це буде працювати:

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

0

Наступний сценарій видаляє гілки. Використовуйте його та модифікуйте на свій страх і ризик тощо

Виходячи з інших відповідей у ​​цьому питанні, я закінчив писати для себе швидкий скрипт. Я назвав це "gitbd" (гіт git -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, виконайте / натисніть, якщо потрібно, клонуйте свіжу копію сховища та видаліть стару.


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.