Удалите все ветки, которых больше нет на Github - PullRequest
3 голосов
/ 09 мая 2019

У меня есть ветви Branch-Master, Branch-A, Branch-B, Branch-C на GitHub. Я обычно сливаюсь в master и удаляю объединенную ветку. Это оставляет кучу веток на моей локальной машине, но не на GitHub.

Как автоматически удалить локальные ветви? Я хочу создать git hook для этого.

Когда я пытаюсь

git remote prune origin

и затем запустите git branch, я все еще вижу все свои ветки, даже те, которые объединены и удалены в master.

Я знаю, что могу сделать

git branch -d {the_local_branch}

вручную, но это не помогает, когда я выполняю действия, или у меня есть несколько веток для систематического удаления.

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

Это то, что они основаны на именах и выводят удаленную ветвь, а не как-то явно передают идентификатор ветки, специфичный для этой ветки. Что я понимаю из приведенной ссылки, так это то, что если я создаю имя ветви, совпадающее с удаленной, оно также будет удалено, даже если это разные ветви.

Как удалить ветку Git локально и удаленно?

Не отвечает на мой запрос, так как его решение уже указано выше.

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

Ответы [ 2 ]

0 голосов
/ 09 мая 2019

Как отметил phd в комментарии , там нет базового идентификатора для филиалов. Имя ветви - это просто локальное имя в вашем хранилище, созданное вами или по вашему запросу, которое идентифицирует один конкретный коммит. Вы можете изменить это имя в любое время на любую понравившуюся вам строку, если она соответствует требованиям для имени ветви . Git не будет помнить, что раньше у него было другое имя.

Теперь есть несколько дополнительных битов информации: ваш файл .git/config может содержать и обычно содержит для каждой ветви некоторые аннотации, такие как:

[branch "master"]
    remote = origin
    merge = master

[branch "develop"]
    remote = another-remote
    merge = develop

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

Эти разделы конфигурации будут автоматически переименованы, если вы используете стандартные команды Git для переименования ветви. Например, после git branch -m develop xyz у вас будет:

[branch "xyz"]
    remote = another-remote
    merge = develop

, что означает, что восходящий поток вашей локальной ветки xyz равен another-remote/develop. (Это предполагает стандартную настройку fetch = для пульта another-remote.)

Можно, с некоторым усилием, прочитать настройки восходящего потока (если таковые имеются) каждой ветви: используйте git for-each-ref, чтобы перечислить все ветви, а затем, для каждой ветви, используйте git rev-parse --symbolic-full-name <branch>@{upstream}, чтобы увидеть, имеет ли она вверх по течению, и если так, то как называется восходящее. Обратите внимание, что вы должны быть здесь немного осторожнее, так как «remote» может быть установлен на ., что указывает на то, что восходящий поток какой-либо локальной ветви является другой локальной ветвью.

Объединение такого рода программных тестов («имеет ли ветвь X восходящий поток, и если да, действительно ли это имя удаленного отслеживания и какое имя удаленного отслеживания это оно?») С второй тест («после использования git remote <remote> prune или git fetch <remote> --prune, существует ли имя для удаленного отслеживания?») может получить то, что вы хотите. Вам нужно будет немного кодировать (например, bash-скриптинг). Сделать его оптимальным или работать изнутри - сложно, но общая задача довольно проста:

git for-each-ref --format='%(refname:short)' refs/heads |
while read branch; do
    # make sure it has an upstream set -- if not, ignore
    upstream=$(git rev-parse --symbolic-full-name ${branch}@{upstream}) || continue
    # make sure the upstream is a remote-tracking name
    case $upstream in
    refs/remotes/*) ;;
    *) continue;;
    esac
    # get the name of the remote
    remote=${upstream#refs/remotes/}
    remote=${remote%%/*}
    # prune remote-tracking branches
    git remote $remote prune
    # and test whether the upstream still exists
    git rev-parse $upstream && continue

    # $branch has upstream $upstream which is gone, so:
    echo git branch -D $branch
done

Это довольно непроверенный, и он пропускает важные биты, такие как молчание о ветвях, которые он не собирается удалить (каждый rev-parse будет выдавать сообщения в stdout и / или stderr). Он также фактически не удаляет ветки: это может быть довольно невосстановимо, поэтому нужно сначала тщательно протестировать его, а затем удалить echo.

.
0 голосов
/ 09 мая 2019

Вы можете удалить все ветви за один раз (кроме той, которая извлечена) одной командой:

git branch --list | xargs git branch -D

Если вы хотите указать какой-либо шаблон, соответствующий имени ветви, вы можете сделатьэто тоже:

git branch --list k* | xargs git branch -D

И с помощью

git remote prune origin

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...