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

С git remote prune origin я могу удалить локальные ветки, которые больше не находятся на пульте дистанционного управления.

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

Как я могу это сделать?

Ответ 1

После обрезки вы можете получить список удаленных ветвей с git branch -r. Список веток с их удаленной ветвью отслеживания можно получить с помощью git branch -vv. Таким образом, используя эти два списка, вы можете найти ветки удаленного отслеживания, которых нет в списке пультов.

Эта строка должна выполнить трюк (требуется bash или zsh, не будет работать со стандартной оболочкой Bourne):

git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

Эта строка получает список удаленных ветвей и передает ее в egrep через стандартный ввод. И фильтрует ветки с ветвью удаленного отслеживания (используя git branch -vv и фильтрацию для тех, у кого есть origin), а затем получает первый столбец этого вывода, который будет именем ветки. Наконец, передав все имена ветвей в команду удаления.

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

Также помните, что сначала нужно запустить git fetch --prune, иначе git branch -r будет видеть удаленные ветки.

Ответ 2

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

git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

Дополнительная информация.

Ответ 3

Среди информации, представленной git help fetch, есть этот маленький элемент:

 -p, --prune
        After fetching, remove any remote-tracking branches which no longer exist on the remote.

Итак, возможно, git fetch -p - это то, что вы ищете?

EDIT: Хорошо, для тех, кто все еще обсуждает этот ответ через 3 года после факта, здесь немного больше информации о том, почему я представил этот ответ...

Во-первых, OP говорит, что они хотят "удалить также те локальные ветки, которые были созданы из этих удаленных веток [которые больше не находятся на пульте дистанционного управления]". Это не однозначно возможно в git. Вот пример.

Скажем, у меня есть репо на центральном сервере, и у него две ветки, называемые A и B. Если я клонирую это репо в свою локальную систему, мой клон будет иметь локальные ссылки (еще не существующие ветки), называемые origin/A и origin/B. Теперь позвольте сказать, что я делаю следующее:

git checkout -b A origin/A
git checkout -b Z origin/B
git checkout -b C <some hash>

Ниже приводятся следующие факты: я почему-то решил создать ветвь на моем локальном репо, у которого другое имя, чем его происхождение, и у меня также есть локальная ветвь, которая еще не существует в репо-источнике.

Теперь скажем, что я удаляю ветки A и B на удаленном репо и обновляю локальное репо (git fetch некоторой формы), что приводит к исчезновению локальных ссылок origin/A и origin/B, Теперь у моего локального репо еще три ветки A, Z и C. Ни один из них не имеет соответствующей ветки на удаленном репо. Два из них были "созданы из... удаленных ветвей", но даже если я знаю, что в начале была ветвь с именем B, я не знаю, что Z был создан из B, потому что он был переименован в процесс, вероятно, по уважительной причине. Таким образом, на самом деле, без каких-либо внешних метаданных происхождения ветвящихся процессов, или человека, который знает историю, невозможно определить, какая из трех ветвей, если таковая имеется, предназначена для удаления. Без какой-либо внешней информации, которую git автоматически не поддерживает для вас, git fetch -p находится примерно так же близко, как вы можете получить, и любой автоматический метод для буквальной попытки того, что задает OP, рискует либо удалить слишком много ветвей, либо не получить некоторые, которые OP в противном случае хотели бы удалить.

Существуют и другие сценарии, например, если я создаю три отдельных ветки с origin/A, чтобы протестировать три разных подхода к чему-то, а затем origin/A уходит. Теперь у меня три ветки, которые, очевидно, не могут совпадать по имени, но они были созданы из origin/A, и поэтому для толкования вопроса OPs потребуется удалить все три. Однако это может быть нежелательно, если вы даже можете найти надежный способ сопоставить их...

Ответ 4

Это приведет к удалению локальных ветвей, для которых удалены ветки удаленного отслеживания. (Убедитесь, что вы находитесь на ветке master!)

git checkout master
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -d

Подробности:

  • git branch -vv отображает "ушел" для локальных ветвей, что удаленный фрагмент был обрезан.

    mybranch abc1234 [origin/mybranch: gone] commit comments
    
  • -d проверяет, было ли оно объединено (-d будет удалять его независимо)

    error: The branch 'mybranch' is not fully merged.
    

Ответ 5

Можно настроить Git на автоматическое удаление ссылок на удаленные удаленные ветки при извлечении:

git config --global fetch.prune true

При вызове git fetch или git pull впоследствии удаленные удаленные ветки удаляются автоматически.

Ответ 6

Там аккуратный пакет NPM, который делает это для вас (и он должен работать на кросс-платформе).

Установите его с помощью: npm install -g git-removed-branches

И затем git removed-branches покажет вам все устаревшие локальные ветки и git removed-branches --prune, чтобы фактически удалить их.

Подробнее здесь.

Ответ 7

Windows Solution

Для Microsoft Windows Powershell:

git checkout master; git remote update origin --prune; git branch -vv | Select-String -Pattern ": gone]" | % { $_.toString().Trim().Split(" ")[0]} | % {git branch -d $_}

Explaination

git checkout master переключается на ветку master

git remote update origin --prune удаленные ветки

git branch -vv получает подробный вывод всех ветвей (ссылка на git)

Select-String -Pattern ": gone]" получает только записи, где они были удалены из удаленного.

% { $_.toString().Split(" ")[0]} получить имя ветки

% {git branch -d $_} удаляет ветку

Ответ 8

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

$ git remote prune origin --dry-run

Если вы хотите отключить эти локальные ветки от локальных, которые не отслеживаются

$ git remote prune origin

Ответ 9

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

git branch --merged | ? {$_[0] -ne '*'} | % {$_.trim()} | % {git branch -d $_}

Объяснение

  • Отображает текущую ветку и ветки, которые были объединены в нее.
  • Фильтрует текущую ветку
  • Очищает все начальные или конечные пробелы из вывода git для каждого оставшегося имени ветки
  • Удаляет объединенные локальные ветки

Это стоит запустить git branch --merged самостоятельно, чтобы убедиться, что он удалит только то, что вы ожидаете.

(Портировано/автоматизировано из http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/.)

Ответ 10

Я хотел что-то, что очистило бы все локальные ветки, которые отслеживали удаленную ветку, по origin, где удаленная ветка удалена (gone). Я не хотел удалять локальные ветки, которые никогда не были настроены для отслеживания удаленной ветки (например, мои локальные ветки dev). Кроме того, мне нужен простой однострочный динамик, который просто использует git или другие простые инструменты CLI, вместо того, чтобы писать собственные скрипты. Я закончил использовать немного grep и awk чтобы сделать эту простую команду, а затем добавил ее как псевдоним в свой ~/.gitconfig.

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

Вот команда git config --global... легко добавляет это как git prune-branches:

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'

ПРИМЕЧАНИЕ. Использование флага -D для git branch может быть очень опасным. Итак, в приведенной выше команде config я использую параметр -D для git branch а не -D; Я использую -D в моей реальной конфигурации. Я использую -D потому что я не хочу слышать, как Гит жалуется на несвязанные ветки, я просто хочу, чтобы они ушли. Вы также можете использовать эту функцию. Если это так, просто используйте -D вместо -D в конце этой команды config.

Ответ 11

Еще короче и безопаснее однострочник:

git branch -d $(git branch --merged | cut -c 3- | grep -v master)

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

Ответ 12

не уверен, как это сделать сразу, но git git branch -d <branchname> будет удалять локальную ветвь ТОЛЬКО, если она полностью слита. Обратите внимание на строчку d.

git branch -d <branchname> (обратите внимание на капитал D) удалит локальную ветвь независимо от ее объединенного состояния.

Ответ 13

Удалить удаленные ветки

$git remote prune origin

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

$git branch -D $(git branch --merged)

Ответ 14

Как отмечает @tzacks... для этого есть пакет npm. Просто сделайте:

npx git-removed-branches --prune

(я бы прокомментировал, но репутации недостаточно)

Ответ 16

Основываясь на ответах выше, я использую этот более короткий вкладыш:

git remote prune origin | awk 'BEGIN{FS="origin/"};/pruned/{print $2}' | xargs -r git branch -d

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

git branch -vv | awk '/^ .*gone/{print $1}' | xargs -r git branch -d

Ответ 17

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

  1. git branch -vv | grep 'gone]' > stale_branches.txt
  2. просмотреть файл и удалить строки для веток, которые вы хотите сохранить (например, ветку master!); вам не нужно редактировать содержимое любой строки
  3. awk '{print $1}' stale_branches.txt | xargs git branch -d

Ответ 18

Основываясь на ответах выше, я пришел с этим однострочным решением:

git remote prune origin; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -d

Ответ 19

Используя вариант на @wisbucky answer, я добавил следующее в качестве псевдонима в мой файл ~/.gitconfig:

pruneitgood = "!f() { \
    git remote prune origin; \
    git branch -vv | perl -nae 'system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}'; \
}; f"

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

Ответ 20

Вариант Шлейса для меня не работает (Ubuntu 12.04), поэтому позвольте мне предложить мои (ясные и блестящие:) варианты:

Вариант 1 (я бы предпочел эту опцию):

git for-each-ref --format='%(refname:short) %(upstream)' refs/heads/ | awk '$2 !~/^refs\/remotes/' | xargs git branch -D 

Вариант 2:

а. Сухой ход:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | awk '{print "git branch -D " $1}'

б. Удалить ветки:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | xargs git branch -D

Ответ 21

Ниже приведена адаптация ответа @wisbucky для пользователей Windows:

for /f "tokens=1" %i in ('git branch -vv ^| findstr ": gone]"') DO git branch %i -d

Я использую posh- git и, к сожалению, PS не нравится голой for, поэтому я создал простую команду ol script с именем PruneOrphanBranches.cmd:

@ECHO OFF
for /f "tokens=1" %%i in ('git branch -vv ^| findstr ": gone]"') DO CALL :ProcessBranch %%i %1

GOTO :EOF

:ProcessBranch
IF /I "%2%"=="-d" (
    git branch %1 %2
) ELSE (
    CALL :OutputMessage %1
)
GOTO :EOF

:OutputMessage
ECHO Will delete branch [%1] 
GOTO :EOF

:EOF

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

Ответ 22

Попробуйте это в git bash, чтобы извлечь и обрезать ссылки на удаленные ветки, а затем обрезать локальные ветки, отслеживающие удаленные:

git fetch -p && git branch -d `git branch -vv | grep ': gone]' | awk '{print $1}' | xargs`

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

Ответ 23

Версия Powershell git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

git branch --merged master | %{ if($_ -notmatch '\*.*master'){ git branch -d "$($_.Trim())" }}

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

git checkout master для переключения.

Ответ 24

Я включил принятый ответ в надежный script. Вы найдете в моем репозитории git -extensions.

$ git-prune --help
Remove old local branches that do not exist in <remote> any more.
With --test, only print which local branches would be deleted.
Usage: git-prune [-t|--test|-f|--force] <remote>

Ответ 25

git fetch --prune
git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv) | awk '{print $1}' | xargs git branch -D

Ответ 26

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

Мне также было все равно, была ли локальная ветвь объединена или нет, так как git branch -d в git branch -d будет просто предупреждать, вместо того, чтобы удалять неотделенные локальные ветки.

git branch -a | grep origin | tr -s ' ' | cut -d '/' -f3 | egrep -v -f /dev/fd/0 <(git branch -a | grep -v origin) | grep branch_prefix_that_I_care_about | xargs git branch -d

# translation
# git branch -a | grep origin | tr -s ' ' | cut -d '/' -f3
## this finds all remote branch names minus the "remote/origin/" part
#
# <(git branch -a | grep -v origin)
## this finds all local branch names and redirects it into the previous command
#
# egrep -v -f /dev/fd/0 STUFF
## this is doing some weird magic that I'm grokking as "take the set difference from whatever was piped in"
#
#
# overall translation: (STUFF TO CONSIDER) | egrep magic <(STUFF TO REMOVE FROM CONSIDERATION) | do cool things with resulting stuff

Ответ 27

В Powershell:

git branch -D (git branch --merged |% { $_.trim() } )

Ответ 28

Удалите любую ветку, которая не обновляется с помощью мастера

git co master && git branch | sed s/\*/\ / | xargs git branch -d 2> /dev/null

Ответ 29

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

Просто перейдите к: C:\Repo\your-project\.git\refs\heads

Каждая ветвь - это файл, созданный в этой папке, просто удалите файлы, соответствующие вашим именам ветвей

Трудно найти метод в Windows, я использую sourcetree, и я не хочу удалять один за другим. Я так понял, и это спасло меня на моей Windows.

Ответ 30

Я уверен, что git remote prune origin - это то, что вы хотите.

Вы можете запустить его как git remote prune origin --dry-run, чтобы увидеть, что он сделает, не внося никаких изменений.