Очистка старых удаленных веток git

Вот мой рабочий процесс git.

Я работаю с двух разных компьютеров (A и B) и храню общий git remote в каталоге dropbox.

Допустим, у меня есть две ветки master и devel. Оба отслеживают свои удаленные аналоги origin/master и origin/devel.

Теперь, находясь на компьютере A, я удаляю ветку devel - как локальную, так и удаленную - следующим образом:

git push origin :heads/devel

git branch -d devel

Теперь, если я сделаю git branch -a на компьютере А я получаю

master
origin/HEAD
origin/master

Теперь я иду к компьютеру Б. git fetch, Я могу удалить локальную ветку

git branch -d devel

Но я не могу удалить удаленную ветку devel.

git push origin :heads/devel

error: unable to push to unqualified destination: heads/proxy3d
The destination refspec neither matches an existing ref on the remote nor
begins with refs/, and we are unable to guess a prefix based on the source ref.
fatal: The remote end hung up unexpectedly

дела git branch -a все еще перечисляет origin / devel в удаленных ветках.

Как я могу очистить удаленный вход devel с машины B?

10 ответов

Решение

Во-первых, каков результат git branch -a на машине Б?

Во-вторых, вы уже удалили heads/devel на originпоэтому вы не можете удалить его с компьютера B.

Пытаться

git branch -r -d origin/devel

или же

git remote prune origin

или же

git fetch origin --prune

и не стесняйтесь добавлять --dry-run до конца вашего git заявление, чтобы увидеть результат его запуска без фактического запуска.

Рассмотрим для запуска:

git fetch --prune

Регулярно в каждом репо удалять локальные ветки, которые отслеживали удаленную ветку, которая удалена (больше не существует в удаленном репозитории GIT).

Это может быть дополнительно упрощено

git config remote.origin.prune true

это per-repo установка, которая сделает любое будущее git fetch or git pull автоматически обрезать.

Чтобы настроить это для своего пользователя, вы также можете отредактировать глобальный.gitconfig и добавить

[fetch]
    prune = true

Тем не менее, рекомендуется сделать это с помощью следующей команды:

git config --global fetch.prune true

или применять его в масштабе всей системы (не только для пользователя)

git config --system fetch.prune true

Я должен добавить ответ здесь, потому что другие ответы либо не охватывают мой случай, либо излишне сложны. Я использую github с другими разработчиками, и я просто хочу, чтобы все локальные ветки, удаленные из которых (возможно, были объединены и) удалены из github PR, были удалены за один раз с моей машины. Нет, такие вещи, как git branch -r --merged не охватывают ветви, которые не были объединены локально, или ветви, которые вообще не были объединены (оставлены) и т. д., поэтому необходимо другое решение.

Во всяком случае, первым шагом я получил его из других ответов:

git fetch --prune

Пробежка git remote prune origin казалось, что в моем случае это будет делать то же самое, поэтому я выбрал самую короткую версию, чтобы сделать ее простой.

Теперь git branch -v следует отметить ветви, удаленные удаленные как [gone], Поэтому все, что мне нужно сделать, это:

git branch -v|grep \\[gone\\]|awk '{print $1}'|xargs -I{} git branch -D {}

Так просто, он удаляет все, что я хочу для приведенного выше сценария.

Менее распространенный xargs синтаксис таков, что он также работает на Mac и BSD в дополнение к Linux. Осторожно, эта команда не является пробной, поэтому она принудительно удалит все ветви, помеченные как [gone], Очевидно, что это git - ничто не уходит навсегда, если вы видите удаленные ветки, которые, как вы помните, хотели сохранить, вы всегда можете восстановить их (приведенная выше команда перечислит их хэш при удалении, поэтому просто git checkout -b <branch> <hash>,

Эта команда "пробный запуск" удалит все удаленные (origin) объединенные ветви, кроме master, Вы можете изменить это или добавить дополнительные ветки после master: grep -v for-example-your-branch-here |

git branch -r --merged | 
  grep origin | 
  grep -v '>' | 
  grep -v master | 
  xargs -L1 | 
  awk '{sub(/origin\//,"");print}'| 
  xargs git push origin --delete --dry-run

Если это выглядит хорошо, удалите --dry-run, Кроме того, вы можете сначала проверить это на развилке.

Вот скрипт bash, который может сделать это за вас. Это модифицированная версия скрипта http://snippets.freerobby.com/post/491644841/remove-merged-branches-in-git. Моя модификация позволяет ему поддерживать различные удаленные местоположения.

#!/bin/bash

current_branch=$(git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
if [ "$current_branch" != "master" ]; then
  echo "WARNING: You are on branch $current_branch, NOT master."
fi
echo -e "Fetching merged branches...\n"

git remote update --prune
remote_branches=$(git branch -r --merged | grep -v '/master$' | grep -v "/$current_branch$")
local_branches=$(git branch --merged | grep -v 'master$' | grep -v "$current_branch$")
if [ -z "$remote_branches" ] && [ -z "$local_branches" ]; then
  echo "No existing branches have been merged into $current_branch."
else
  echo "This will remove the following branches:"
  if [ -n "$remote_branches" ]; then
echo "$remote_branches"
  fi
  if [ -n "$local_branches" ]; then
echo "$local_branches"
  fi
  read -p "Continue? (y/n): " -n 1 choice
  echo
  if [ "$choice" == "y" ] || [ "$choice" == "Y" ]; then
    remotes=`echo "$remote_branches" | sed 's/\(.*\)\/\(.*\)/\1/g' | sort -u`
# Remove remote branches
for remote in $remotes
do
        branches=`echo "$remote_branches" | grep "$remote/" | sed 's/\(.*\)\/\(.*\)/:\2 /g' | tr -d '\n'`
        git push $remote $branches 
done

# Remove local branches
git branch -d `git branch --merged | grep -v 'master$' | grep -v "$current_branch$" | sed 's/origin\///g' | tr -d '\n'`
  else
echo "No branches removed."
  fi
fi

Если git branch -r показывает множество веток удаленного отслеживания, которые вас не интересуют, и вы хотите удалить их только из локальной, используйте следующую команду:

git branch -r | grep -Ev 'HEAD|master|develop'  | xargs -r git branch -rd

Более безопасная версия - удалить только объединенные:

git branch -r --merged | grep -Ev 'HEAD|master|develop'  | xargs -r git branch -rd

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

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

Чтобы прекратить извлекать эти ветки удаленного отслеживания, вам нужно явно указать ссылки для извлечения в .git / config:

[remote "origin"]
  # fetch = +refs/heads/*:refs/remotes/origin/*
  fetch = +refs/heads/master:refs/remotes/origin/master
  fetch = +refs/heads/develop:refs/remotes/origin/develop
  fetch = +refs/heads/release/*:refs/remotes/origin/release/*

В приведенном выше примере мы только получить master, develop и выпускайте ветки, не стесняйтесь и добавляйте свои.

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

git push --all --prune --dry-run

Делая так, как указано выше, git предоставит вам список того, что произойдет, если приведенная ниже команда будет выполнена.

Затем выполните следующую команду, чтобы удалить все ветви из удаленного репо, которых нет в вашем локальном репо:

git push --all --prune

Вот как это сделать с SourceTree (v2.3.1):
1. Нажмите "Получить"
2. Установите флажок "Обрезать ветви отслеживания..."
3. Нажмите ОК
4.

# First use prune --dry-run to filter+delete the local branches
git remote prune origin --dry-run \
  | grep origin/ \
  | sed 's,.*origin/,,g' \
  | xargs git branch -D

# Second delete the remote refs without --dry-run
git remote prune origin

Удалите одни и те же ветки из локальных и удаленных ссылок (в моем примере из origin).

Ответить с помощью PowerShell

Для всех, кто использует powershell. Следующее облегчило мне жизнь.

Во-первых, как следует из других ответов:

      git fetch --prune

Затем, чтобы получить строки изbranch -vу которых больше нет удаленной ветки:

      git branch -v | findstr "gone" > .\branches.txt

И, наконец, чтобы удалить ветки (используйте с -D на свой страх и риск):

      Get-Content .\branches.txt | ForEach-Object { git branch -d (($_.Trim() -split '\s+')[0]) }

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

(Версия Powershell: 7.3.6)

Другие вопросы по тегам