더 이상 원격에서 추적 지점 제거


1171

더 이상 동일한 원격 지사가없는 모든 추적 분기를 삭제하는 간단한 방법이 있습니까?

예:

지점 (로컬 및 원격)

  • 석사
  • 원산지 / 마스터
  • 원산지 / 버그 수정 -a
  • 원산지 / 버그 수정 -b
  • 원산지 / 버그 수정 -c

로컬에는 마스터 브랜치 만 있습니다. 이제 bug-fix-a 작업을해야 하므로 확인하고 작업 한 다음 변경 사항을 원격으로 푸시합니다. 다음으로 bug-fix-b 와 동일한 작업을 수행합니다 .

지점 (로컬 및 원격)

  • 석사
  • 버그 수정
  • 버그 수정 -b
  • 원산지 / 마스터
  • 원산지 / 버그 수정 -a
  • 원산지 / 버그 수정 -b
  • 원산지 / 버그 수정 -c

이제 로컬 분기 master , bug-fix-a , bug-fix-b 있습니다. 마스터 지점 관리자는 변경 사항을 마스터 로 병합 하고 이미 병합 한 모든 지점을 삭제합니다.

현재 상태는 다음과 같습니다.

지점 (로컬 및 원격)

  • 석사
  • 버그 수정
  • 버그 수정 -b
  • 원산지 / 마스터
  • 원산지 / 버그 수정 -c

이제 원격 저장소에 더 이상 표시되지 않는 분기 (이 경우 bug-fix-a , bug-fix-b ) 를 삭제하는 명령을 호출하고 싶습니다 .

기존 명령 git remote prune origin과 비슷하지만 더 비슷 git local prune origin합니다.

답변:


1280

git remote prune origin 리모콘이 아닌 분기를 추적합니다.

git branch --merged 현재 분기에 병합 된 분기를 나열합니다.

xargs git branch -d 표준 입력에 나열된 분기를 삭제합니다.

로 표시된 분기를 신중하게 삭제하십시오 git branch --merged. 목록에는 master삭제하지 않으려는 분기 가 포함되어있을 수 있습니다 .

분기를 삭제하기 전에 목록을 편집 할 수있는 기회를 제공하기 위해 한 줄로 다음을 수행 할 수 있습니다.

git branch --merged >/tmp/merged-branches && \
  vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches

17
병합 된 분기의 첫 번째 줄은 * master내 시스템에 있습니다. 다음 명령이 나를 위해 일했습니다 :git branch -d $(git branch --merged |tail -n +2)
Trendfischer 2016

99
나는에있어 경우 develop다음 git branch --merged포함 master! 아마 (확실히!) 그것을 삭제하고 싶지 않을 것입니다. 또한 git branch -d소문자가 -d"안전한 삭제"를 의미하는 곳 이어야한다고 생각합니다 . 예를 들어 병합 된 경우에만 삭제하십시오.
thom_nic

11
향상된 솔루션이 제공되는 것 같습니다 있다 .
Sergey Brunov

34
제거 된 병합은 유용하지만 "원격이 아닌 분기 제거"와 동일하지 않습니다.
dlsso

11
grep을 사용하여 마스터를 제외하십시오.git branch --merged | grep -v "master" >/tmp/merged-branches && vi /tmp/merged-branches && xargs git branch -d </tmp/merged-branches
geniass

589

명령 후

git fetch -p

실행할 때 원격 참조를 제거합니다

git branch -vv

원격 상태로 'gone'이 표시됩니다. 예를 들어

$ git branch -vv
  master                 b900de9 [origin/master: behind 4] Fixed bug
  release/v3.8           fdd2f4e [origin/release/v3.8: behind 2] Fixed bug
  release/v3.9           0d680d0 [origin/release/v3.9: behind 2] Updated comments
  bug/1234               57379e4 [origin/bug/1234: gone] Fixed bug

따라서 원격으로 이동 한 로컬 분기를 제거하는 간단한 스크립트를 작성할 수 있습니다.

git fetch -p && for branch in $(git branch -vv | grep ': gone]' | awk '{print $1}'); do git branch -D $branch; done

위는 "porcelain"명령 git branch을 사용하여 업스트림 상태를 가져옵니다.

이 상태를 얻는 또 다른 방법은 "배관"명령 git for-each-ref을 보간 변수와 함께 사용 %(upstream:track)하는 것 [gone]입니다.

커밋 메시지의 일부에서 실수로 일치 할 위험이 없기 때문에이 방법은 다소 안전합니다.

git fetch -p && for branch in $(git for-each-ref --format '%(refname) %(upstream:track)' refs/heads | awk '$2 == "[gone]" {sub("refs/heads/", "", $1); print $1}'); do git branch -D $branch; done

8
@KrzysztofWende-Solaris 및 일부 BSD 및 일부 OS X에는 없음 :)
jww

4
마지막 커밋 메시지에서 "사라진"지점도 제거하는 것 같습니다.
dlsso

11
@dlsso 마지막 커밋 메시지에 ": gone]"문자열이 포함되어 있으면 예도 제거됩니다. 커밋 메시지를 제거하기 위해 추가 awk / gawk를 사용하여 단순성을 희생하면서 더 강력하게 만들 수 있습니다. git branch -vv | gawk '{print $1,$4}' | grep 'gone]' | gawk '{print $1}'
jason.rickman

2
이전 의견 (질문)에 대한 답장으로 현재 지점은 *를 첫 번째 필드로 사용합니다. 만약 "gone"브랜치 목록에있을 경우 $ 1이 할당되고 * 파일 및 폴더 이름을 뱉어내는 파일 스펙으로 해석됩니다. grep 표현을 제거하고 awk가 모든 필터링을 수행했습니다 awk '/: gone]/{if ($1!="*") print $1}'. 이제 예상대로 작동합니다.
rhaben

5
명령이 작은 따옴표를 사용하기 때문에 @ahmedbhs '전체 명령을 둘러싸려면 큰 따옴표를 사용해야합니다.'또한 쉘 명령 (예 : 이와 같은) 인 git 별칭에는!가 필요합니다.test = "!git fetch -p && for branch in `git branch -vv | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done"
jason.rickman

306

이 답변의 대부분은 실제로 원래 질문에 대답하지 않습니다. 나는 많은 파기를했고 이것은 내가 찾은 가장 깨끗한 해결책이었습니다. 해당 답변의 약간 더 철저한 버전이 있습니다.

  1. 기본 지점을 확인하십시오. 보통git checkout master
  2. 운영 git fetch -p && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -d

설명:

추적 분기를 잘라 내고에서 "갈았다"고 표시되는 로컬 분기를 삭제하여 작동합니다 git branch -vv.

노트:

언어가 영어 이외의 언어로 설정되어 있으면 gone적절한 단어 로 변경 해야합니다. 로컬에만있는 지점은 건드리지 않습니다. 원격에서 삭제되었지만 병합되지 않은 지점은 알림을 표시하지만 로컬에서는 삭제되지 않습니다. 그것들을 삭제하려면로 변경 -d하십시오 -D.


2
사라 프랑스어 OS에 대한 disparue에 의해 변경 될 필요가
모하메드 EL 하비브에게

4
git branch 앞에 LANG = en_US를 추가하여 영어를 강제 실행해야합니다. git fetch --prune && LANG = en_US git branch -vv | awk '/ : gone] / {print $ 1}'| xargs git branch -d
Mohamed EL HABIB

3
git checkout master && ...명령 시작 부분에 추가하겠습니다 .
iarroyo

2
삭제하려는 브랜치에있을 때 위험합니다.이 경우 첫 번째 열은 '*'이며 xargs로 전달됩니다. 이를 개선하려면 출력을 awk에 전달하기 전에 '*'문자를 제거하십시오. sed -e 's / ^ * //'
meeee

6
꼼꼼한! 모든 로컬 브랜치를 삭제하는 가장 중요한 경우가 있습니다. 현재 원격에서 삭제 된 브랜치에있는 경우 출력은 git branch -vv별표로 시작하여 결국 결과가 실행 git branch -d *됩니다. 다음은 별표가있는 행을 무시하는 패치 버전입니다.git branch -vv | grep ': gone]'| grep -v "\*" | awk '{ print $1; }' | xargs -r git branch -d
kcm

209

나는 일반적으로 이미 16 답변이있는 질문에 대답하지는 않지만 다른 모든 답변은 잘못되었으며 정답은 너무 간단합니다. 문제는 "원격에 해당하는 원격 추적 분기가 더 이상없는 모든 추적 분기를 삭제하는 간단한 방법이 있습니까?"

"간단한"이라는 말이 모든 것을 한 번에 삭제하고, 취약하지 않고, 위험하지 않으며, 모든 독자가 갖지 못할 도구에 의존하지 않는다면 올바른 대답은 다음과 같습니다.

일부 답변은 간단하지만 요청 된 내용을 수행하지 않습니다. 다른 사람들은 요청을했지만 간단하지는 않습니다. 모두 텍스트 조작 명령 또는 스크립팅 언어를 통해 Git 출력을 구문 분석하는 데 의존합니다. 일부 시스템에는 없을 수 있습니다. 또한 대부분의 제안은 출력이 스크립트로 구문 분석되지 않는 포셀린 명령을 사용합니다 ( "포슬린"은 사용자 조작을위한 명령을 의미합니다. 스크립트는 하위 레벨 "배관"명령을 사용해야 함).

더 읽을 거리 :


문제의 유스 케이스 (서버에서 삭제되었지만 여전히 로컬 브랜치로 존재하는 가비지 수집 추적 브랜치)의 경우와 상위 레벨 Git 명령 만 사용하여 안전하게 수행하려면

  • git fetch --prune(또는 git fetch -p별칭이거나 git prune remote origin가져 오지 않고 동일한 작업을 수행하며 대부분의 시간이 아닐 수도 있습니다).
  • 삭제 된 것으로보고 된 모든 원격 브랜치에 유의하십시오. 또는 나중에 찾기 위해 git branch -v(고아 추적 지점은 "[gone]"으로 표시됨).
  • git branch -d [branch_name] 각 고아 추적 지점에서

(이것은 다른 답변 중 일부가 제안하는 것입니다).

Mark Longair의 답변다른 질문에 대한 답변for-each-ref같이 솔루션을 스크립팅하려는 경우 시작 지점 이지만 쉘 스크립트 루프를 작성하지 않거나 xargs 또는 무언가를 사용하지 않고 솔루션 을 악용하는 방법을 볼 수 없습니다 .


배경 설명

진행 상황을 이해하려면 지점을 추적하는 상황에서 지점이 하나가 아니라 3 개라는 점을 이해해야합니다. 그리고 "branch"는 단순히 커밋에 대한 포인터를 의미한다는 것을 기억하십시오.

추적 분기가 주어지면 feature/X원격 저장소 (서버)에이 분기가 있으며이를 호출합니다 feature/X. 로컬 리포지토리에는 remotes/origin/feature/X"이것은 원격에서 기능 / X 브랜치가 마지막으로 얘기 한 시간입니다"라고 말한 지점이 있으며 마지막으로 로컬 리포지토리에는 feature/X최신 커밋을 가리키는 브랜치가 있으며 "track" remotes/origin/feature/X을 사용하면 당겨서 정렬 할 수 있습니다.

어느 시점에서 누군가가 feature/X리모컨 의을 삭제했습니다 . 그 순간부터, 당신은 로컬에 남아 있습니다 feature/X(기능 X에 대한 작업이 아마 끝났기 때문에 더 이상 원하지 않을 것입니다). 그리고 remotes/origin/feature/X그 목적은 서버 지점의 상태를 기억하는 것이기 때문에 확실히 쓸모가 없습니다. .

그리고 힘내는 자동으로 중복 청소를하게됩니다 remotes/origin/feature/X거야 - git fetch --prune하지만 어떤 이유로, 당신이 자동으로 자신을 삭제하지 않습니다 -하지를 feature/X당신의 ... 비록 feature/X이 정보를 가지고 있으므로, 여전히 분리 된 추적 정보를 포함 완전히 병합 된 이전 추적 지점을 식별합니다. (결국, 그것은 줄 수있는 당신에게 당신이 손으로 직접 작업을 수행 할 수 있습니다 정보를.)


3
이것은 훨씬 안전한 답변입니다. 또한 선택한 답변과 달리 "스쿼시 및 병합"워크 플로를 사용하면 작동합니다.
Jake Levitt

3
이것은 실제로 "지난 가지를 찾는 방법"이라는 질문의 쉬운 부분 (그리고 2015 년 jason.rickman이 이미 게시 한 것과 동일한 명령으로)에만 대답하지만 모든 가지를 수동으로 삭제하도록 지시합니다. 하고 싶지 않다.
Voo

4
@Voo 그것은 대답의 요점입니다. 그것을하는 방법을 알려주는 것이 아니라 (단지 보너스 일뿐입니다.) 대답은 쉽고 간단한 방법이 없다는 것입니다. 공식화 된 질문에 대한 정답입니다.
앤드류 스펜서

1
"문제의 유스 케이스에 대해 안전하게 수행하려면 첫 번째 단락의 대부분의 주장을 무효화하십시오." "[Git]은 사용자가 직접 작업을 수행 할 수있는 정보를 제공 할 수 있습니다."-우리는 프로그래머이므로 정보가 목록으로 표시되므로 (예 :) 작업은 여전히 ​​간단합니다 (예 :) xargs. git alias여러 경우를 단순화하는 것도 있습니다 .
user2864740 2016 년

2
@ user2864740 일부 독자들은 작은 bash 스크립트를 작성하는 것이 "간단한"정의에 해당한다고 생각할 수 있으며, 이는 완벽하게 방어 할 수있는 입장이지만, 두 번째 단락에서 "단순한"에 대한 내 자신의 해석을 제공했으며 나머지 답변은 일관성이 있습니다. 그것으로. 그리고 내 Git 사용자가 인정 xargs하거나 제한적으로 해석하는 것을 막기 위해 모든 Git 사용자가 가지고 있거나 강타하지는 않을 것입니다. 마이크로 코딩 과제를 찾지 않았을 수도 있습니다. 그들은 실제 목표에서 멀어지지 않고 안전하게 적용 할 수있는 빠른 답변입니다. .
앤드류 스펜서

52

여기에서 답을 찾았습니다 : 병합 된 모든 자식 분기를 어떻게 삭제할 수 있습니까?

git branch --merged | grep -v "\*" | xargs -n 1 git branch -d

우리는 주인을 유지해야합니다

당신을 확인 할 수 있습니다 master, 또는 그 문제에 대한 다른 지점은, 다른를 추가로 제거되지 않는 grep첫 번째 후. 이 경우 당신은 갈 것입니다 :

git branch --merged | grep -v "\*" | grep -v "YOUR_BRANCH_TO_KEEP" | xargs -n 1 git branch -d

그래서 만약 우리가 유지하고 싶어 master, develop그리고 staging예를 들어, 우리는 갈 것입니다 :

git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d

이것을 별명으로 만드십시오

약간 길기 때문에 .zshrc또는에 별칭을 추가 할 수 있습니다 .bashrc. 내 이름은 gbpurge( git branches purge)입니다.

alias gbpurge='git branch --merged | grep -v "\*" | grep -v "master" | grep -v "develop" | grep -v "staging" | xargs -n 1 git branch -d'

그런 다음 다시로드하여 .bashrc.zshrc:

. ~/.bashrc

또는

. ~/.zshrc

8
유용하지만 "원격이 아닌 지점 제거"와 동일하지 않음
dlsso

위대한 답변 @karlingen, 나는 모든 개발 환경에서 영구적으로 gbpurge
Peter Dolan

50

Windows 솔루션

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 $_}

설명

git checkout master 마스터 브랜치로 전환

git remote update origin --prune 먼 가지를 가지 치기

git branch -vv모든 분기의 자세한 출력을 얻습니다 ( git reference )

Select-String -Pattern ": gone]" 원격에서 제거 된 레코드 만 가져옵니다.

% { $_.toString().Trim().Split(" ")[0]} 지사 이름을 얻다

% {git branch -d $_} 지점을 삭제합니다


3
분기 이름 앞에 두 개의 공백을 제거하기 위해 .Trim()after 를 추가해야했지만이 점에 감사드립니다 .toString().
Matthew

2
이 명령에 감사드립니다. 지점을 완전히 병합하지 않았다는 오류가 발생하여 를 변경해야 git branch -d했습니다 git branch -D.
markieo

1
@markieo 당신은 아마 이미 알고 있지만, 다른 사람을 위해 - git branch -D이다 파괴 하고 아직 추진되지 않았 음을 로컬 작업을 삭제합니다. -d항상 안전하므로주의하십시오 -D.
Nate Barbettini

33

대부분의 다른 솔루션에서 "gone"에 대한 패턴 일치는 약간 무섭습니다. 보다 안전하게하기 위해 --format플래그를 사용하여 각 지점의 업스트림 추적 상태 를 가져옵니다 .

Windows 친화적 인 버전이 필요했기 때문에 Powershell을 사용하여 "삭제"로 표시되는 모든 분기를 삭제합니다.

git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | 
    ? { $_ -ne "" } | 
    % { git branch -D $_ }

첫 번째 줄에는 업스트림 브랜치가 "gone"인 로컬 브랜치의 이름이 표시됩니다. 다음 행은 빈 행을 제거하고 ( "사라지 않은"분기에 대해 출력 됨) 분기 이름을 명령에 전달하여 분기를 삭제합니다.


6
--format옵션은 상당히 새로운 것 같다; git을 2.10.something에서 2.16.3으로 업그레이드해야했습니다. 이것은 Linux-ish 시스템에 대한 나의 수정입니다 :git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)" | sed 's,^refs/heads/,,' | grep . | xargs git branch -D
bxm

2
이것이 지금까지 가장 좋은 솔루션입니다. 한 가지 제안은을 사용하는 것 refname:short입니다. 그러면 줄을 삭제할 수 있습니다% { $_ -replace '^refs/heads/', '' }
ioudas

2
이것은 Windows에 대한 훌륭한 솔루션입니다. 나는 이것을 더 읽기 쉬운 원인 git branch --list --format "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" | where { $_ -ne "" } | foreach { git branch -d $_ }으로 사용하고 있습니다. -d대신에 대신 사용하는 것이 좋습니다 -D. 더 이상 원격에 있지 않은 분기에는 강제 삭제가 필요하지 않습니다.
Rubanov

31

마스터로 병합 된 모든 브랜치를 제거하지만 마스터 자체를 제거하지 마십시오.

git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)

또는 별명을 추가하십시오.

alias gitcleanlocal="git checkout master && git pull origin master && git fetch -p && git branch -d $(git branch --merged | grep master -v)"

설명:

git checkout master 결제 마스터 지점

git pull origin master 로컬 지사가 모든 원격 변경 사항을 병합했는지 확인

git fetch -p 삭제 된 원격 브랜치에 대한 참조 제거

git branch -d $(git branch master --merged | grep master -v) 마스터로 병합 된 모든 분기를 삭제하지만 마스터 자체를 제거하지 마십시오.


3
한 가지 참고 사항은 매우 유용하지만 원격으로 푸시되지 않은 브랜치를 제거합니다. 차이점 만 나열한 다음 실제로 삭제하려는 항목을 git branch -D명령에 복사하는 것이 더 안전합니다.
Zefiryn

명확히하기 위해 Zefiryn은 원 라이너의 일부가 아닌 -D 옵션을 사용하는 것을 언급하고 있습니다.
cs01

1
또는 git branch -d푸시되지 않은 분기에 대해 경고를 표시해야하는 소문자 를 판단하십시오.
acme

16
git fetch -p

이것은 더 이상 리모콘에 존재하지 않는 분기를 제거 합니다.


64
이렇게하면 원격 참조는 제거되지만 로컬 분기 자체는 제거되지 않습니다. 유용한 명령이지만 이것이 OP의 질문에 대답하지 않는다고 생각합니다.
thataustin

뭐? 이것은 나를 위해 현지 지점을 삭제합니다.
Alex Hall

1
@AlexHall 원격 저장소에는 분기가 있습니다 X. 당신 git checkout X; 이제 저장소에는 (로컬) 추적 분기 X와 원격 분기가 있습니다 origin/X. 원격 저장소가 삭제됩니다 X. 당신 git fetch-p; 로컬 저장소 origin/X뿐만 아니라 X삭제되었습니다. 그게 니가 말하는거야?
앤드류 스펜서

16

패트릭의 대답 ( 출력 gone]에서 일치 하는 위치에 대한 모호성을 없애기 때문에 좋아 git branch하지만) * nix를 추가 하여 더미에 대한 또 다른 대답 .

가장 간단한 형태로 :

git branch --list --format \
  "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)" \
  | xargs git branch -D

나는 이것을 git-gone내 경로 의 스크립트로 싸웠다.

#!/usr/bin/env bash

action() {
  ${DELETE} && xargs git branch -D || cat
}

get_gone() {
  git branch --list --format \
    "%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)"
}

main() {
  DELETE=false
  while [ $# -gt 0 ] ; do
    case "${1}" in
      (-[dD] | --delete) DELETE=true ;;
    esac
    shift
  done
  get_gone | action
}

main "${@}"

NB- --format옵션은 상당히 새로운 것 같습니다. git을 2.10.something에서 2.16.3으로 업그레이드해야했습니다.

편집은 : 대한 제안을 포함 쥐게 refname:short에서 벤자민 W.

bashNB2- 나는 해시 뱅 에서만 테스트 했지만 아마도 이식 가능하다 sh.


첫 번째 줄 sed을 사용하여 부품 을 건너 뛸 수 없습니까 %(refname:short)?
Benjamin W.

나를 위해 일하는 것 같고, 나는 그것을 깔끔한 Git 별칭으로 사용했습니다. 여기에서 가장 깨끗한 솔루션입니다!
Benjamin W.

2.13 도입 --format. sed부품 을 건너 뛰는 또 다른 방법 은을 사용하는 것 git update-ref -d입니다. 이 방법은 다소 안전하지 않으므로 사용하는 git for-each-ref것이 더 안전합니다 (given --shell).
gsnedders

대단한 답변이며,이를 해결 --format하기 위해 실수를 할 때 내 질문에 대답하는 데 도움 이되었습니다. 단 하나의 질문 : 왜 #!bash? 여기의 모든 것은 sh나에게 휴대용처럼 보입니다 .
Toby Speight

그건 내 일반적인 상용구이며 다른 곳에서는 테스트하지 않았습니다.
bxm

15

마스터를 제외한 모든 로컬 브랜치를 지우고 개발하기 위해 간단한 한 줄에 유용 할 수 있습니다.

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

멋진 답변! 나는 'git branch | grep -v "master" | grep -v "develop"명령의 삭제 부분에 추가하기 전에 어떤 종류의 물건을 쉽게 사용할 수 있는지 좋아합니다 . 👏😊
finneycanhelp 19.49에

그러나 이것은 위의 질문에 대답하지 않습니다. 이것은 원격이 여전히 있더라도 분기를 삭제합니다.
Jim.B

13

로컬 마스터 참조와 현재 사용중인 것을 제외한 병합 된 모든 로컬 분기가 삭제됩니다.

git branch --merged | grep -v "*" | grep -v "master" | xargs git branch -d

그러면 " origin "이 참조하는 원격 저장소에서 이미 제거 된 모든 분기가 삭제 되지만 " remotes / origin " 에서 여전히 로컬로 사용 가능 합니다.

git remote prune origin

git branch -vv | grep 'gone]' | grep -v "\*" | awk '{print $1}' | xargs -r git branch -d 설명 : 나는 대체 선호 git branch --merged에 의해 git branch -vv이전이 때문에 상태 (사라)을 보여주고 git branch --merged또한 마스터 보여줄 수
jpmottin

13

이 작업을 수행하는 기본 제공 명령이 없다고 생각하지만 다음을 수행하는 것이 안전합니다.

git checkout master
git branch -d bug-fix-a

을 사용 -d하면 git은 브랜치가 완전히 HEAD업스트림 원격 추적 브랜치에 완전히 통합되지 않으면 브랜치 삭제를 거부합니다 . 따라서 항상 출력을 반복하고 git for-each-ref각 분기를 삭제하려고 할 수 있습니다. 이 방법의 문제점 은 기록이 포함되어 bug-fix-d있기 때문에 삭제 하지 않으려는 것 같습니다 origin/bug-fix-d. 대신 다음과 같은 스크립트를 만들 수 있습니다.

#!/bin/sh

git checkout master &&
for r in $(git for-each-ref refs/heads --format='%(refname:short)')
do
  if [ x$(git merge-base master "$r") = x$(git rev-parse --verify "$r") ]
  then
    if [ "$r" != "master" ]
    then
      git branch -d "$r"
    fi
  fi
done

경고 : 나는이 스크립트를 테스트하지 않았습니다-조심해서 만 사용하십시오 ...


스크립트를 편집 할 자유가있었습니다. 여전히 보장하지는 않지만 지금 실행되고 작동하는 것 같습니다.
fwielstra

13

TL; DR :

원격에없는 모든 로컬 브랜치 제거

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

원격에 있지 않고 완전히 병합 되었으며 이전에 많은 답변에서 언급했듯이 사용되지 않은 모든 로컬 분기를 제거하십시오 .

git fetch -p && git branch --merged | grep -v '*' | grep -v 'master' | xargs git branch -d

설명

  • git fetch -p 더 이상 원격에 존재하지 않는 모든 지점을 정리합니다
  • git branch -vv 로컬 브랜치를 인쇄하고 정리 된 브랜치는 태그가 붙습니다. gone
  • grep ': gone]' 사라진 지점 만 선택
  • awk '{print $1}' 분기 이름 만 표시하도록 출력 필터링
  • xargs git branch -D 모든 라인 (지점)을 반복 하고이 지점을 강제로 제거합니다.

git branch -D이 아닌 git branch -d다른 사람이 완전히 병합되지 않습니다 지점에 대한 것입니다.

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

1
마스터 대신 원격으로 말하고 싶습니까?
티노스

8

당신은 이것을 할 수 있습니다 :

git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d

7

위의 정보를 바탕으로 이것은 나를 위해 일했습니다.

git br -d `git br -vv | grep ': gone] ' | awk '{print $1}' | xargs`

': gone] '원격에있는 모든 로컬 분기를 제거합니다 .


1
마지막 커밋 메시지에서 "사라진"지점도 제거하는 것 같습니다.
dlsso

또한 gone이름의 아무 곳에 나 있는 분기를 제거합니다 .
bfontaine

3
"git branch -D git branch -vv | grep ': gone]'| awk '{print $ 1}'| xargs`"이것은 저에게 도움이되었습니다.
Muthu Ganapathy Nathan

7
grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -d

위의 명령을 사용하여 원격에서 병합 및 삭제 된 분기를 가져오고 원격에서 더 이상 사용할 수없는 로컬 분기를 삭제합니다.


지금까지 최선의 해결책은 grep gone <(git branch -v) | cut -d ' ' -f 3 | xargs git branch -D모두 삭제하도록 변경했지만
Shoaib

분기 이름 중 하나라도 하위 문자열을 포함하는 경우 위험 gone합니다 (예 :) usingonefunction.
Toby Speight

7

이 중 어느 것도 정말 나에게 적합하지 않았습니다. 나는에, 원격 지점을 추적 한 모든 지역 지점 제거 할 것을 원 origin원격 지점이 삭제 된 곳을 ( gone). 원격 지점을 추적하도록 설정되지 않은 로컬 지점 (예 : 로컬 로컬 지점)을 삭제하고 싶지 않았습니다. 또한 나는 단지 사용하는 간단한 원 라이너를 원했습니다.git 사용자 정의 스크립트를 작성하는 대신, 또는 다른 간단한 CLI 도구를 . 나는 약간의를 사용하여 종료 grepawk 간단한 명령을 할 수 있습니다.

이것은 궁극적으로 내 결국 ~/.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'

참고 : config 명령에서, 나는 사용 -d에 옵션 git branch이 아닌 -D내 실제 설정에서처럼. -DGit이 병합되지 않은 브랜치에 대해 불평하는 것을 듣고 싶지 않기 때문에 사용 합니다. 이 기능도 필요할 수 있습니다. 그렇다면, 해당 config 명령 끝에 -D대신 사용 -d하십시오.


나는 git alias 접근법을 좋아한다. 빠른 질문 : 왜하고 git branch -vvgreping : gone]하고하지 않고 git branch -vgrep [gone]합니까?
lalibi 2019 년

@ lalibi, 좋은 질문입니다. 기억이 안나요 무언가가 하나만 나타나지 않는 것 같습니다 v. 경우에 git branch -v | grep '[gone]'당신을위한 작품, 그것을 위해 이동합니다. 좀 더 깨끗해 보입니다.
Karl Wilbur

4

을 바탕으로 삭제 오래된 지역 지점 : 망할 놈의 팁 , 유사합니다 jason.rickman의 솔루션 I라는이 목적을 위해 사용자 정의 명령을 구현 자식 간 Bash를 이용한 :

$ git gone
usage: git gone [-pndD] [<branch>=origin]
OPTIONS
  -p  prune remote branch
  -n  dry run: list the gone branches
  -d  delete the gone branches
  -D  delete the gone branches forcefully

EXAMPLES
git gone -pn    prune and dry run
git gone -d     delete the gone branches

git gone -pn 가지 치기와 "사라진"분기를 나열합니다.

$ git gone -pn
  bport/fix-server-broadcast         b472d5d2b [origin/bport/fix-server-broadcast: gone] Bump modules
  fport/rangepos                     45c857d15 [origin/fport/rangepos: gone] Bump modules

그런 다음 사용 방아쇠를 당길 수 git gone -d또는git gone -D .

노트

  • 사용되는 정규 표현식 I는 "$BRANCH/.*: gone]"어디에 $BRANCH정상적으로 될 것origin . Git 출력이 프랑스어 등으로 현지화 된 경우 작동하지 않을 수 있습니다.
  • Sebastian Wiesner는 또한 Windows 사용자를 위해 Rust로 포팅했습니다. 그 중 하나는 git gone 이라고도 합니다.

이것은 아마도 받아 들여질만한 대답이어야합니다- git gone의 별칭처럼 보이 git branch -vv | grep 'origin/.*: gone]' | awk '{print $1}' | xargs git branch -d므로 OP 문제를 해결합니다.
alex

4

여기에 여러 가지 다른 답변을 많이 사용하여 UNIX와 같은 쉘에서 작동하는 다음 (git 2.13 이상 만 믿습니다)으로 끝났습니다.

git for-each-ref --shell --format='ref=%(if:equals=[gone])%(upstream:track)%(then)%(refname)%(end)' refs/heads | while read entry; do eval "$entry"; [ ! -z "$ref" ] && git update-ref -d "$ref" && echo "deleted $ref"; done

이것은 ( 기계 처리가 아닌 사람이 읽을 수있는 출력을 위해 설계된 "porcelain"명령 과 같이 ) for-each-ref대신에 사용 branch되며 branch, --shell적절하게 이스케이프 된 출력을 얻기 위해 인수를 사용합니다 (참조 이름의 문자에 대해 걱정할 필요가 없습니다).


그것은 나를 위해 작동하지만 명령의 다른 단계가 무엇을하는지 설명 할 수 있다면 좋을 것입니다. 예를 들어 나는 무슨 [ ! -z "$ref" ]뜻 인지 모른다 . 멀티 라이너가 이미 도움이되었을 것입니다. 그러나 귀하의 의견에 여전히 감사드립니다!
KevinH

4

또 다른 대답은 우아함과 교차 플랫폼에 대한 나의 요구에 맞는 솔루션이 없기 때문입니다.

원격이 아닌 로컬 브랜치를 삭제하는 명령 :

for b in $(git for-each-ref --format='%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)' refs/heads); do git branch -d $b; done

gitconfig와 통합하여 다음과 같이 실행할 수 있습니다. git branch-prune 같이 .

세게 때리다

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format='\''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'\'' refs/heads); do git branch -d $b; done'

PowerShell

git config --global alias.branch-prune '!git fetch -p && for b in $(git for-each-ref --format=''%(if:equals=[gone])%(upstream:track)%(then)%(refname:short)%(end)'' refs/heads); do git branch -d $b; done'

PowerShell 및 bash에 대한 범용 명령을 찾는 데 도움이 필요합니다.

이 답변이 가장 좋은 이유는 무엇입니까?

  • 완벽한 솔루션 제공 : git branch-prune git에 명령
  • Windows PowerShell에서 제대로 작동
  • 핵심 아이디어는 @ jason.rickman방탄 방법입니다. 사용하여git for-each-ref
  • 구문 분석 및 필터링이 수행 --filter되므로 외부 종속성이 필요하지 않습니다.

설명:

  • 에 새로운 별칭을 추가합니다 ~\.gitconfig . 이것을 실행하면 간단하게 할 수 있습니다git branch-prune
  • 이 별명 내부 :
    • 와 함께 지점을 가져옵니다 --prune플래그를 "원격 추적 분기를 더 이상 원격에서 제거하지 않습니다"
    • git for-each-ref및을 사용 --filter하여 분기 목록을 가져옵니다 [gone](원격 없음).
    • 이 목록을 반복하고 분기를 안전하게 삭제합니다

1
이 솔루션의 훌륭함을 무한대로 개선해 준 @ jerry-wu 에게 감사합니다 .
Himura

@ jerry-wu 와 git config 명령의 마지막 편집이 PowerShell에서 작동하지 않습니다 ((
Himura

1

이 bash 스크립트를 생각해 냈습니다. 그것은 항상 가지를 유지 develop, qa, master.

git-clear() {
  git pull -a > /dev/null

  local branches=$(git branch --merged | grep -v 'develop' | grep -v 'master' | grep -v 'qa' | sed 's/^\s*//')
  branches=(${branches//;/ })

  if [ -z $branches ]; then
    echo 'No branches to delete...'
    return;
  fi

  echo $branches

  echo 'Do you want to delete these merged branches? (y/n)'
  read yn
  case $yn in
      [^Yy]* ) return;;
  esac

  echo 'Deleting...'

  git remote prune origin
  echo $branches | xargs git branch -d
  git branch -vv
}

1

트릭을 수행하는 짧은 방법을 사용합니다. 시간을 절약하고 더 많은 가시성을 제공 할 수있는 것과 동일한 작업을 수행하는 것이 좋습니다.

다음 스 니펫을 .bashrc (macos의 .bashprofile)에 추가하십시오.

git-cleaner() { git fetch --all --prune && git branch --merged | grep -v -E "\bmaster|preprod|dmz\b" | xargs -n 1 git branch -d ;};
  1. 모든 리모컨 가져 오기
  2. 자식에서 병합 된 분기 만 가져 오기
  3. 이 목록에서 "보호 된 / 중요한"분기를 제거하십시오.
  4. 나머지를 제거하십시오 (예 : 깨끗하고 병합 된 가지)

필요에 맞게 grep 정규식을 편집해야합니다 (여기서 master, preprod 및 dmz가 삭제되지 않도록 방지).


git fetch --all --prune트릭을했다. 감사!
LeOn-Han Li

1

이것은 나를 위해 일했다 :

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

오, 나는 이것을 두 번 게시했습니다 ... 게시물을 검토 할 때 이것을 보았습니다. 그러나 당신은 이것을 이것을 당신의 것으로 대신하는 대신이 명령을 제공 한 사람을 가리킬 수 있습니다!
Dwza

나는 그것을 포럼에서 얻습니다. 똑똑하지 않으려 고 노력하십시오.

당신이 할 수있는 것보다 .. 어쨌든 ... 당신과이 문제를 논의하기 위해 여기에 오지 않았습니다. 당신이 말한대로.. 내 의견을 가져 가거나 무시;)
Dwza

0

나는 얼마나 오래 있는지 확실하지 않지만 지금은 git-up을 사용합니다.

나는 git up그것을하고 새 가지를 추적하고 오래된 가지를 삭제하기 시작합니다.

명확하게하기 위해, 기본 git 명령이 아닙니다 – https://github.com/aanand/git-up

BTW는 또한 더티 트리를 숨기고 단지 rebase를 그대로 만듭니다 git up.

누군가에게 도움이되기를 바랍니다.


2
이것은 서버에 존재하지 않는 로컬 브랜치를 삭제하지 않습니다.
Ashley

0

생선 껍질에 사용하는 솔루션이 있습니다. 테스트 Mac OS X 10.11.5, fish 2.3.0git 2.8.3.

function git_clean_branches
  set base_branch develop

  # work from our base branch
  git checkout $base_branch

  # remove local tracking branches where the remote branch is gone
  git fetch -p

  # find all local branches that have been merged into the base branch
  # and delete any without a corresponding remote branch
  set local
  for f in (git branch --merged $base_branch | grep -v "\(master\|$base_branch\|\*\)" | awk '/\s*\w*\s*/ {print $1}')
    set local $local $f
  end

  set remote
  for f in (git branch -r | xargs basename)
    set remote $remote $f
  end

  for f in $local
    echo $remote | grep --quiet "\s$f\s"
    if [ $status -gt 0 ]
      git branch -d $f
    end
  end
end

몇 가지 참고 사항 :

올바른 설정을하십시오 base_branch. 이 경우 develop기본 분기로 사용하지만 아무 것도 될 수 있습니다.

이 부분은 매우 중요합니다 : grep -v "\(master\|$base_branch\|\*\)". 마스터 또는 기본 분기를 삭제하지 않도록합니다.

git branch -d <branch>업스트림 또는 현재 HEAD와 완전히 병합되지 않은 브랜치를 삭제하지 않도록 추가 예방 조치로 사용 합니다.

테스트하는 쉬운 방법은로 대체 git branch -d $f하는 것 echo "will delete $f"입니다.

나는 또한 다음을 추가해야한다고 가정한다.


0

원격에 존재하지 않는 로컬 분기를 삭제하기 위해 GitPython 을 사용하여 Python 스크립트를 작성했습니다 .

    import git
    import subprocess
    from git.exc import GitCommandError
    import os

    def delete_merged_branches():
        current_dir = input("Enter repository directory:")
        repo = git.Repo(current_dir)
        git_command = git.Git(current_dir)

        # fetch the remote with prune, this will delete the remote references in local.
        for remote in repo.remotes:
            remote.fetch(prune=True)

        local_branches = [branch.name for branch in repo.branches]
        deleted_branches = []

        # deleted_branches are the branches which are deleted on remote but exists on local.
        for branch in local_branches:
            try:
                remote_name = 'origin/'+ branch
                repo.git.checkout(remote_name)
            except GitCommandError:
            # if the remote reference is not present, it means the branch is deleted on remote.
                deleted_branches.append(branch)

        for branch in deleted_branches:
            print("Deleting branch:"+branch)
            git_command.execute(["git", "branch", "-D",branch])


        # clean up the work flow.
        repo.git.checkout('master')
        repo.git.pull()

    if __name__ == '__main__':
        delete_merged_branches()

누군가가 유용하다고 생각하기를 바랍니다.


0

당신이 사용하는 경우 zsh와 쉘을 Oh My Zsh한 후 안전하게이 작업을 수행 할 수있는 가장 쉬운 방법은 설치가 자동 완성에 내장 된 사용하는 것입니다.

먼저 삭제할 분기를 결정하십시오.

~ git branch --merged

  branch1
  branch2
  branch3
* master

이미 병합 된 지점의 목록이 표시됩니다

몇 가지를 삭제 한 후 다음을 입력하십시오.

~ git branch -d 

[탭]을 누르기 만하면 로컬 지점 목록이 표시됩니다. tab-complete를 사용하거나 [tab]을 다시 누르면 [enter]로 분기를 선택할 수 있습니다.

탭 삭제할 분기 목록이 나타날 때까지 분기를 반복해서 선택하십시오.

~ git branch -d branch1 branch2 branch3

이제 Enter 키를 눌러 분기 모음을 삭제하십시오.

터미널에서 zsh를 사용하지 않는 경우 여기로 가져 오십시오 .


0

파이프를 사용하면 명령을 쉽게 읽을 수 있기 때문에 파이프를 사용하는 것이 좋습니다.

master를 제외한 모든 분기를 제거하려는 경우 이것이 내 솔루션입니다.

git branch | grep -v master | xargs -n 1 git branch -D

기준과 일치하는 다른 분기를 삭제하려면 첫 번째 및 두 번째 블록을 수정하십시오.

git branch --merged | grep feature_name | xargs -n 1 git branch -D

-3

git 클라이언트를 사용하여 나를 위해 일한 간단한 대답은 다음과 같습니다.

머신에서 저장소를 모두 삭제 한 후 다시 체크 아웃하십시오.

위험한 스크립트를 사용하지 않아도됩니다.


2
내가 현재 일하고 가지에 대한 : /
Mailo Světel

그들은 원격 다음에있는 당신은 단지 그들을 다시 뽑을 수 있다면 @ MailoSvětel (커밋하고 원격으로 최신 작업을 밀어 기억!)
후안 카를로스 Ospina 곤잘레스에게

내 질문과 대부분의 답변에서 불필요한 작업을 피하려고합니다. 다시 말해 : 내가해야 할 것은 가지를 제거하는 것입니다. 더 이상 작업하지 않겠습니다. repo를 제거하고 복제 한 다음 다시 지점을 추적하기 시작하면 많은 불필요한 작업이 발생합니다. 게다가, 일부 작업이 손실 될 수 있습니다 :(
Mailo Světel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.