오래된 원격 자식 분기 정리


696

나는 두 개의 다른 컴퓨터 (A와 B)에서 일하고 공통 git remote를 dropbox 디렉토리에 저장합니다.

master와 devel이라는 두 가지 분기가 있다고 가정 해 봅시다. 둘 다 원격 상대방의 출발지 / 마스터 및 출발지 / 출발지를 추적하고 있습니다.

이제 컴퓨터 A에서 로컬 및 원격에서 분기 디벨을 삭제합니다.

git push origin :heads/devel
git branch -d devel

git branch -a컴퓨터 A에서 실행 하면 다음과 같은 분기 목록이 나타납니다.

  • 석사
  • 원산지 / 헤드
  • 출발지 / 마스터

git fetch컴퓨터 B에서 실행 하면로 로컬 개발 분기를 git branch -d devel제거 할 수 있지만 원격 개발 분기는 제거 할 수 없습니다.

git push origin :heads/devel 다음과 같은 오류 메시지를 반환합니다.

오류 : 규정되지 않은 대상으로 푸시 할 수 없음 : heads / proxy3d
대상 참조 스펙 이 원격의 기존 참조와 일치하거나 refs /로 시작하지 않으며 소스 참조를 기반으로 접두사를 추측 할 수 없습니다.
치명적인 : 원격 끝이 예기치 않게 끊어졌습니다.

git branch -a 여전히 원격 브랜치에서 출발지 / 출발점을 나열합니다.

컴퓨터 B에서 원격 브랜치를 정리하려면 어떻게해야합니까?


4
Dropbox 폴더의 자식 리포지토리는 약간 취약하지만 추가 세부 정보는 없다고 시도한 사람이 들었습니다.
Thorbjørn Ravn Andersen

5
@ ThorbjørnRavnAndersen 아마도 다른 컴퓨터에서 안전하게 사용할 수 있는지 확인하기 전에 커밋 할 때마다 완전히 동기화되도록 기다릴 필요가 있습니다 (그리고 다른 동기화 필요).
ataulm

답변:


1240

먼저, git branch -a기계 B 의 결과는 무엇 입니까?

둘째, 당신은 이미 삭제 한 heads/develorigin그래서 왜 당신이 기계 B.에서 항목을 삭제할 수는 없습니다,

시험

git branch -r -d origin/devel

또는

git remote prune origin

또는

git fetch origin --prune

실제로 명령문을 실행하지 않고 실행 한 결과를 보려면 명령문 --dry-run끝에 추가 git하십시오.

에 대한 문서 git remote prunegit branch.


50
git remote prune origin나를 위해 일한 => * [pruned] origin/my-old-branch
Hari Karam Singh 16:19에

126
git remote prune origin --dry-run실제로 수행하지 않고 삭제할 내용을 보여줍니다.
Wolfram Arnold

31
git fetch origin --prune삭제 된 지점을 제거 완벽했다
세바스티앙 비에리

10
사라진 리모컨을 추적하는 로컬 지점이있는 경우 아무 것도 삭제되지 않습니다. 그런 git branch -vv다음에 git branch -D branchname는 자두가 가장 좋은 방법입니다.
Roman Starkov

7
다음 옵션을 설정하여 풀 / 페치시 자동으로 가지 치기를 구성 할 수 있습니다.git config remote.origin.prune true
Patrick James McDougle

101

다음을 실행하십시오.

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

14

여기 당신을 위해 그것을 할 수있는 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

1
이것은 "origin / feature / mybranch"라는 브랜치에서 끊어졌습니다. 이유가 확실하지 않습니다.
Stavros Korokithakis

두 가지 문제가 sed있습니다. 교체 sed 's/\(.*\)\/\(.*\)/\1/g'sed 's/\([^/]*\)\/\(.*\)/\1/g'
브누아 Latinier에게

14

이 명령은를 제외한 모든 원격 ( origin) 병합 된 분기 를 "건조 실행" 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. 또한이를 포크에서 먼저 테스트하고 싶을 수도 있습니다.


좋은. 첫 xargs + awk 대신 perl을 사용하여 조정 : git branch -r --merged | grep 원산지 | grep -v '>'| grep -v 마스터 | perl -lpe '($ junk, $ _) = split (/ \ //, $ _, 2)'| xargs git push origin --delete
Andrew

6

경우 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/*    ### don't fetch everything
  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해제 가지를, 당신이 필요로 적응 주시기 바랍니다.


1
고마워, 첫 번째 명령이 나를 위해 일했습니다. 또한 현재 브랜치 (개인적으로 선호하는 것) 만 페치 git fetch origin branchname하는 것처럼 하나의 브랜치를 가져 오거나 별명을 작성할 수도 있습니다 ft = "!f() { git fetch origin $(git rev-parse --abbrev-ref HEAD);}; f". 건배.
GiovanyMoreno

어쩌면 OT이지만 -r깃발의 의미는 무엇입니까? 내가 볼 xargs-R인수를하지만에 대해 아무것도 찾지 못했습니다 -r. 이론 상으로는 그것이 제대로 xargs작동하지 않더라도 작동 하는 방식을 정확하게 기억한다면 이론적으로 말입니다 -r.
Aldo 'xoen'Giambelluca

나는이 답변을 좋아한다. 몇 가지 메모 (명백한 사실을 말함). 마지막 파이프와 마지막 명령을 제거하여 삭제할 분기를 "미리보기"할 수 있습니다 | xargs git branch -d. 또한 -r옵션 ( --remotes)을 git branch -d제거하여 로컬 분기 만 정리합니다 (기본적으로 git branch원격 분기가 표시되지 않는다는 것을 고려하면 충분할 수 있음 ).
Aldo 'xoen'Giambelluca

감사! 이것은 내가 필요한 것입니다. 다른 솔루션은 가지 치기 된 로컬 브랜치를 리모트로 밀어서 제거 할 것을 제안하지만 리모트가 제거되었거나 더 이상 존재하지 않는 경우에는 도움이되지 않습니다. 이 접근 방식은 더 이상 액세스 할 수없는 원격 지점에 대한 로컬 참조를 제거했습니다.
cautionbug

@aldo, xargs -r--no-run-if-empty, GNU 확장의 의미입니다. 여기에 좋은 설명이 있습니다.
ryenus

4

삭제는 항상 어려운 작업이며 위험 할 수 있습니다 ! 따라서 먼저 다음 명령을 실행하여 어떻게되는지 확인하십시오.

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

위와 같이함으로써 git아래 명령이 실행될 때 일어날 일의 목록을 제공 할 것입니다.

그런 다음 다음 명령을 실행하여 로컬 저장소에없는 원격 저장소에서 모든 분기를 제거하십시오.

git push --all --prune

10
이 명령은 위험 해 보입니다 ... 원하는 것을 삭제했습니다 (위의 답변 중 4 개 이상으로는 수행 할 수 없음). 그러나 다른 4 개의 개발 지점도 삭제했습니다. 힘내는 절대 짜증나 ...
jww

2
해당 지점은 해당 지역에 있지 않아야합니다. 그러나 모든 것이 손실되지는 않습니다. 힘내 커밋, 힘내 참조 및 git reset --hard <checksum>. 말 그대로 커밋 (일명 저장) 및 다른 사람들 에게이 작업을 수행 할 수 있습니다. 분기는 레이블 일 뿐이므로 레이블을 삭제해도 저장이 삭제되지는 않습니다. 영원히 체크섬을 갖게됩니다. 도와 드릴 수 있는지 알려주세요
Timothy LJ Stewart

3
물론 git의 가비지 수집기는 결국 분기에서 참조하지 않는 커밋을 제거하기 때문에이를 빠르게 복구하려고합니다.
Andrew

1
-n이 명령 에 (드라 이런) 을 추가 하여 변경 사항을 미리 볼 수 있으며 모든 것이 괜찮다면을 사용하지 않고 다시 호출하십시오 -n.
mati865

1
@GuiWeinmann에 동의하십시오-이것은 특히 건식 실행에서 이것을 먼저 실행하기에는 특정 설명이 없으면 너무 위험합니다.
Vivek M. Chawla

2

SourceTree (v2.3.1)를 사용하여 수행하는 방법은 다음과 같습니다.
1. 가져 오기를 클릭합니다
. " 프린 추적 분기 추적 ..."을
확인합니다
. 3. 확인을 누릅니다 .

여기에 이미지 설명을 입력하십시오


1

다른 답변이 내 사례를 다루지 않거나 불필요하게 복잡하기 때문에 여기에 답변을 추가해야합니다. 다른 개발자와 함께 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구문은 Linux뿐만 아니라 Mac & BSD에서도 작동합니다. 이 명령은 드라 이런이 아니므로로 표시된 모든 분기를 강제로 삭제합니다 [gone]. 분명히이 자식은 영원히 사라지지 않습니다. 분기가 삭제되었다는 것을 기억하면 항상 삭제를 취소 할 수 있습니다. 위의 명령은 삭제시 해시를 나열하므로 간단 git checkout -b <branch> <hash>합니다.


0
# 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

local- 및 remote-refs (내 예제에서 origin) 에서 동일한 분기를 정리하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.