리모컨없이 모든 로컬 브랜치 나열


91

문제점 : 리모컨이없는 모든 로컬 브랜치를 삭제하는 방법을 원합니다. 브랜치의 이름을으로 파이프하는 것은 쉽지만 git branch -D {branch_name}처음에 그 목록을 어떻게 얻습니까?

예를 들면 :

리모컨없이 새 분기를 만듭니다.

$ git co -b no_upstream

모든 지점을 나열했는데 리모컨이있는 지점은 하나뿐입니다.

$ git branch -a
master
* no_upstream
remotes/origin/HEAD -> origin/master
remotes/origin/master

no_upstream답 을 얻기 위해 어떤 명령을 실행할 수 있습니까?

실행할 git rev-parse --abbrev-ref --symbolic-full-name @{u}수 있으며 리모컨이 없음을 보여줍니다.

$ git rev-parse --abbrev-ref --symbolic-full-name @{u}
error: No upstream configured for branch 'no_upstream'
error: No upstream configured for branch 'no_upstream'
fatal: ambiguous argument '@{u}': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

그러나 이것은 오류이기 때문에 그것을 사용하거나 다른 명령으로 파이프 할 수 없습니다. 나는 이것을 쉘 스크립트 별칭으로 사용 git-delete-unbranched하거나 아마도 매우 간단한 보석을 만들려고합니다.git-branch-delete-orphans



답변:


103

나는 최근 git branch -vvgit branch명령 의 "매우 장황한"버전을 발견했습니다 .

원격 분기가있는 경우 다음 형식으로 분기와 함께 분기를 출력합니다.

  25-timeout-error-with-many-targets    206a5fa WIP: batch insert
  31-target-suggestions                 f5bdce6 [origin/31-target-suggestions] Create target suggestion for team and list on save
* 54-feedback-link                      b98e97c [origin/54-feedback-link] WIP: Feedback link in mail
  65-digest-double-publish              2de4150 WIP: publishing-state

이 멋진 형식의 출력 을 얻으면 파이프를 연결 cut하고 awk목록을 얻는 것만 큼 ​​쉽습니다 .

git branch -vv | cut -c 3- | awk '$3 !~/\[/ { print $1 }'

결과는 다음과 같습니다.

25-timeout-error-with-many-targets
65-digest-double-publish

cut부분은 데이터를에 *전달하기 전에 출력에서 처음 두 문자 (포함 )를 제거하여 데이터를 정규화합니다 awk.

awk세 번째 열에 대괄호가없는 경우 해당 부분은 첫 번째 열을 인쇄합니다.

보너스 : 별칭 만들기

전역 .gitconfig파일 (또는 어디에서나)에 별칭을 만들어 실행하기 쉽게 만듭니다 .

[alias]
  local-branches = !git branch -vv | cut -c 3- | awk '$3 !~/\\[/ { print $1 }'

중요 : 백 슬래시는 별칭에서 이스케이프 처리해야합니다. 그렇지 않으면 잘못된 gitconfig 파일이 생성됩니다.

보너스 : 원격 필터링

어떤 이유로 서로 다른 지점에 대해 여러 개의 추적 리모컨이있는 경우 확인할 리모컨을 지정하는 것이 쉽습니다. awk 패턴에 원격 이름을 추가하기 만하면됩니다. 제 경우에는 origin이렇게 할 수 있습니다.

git branch -vv | cut -c 3- | awk '$3 !~/\[origin/ { print $1 }'

WIP:어쨌든 그게 뭐야 ..? 그것은 숨김 명령이 생성하는 것이 아닙니다 ..?
igrek

@igrek 커밋 메시지에서 사용한 접두사입니다. git에만 국한된 것은 없습니다.
제레미 베이커

내가 할 때 git branch -vv원격 분기가 존재하고 내 로컬 분기와 일치 [origin/branch-name]하더라도 결과와 함께 표시되지 않습니다 . 나는 diff실제로 지역 전용 인 것을 알아 내기 위해 두 개의 지점 목록을 작성 해야했습니다 .
ryantuck

git branch -vv | grep -v origin/나를 위해 충분하다
당황하지 말고

2
표시된 원격 지점을 놓치지 gone않습니까?
Reid

36

git branch (옵션없이) 로컬 브랜치 만 나열하지만 원격 브랜치를 추적하는지 여부는 알 수 없습니다.

일반적으로 이러한 로컬 브랜치는 다음으로 병합되면 삭제해야합니다 master( git-sweep의 이번 호 에서 볼 수 있음 ).

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

원하는만큼 완전하지는 않지만 시작일뿐입니다.

를 사용하면 --merged명명 된 커밋에 병합 된 분기 (즉, 명명 된 커밋에서 팁 커밋에 도달 할 수있는 분기) 만 나열됩니다.


1
로컬 브랜치없이 원격 브랜치를 포함하려면 git branch -a --merged.
Acumenus

21

비슷한 문제가 있습니다. 이제 삭제 된 원격 분기를 추적하던 모든 로컬 분기를 제거하고 싶습니다. 나는 git remote prune origin내가 원하는 가지를 제거하기에 불충분하다는 것을 알고 있습니다. 리모컨이 삭제되면 로컬도 삭제하고 싶습니다. 나를 위해 일한 것은 다음과 같습니다.

~/.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-D내가 망할 놈의 병합 지점에 대해 불평을 듣고 싶지 않기 때문에, 내 실제 구성. 이 기능도 원할 수 있습니다 . 그렇다면 해당 명령의 끝에 -D대신 사용 -d하십시오.

또한 FWIW, 전역 구성 파일은 거의 항상 ~/.gitconfig.

(OS X 수정)

쓰여진대로, 이것은 xargs -r(감사합니다, Korny )를 사용하기 때문에 OS X에서 작동하지 않습니다 .

-r방지하는 것입니다 xargs실행 git branch -d오류 메시지 "가 발생합니다 지점 이름없이 fatal: branch name required". 오류 메시지가 마음에 들지 않는 경우 -r인수를 제거하기 만하면 xargs모든 설정이 완료된 것입니다.

그러나 오류 메시지를보고 싶지 않다면 (그리고 정말로 누가 당신을 비난 할 수 있는지) 빈 파이프를 확인하는 다른 것이 필요합니다. moreutils 에서 ifne 을 사용할 수 있다면 . ifne앞에 삽입 하면 빈 데이터로 실행 xargs이 중지 xargs됩니다. 참고 : 아무것도 비어 있지 않은 ifne것으로 간주 합니다. 여기에는 빈 줄이 포함되므로 해당 오류 메시지가 계속 표시 될 수 있습니다. 나는 이것을 OS X에서 테스트하지 않았습니다.

다음은 그 git config줄입니다 ifne.

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

1
이것을 "git config --global ..."명령으로 변환 할 수 있습니까? 입문자 용 지침 / 방법 위키의 관점에서 "git config 파일을 찾아서 편집기를 사용하여 편집 한 다음 명령을 실행"이라고 말하는 대신 전달하기 쉽습니다.
Kannan Ekanath


알아 둘만 한. OSX에서 "비어 있으면 실행 안 함"옵션이 무엇인지 모르겠습니다.
Karl Wilbur

18

늦은 편집 :

낫다

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

GNU / anything에서

for b in `git branch|sed s,..,,`; do
    git config --get branch.$b.remote|sed Q1 && echo git branch -D $b
done

소수 이상의 분기가있을 가능성이 있다면 및 comm -23의 출력을 사용 하는 더 좋은 방법이있을 것 입니다.git branch|sed|sortgit config -l|sed|sort


1
@nmr s / git. * Q1 / test $ (git config --get branch. $ b.remote | sed q | wc -1) = 1 /
jthill

15

이것은 나를 위해 작동합니다.

git branch -vv | grep -v origin

(리모콘의 이름이 origin이 아닌 다른 이름으로 지정되면 대체하십시오).

이렇게하면 리모컨을 추적하지 않는 모든 분기가 나열됩니다.


2
이것은 원격을 가지고 있었지만 더 이상 실행하지 않는 분기를 나열합니다 git fetch --prune.
RusinaRange

2
IMO, "origin"을 필터링하는 대신 ": gone]"을 찾는 것이 좋습니다
fiorentinoing

4

origin/***: gone브랜치 를 얻기 위해 내 자신의 Git 명령을 합성합니다 .

git remote prune origin && git branch -vv | cut -c 3- | grep ': gone]' | awk '{print $1}' | xargs -n1 -r echo git branch -d

git remote prune origin && git branch -vv 자세한 모드로 분기를 인쇄합니다.

cut -c 3- 첫 번째 문자를 제거합니다.

grep ': gone]'사라진 원격 분기 만 인쇄합니다 .

awk '{print $1}' 지점 이름을 인쇄합니다.

xargs -n1 -r echo git branch -dgit branch -d분기를 제거 하는 명령을 인쇄합니다 (-n1은 한 번에 하나의 명령을 관리하고 분기가없는 경우 명령을 실행하지 않으려면 -r).

힌트 : "echo"명령을 제거하여 인쇄 만하는 대신 명령을 실행 합니다. 명령에이 명령을 남겨 git을 발행하기 전에 명령을 확인했습니다.

힌트 2 :git branch -D 병합되지 않은 분기를 제거하려는 경우에만 발행


이것에서 나는 나의 개인적인 자식이 사라졌다
fiorentinoing

1
이다 지금까지 내가 찾은 깨끗한 솔루션, 좋은! 나는 공부하는 데 시간을 보낸 적이 없습니다 awk. 당신이 그렇게 할 수 있는지 몰랐습니다.
adamjc

2

다음은 PowerShell에서 수행중인 작업을 설명하기 위해 주석과 함께 사용한 것입니다. 무슨 일이 일어나고 있는지 명확히하기 위해 약식 PowerShell 명령 (별칭)을 사용하지 않았습니다. 원하는 수준의 비밀 수준으로 자유롭게 압축하십시오 :)

$verboseList = @(git branch -vv)
foreach ($line in $verboseList)
{
    # Get the branch name
    $branch = [regex]::Match($line, "\s(\S+)\s").Captures.Groups[1].Value
    # Check if the line contains text to indicate if the remote is deleted
    $remoteGone = $line.Contains(": gone]")
    # Check if the line does not contain text to indicate it is a tracking branch (i.e., it's local)
    $isLocal = !($line.Contains("[origin/"))
    if ($remoteGone -or $isLocal)
    {
        # Print the branch name
        $branch
    }
}

0

몇 가지 기존 답변을 결합 :

[alias]
        branch-local = !git branch -vv | cut -c 3- | egrep '([0-9a-f]{7} [^[])|(: gone\\])' | sed -E 's/(^.+[0-9a-f]{7} (\\[.+\\])?).*$/\\1/'

예 :

$ git branch-local
autogen_autoreconf      fcfb1c6 [github/autogen_autoreconf: gone]
autotools_documentation 72dc477 [github/autotools_documentation: gone]
cray-mpich-messy        2196f4b
epel-sphinx             cfda770
lammps                  07d96a7 [github/lammps: gone]
lark-error              9ab5d6c [github/lark-error: gone]
no-root2                c3894d1
openmpi-cray            69326cf [github/openmpi-cray: gone]
shellcheck-cleanup      40d90ec
travis-python36         cde072e
update_vagrant_default  4f69f47 [github/update_vagrant_default: gone]
web-docs                e73b4a8
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.