programing tip

원격에 더 이상 존재하지 않는 로컬 추적 분기를 정리하는 방법

itbloger 2020. 10. 2. 21:47
반응형

원격에 더 이상 존재하지 않는 로컬 추적 분기를 정리하는 방법


git remote prune origin나는 더 이상 원격에없는 로컬 가지를 제거 할 수 있습니다.

하지만 원격 브랜치에서 생성 된 로컬 브랜치를 제거하고 싶습니다 (병합 해제되었는지 확인하는 것이 좋습니다).

어떻게 할 수 있습니까?


가지 치기 후 .NET을 사용하여 원격 분기 목록을 가져올 수 있습니다 git branch -r. 원격 추적 분기가있는 분기 목록은를 사용하여 검색 할 수 있습니다 git branch -vv. 따라서이 두 목록을 사용하여 원격 목록에없는 원격 추적 분기를 찾을 수 있습니다.

이 줄은 트릭을 수행해야합니다 ( bash또는 필요 zsh, 표준 Bourne 셸에서는 작동하지 않음).

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

이 문자열은 원격 분기 목록을 가져와 egrep표준 입력 통해 전달합니다 . 그리고 원격 추적 분기가있는 분기를 git branch -vv필터링 origin한 다음 (가있는 분기에 대해 사용 및 필터링 ) 분기 이름이 될 출력의 첫 번째 열을 가져옵니다. 마지막으로 모든 분기 이름을 delete branch 명령에 전달합니다.

-d옵션을 사용하고 있기 때문에이 명령을 실행할 때 현재있는 분기에 병합되지 않은 분기는 삭제되지 않습니다.

또한 git fetch --prune 먼저 실행해야 함을 기억 git branch -r하십시오. 그렇지 않으면 원격 분기가 계속 표시됩니다.


이미 master에 병합 된 모든 로컬 분기를 삭제하려면 다음 명령을 사용할 수 있습니다.

git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

더 많은 정보 .


에서 제공하는 정보 가운데 다음과 git help fetch같은 작은 항목이 있습니다.

 -p, --prune
        After fetching, remove any remote-tracking branches which no longer exist on the remote.

그래서 아마도 git fetch -p당신이 찾고있는 것이 무엇입니까?

편집 : 좋아, 사실 3 년 후에도이 답변을 토론하는 사람들을 위해 여기 에이 답변을 제시 한 이유에 대한 정보가 조금 더 있습니다 ...

첫째, OP는 "[더 이상 원격에 있지 않은] 원격 브랜치에서 생성 된 로컬 브랜치를 제거"하고 싶다고 말합니다. 이것은 git. 여기에 예가 있습니다.

하자 내가 중앙 서버에 REPO가 있다고, 그것은라는 두 가지를 가지고 AB. 해당 리포지토리를 로컬 시스템에 복제하면 내 복제에는 origin/A라는 로컬 참조 (아직 실제 분기가 아님)가 origin/B있습니다. 이제 다음을 수행한다고 가정 해 보겠습니다.

git checkout -b A origin/A
git checkout -b Z origin/B
git checkout -b C <some hash>

여기에 관련된 사실은 어떤 이유로 인해 원본과 다른 이름을 가진 로컬 리포지토리에 브랜치를 만들기로 선택했으며 오리진 리포지토리에 (아직) 존재하지 않는 로컬 브랜치를 가지고 있다는 것입니다.

이제하자 내가 모두 제거 말 AB원격 REPO에 지점을하고 (내 지역의 repo 업데이트 git fetch내 로컬 심판을 야기 어떤 형태의)을 origin/A하고 origin/B사라. 자, 내 지역의 repo는 세 가지 아직,이 A, Z등을 C. 이들 중 어느 것도 원격 저장소에 해당 분기가 없습니다. 그 중 두 "에서 ... 원격 지점 생성"했다,하지만 난라는 지점이있을 사용되는 것을 알고 경우에도 B출처에, 그 알 수있는 방법이 없다 Z에서 생성을B, 아마도 그 과정에서 이름이 바뀌었기 때문일 것입니다. 따라서 실제로 분기 원본 메타 데이터를 기록하는 외부 프로세스가 없거나 기록을 아는 사람이 없으면 OP가 제거 대상인 세 분기 중 어느 것이 있는지 알 수 없습니다. git자동으로 유지되지 않는 외부 정보가 없으면 git fetch -p얻을 수있는 한 가깝고 OP가 요청한 것을 문자 그대로 시도하는 자동 방법은 너무 많은 분기를 삭제하거나 OP가 그렇지 않은 경우 일부를 누락 할 위험이 있습니다. 삭제를 원합니다.

다른 시나리오도 있습니다. 예를 들어, origin/A세 가지 다른 접근 방식을 테스트하기 위해 세 개의 개별 분기 를 만든 다음 origin/A사라지는 경우입니다. 이제 세 가지 브랜치가 있습니다. 분명히 모두 이름과 일치 할 수는 없지만에서 생성 origin/A되었으므로 OP 질문을 문자 그대로 해석하려면 세 가지를 모두 제거해야합니다. 그러나 신뢰할 수있는 방법을 찾을 수 있다면 바람직하지 않을 수 있습니다.


이렇게하면 원격 추적 분기가 정리 된 로컬 분기가 삭제됩니다. ( master지점 에 있는지 확인하십시오 !)

git checkout master
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -d

세부:

  • git branch -vv 원격이 정리 된 로컬 분기에 대해 "사라짐"을 표시합니다.

    mybranch abc1234 [origin/mybranch: gone] commit comments
    
  • -d병합되었는지 확인합니다 ( -D상관없이 삭제됩니다)

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

One can configure Git to automatically remove references to deleted remote branches when fetching:

git config --global fetch.prune true

When calling git fetch or git pull afterwards, references to deleted remote branches get removed automatically.


There's a neat NPM package that does it for you (and it should work cross platform).

Install it with: npm install -g git-removed-branches

And then git removed-branches will show you all the stale local branches, and git removed-branches --prune to actually delete them.

More info here.


Windows Solution

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

Explaination

git checkout master switches to the master branch

git remote update origin --prune prunes remote branches

git branch -vv gets a verbose output of all branches (git reference)

Select-String -Pattern ": gone]" gets only the records where they have been removed from remote.

% { $_.toString().Split(" ")[0]} get the branch name

% {git branch -d $_} deletes the branch


It will list the local branches whose remote tracking branch is deleted from remote

$ git remote prune origin --dry-run

If you want to de-reference these local branches from local which are un tracked

$ git remote prune origin

If using Windows and Powershell, you can use the following to delete all local branches that have been merged into the branch currently checked out:

git branch --merged | ? {$_[0] -ne '*'} | % {$_.trim()} | % {git branch -d $_}

Explanation

  • Lists the current branch and the branches that have been merged into it
  • Filters out the current branch
  • Cleans up any leading or trailing spaces from the git output for each remaining branch name
  • Deletes the merged local branches

It's worth running git branch --merged by itself first just to make sure it's only going to remove what you expect it to.

(Ported/automated from http://railsware.com/blog/2014/08/11/git-housekeeping-tutorial-clean-up-outdated-branches-in-local-and-remote-repositories/.)


I wanted something that would purge all local branches that were tracking a remote branch, on origin, where the remote branch has been deleted (gone). I did not want to delete local branches that were never set up to track a remote branch (i.e.: my local dev branches). Also, I wanted a simple one-liner that just uses git, or other simple CLI tools, rather than writing custom scripts. I ended up using a bit of grep and awk to make this simple command, then added it as an alias in my ~/.gitconfig.

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -D

Here is a git config --global ... command for easily adding this as 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'

NOTE: Use of the -D flag to git branch can be very dangerous. So, in the config command above I use the -d option to git branch rather than -D; I use -D in my actual config. I use -D because I don't want to hear Git complain about unmerged branches, I just want them to go away. You may want this functionality as well. If so, simply use -D instead of -d at the end of that config command.


Even shorter and safer one-liner:

git branch -d $(git branch --merged | cut -c 3- | grep -v master)

Be sure to checkout to branch that is not merged yet, before run it. Because you can not delete branch that you are currently checked in.


not sure how to do it all at once, but git git branch -d <branchname> will delete a local branch ONLY if it is completely merged. Note the lowercase d.

git branch -D <branchname> (note the capital D) will delete a local branch regardless of its merged status.


To remove remote branches

$git remote prune origin

To remove local branches that are already merged

$git branch -D $(git branch --merged)

As @tzacks notes... there is an npm package that is handy for this. Just do:

npx git-removed-branches --prune

(I would have commented but not enough reputation)


You can use this command:

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

Git Clean: Delete Already-Merged Branches including break down of command


There doesn't seem to be a safe one-liner, too many edge cases (like a branch having "master" as part of its name, etc). Safest is these steps:

  1. git branch -vv | grep 'gone]' > stale_branches.txt
  2. view the file and remove lines for branches you want to keep (such as master branch!); you don't need to edit the contents of any line
  3. awk '{print $1}' stale_branches.txt | xargs git branch -d

Based on the answers above I'm using this shorter one liner:

git remote prune origin | awk 'BEGIN{FS="origin/"};/pruned/{print $2}' | xargs -r git branch -d

Also, if you already pruned and have local dangling branches, then this will clean them up:

git branch -vv | awk '/^ .*gone/{print $1}' | xargs -r git branch -d

Based on the answers above I came with this one line solution:

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

Using a variant on @wisbucky's answer, I added the following as an alias to my ~/.gitconfig file:

pruneitgood = "!f() { \
    git remote prune origin; \
    git branch -vv | perl -nae 'system(qw(git branch -d), $F[0]) if $F[3] eq q{gone]}'; \
}; f"

With this, a simple git pruneitgood will clean up both local & remote branches that are no longer needed after merges.


Schleis' variant does not work for me (Ubuntu 12.04), so let me propose my (clear and shiny :) variants:

Variant 1 (I would prefer this option):

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

Variant 2:

a. Dry-run:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | awk '{print "git branch -D " $1}'

b. Remove branches:

comm -23 <( git branch | grep -v "/" | grep -v "*" | sort ) <( git br -r | awk -F '/' '{print $2}' | sort ) | xargs git branch -D

Following is an adaptation of @wisbucky's answer for Windows users:

for /f "tokens=1" %i in ('git branch -vv ^| findstr ": gone]"') DO git branch %i -d

I use posh-git and unfortunately PS doesn't like the naked for, so I created a plain 'ol command script named PruneOrphanBranches.cmd:

@ECHO OFF
for /f "tokens=1" %%i in ('git branch -vv ^| findstr ": gone]"') DO CALL :ProcessBranch %%i %1

GOTO :EOF

:ProcessBranch
IF /I "%2%"=="-d" (
    git branch %1 %2
) ELSE (
    CALL :OutputMessage %1
)
GOTO :EOF

:OutputMessage
ECHO Will delete branch [%1] 
GOTO :EOF

:EOF

Call it with no parameters to see a list, and then call it with "-d" to perform the actual deletion or "-D" for any branches that are not fully merged but which you want to delete anyway.


Try this in git bash, to fetch and prune references to deleted branches, and then prune the local branches that were tracking the removed ones:

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

Remember to checkout first a branch that won't be deleted, so that does not block the deleting of the branch.


The Powershell Version of git branch --merged master | grep -v '^[ *]*master$' | xargs git branch -d

git branch --merged master | %{ if($_ -notmatch '\*.*master'){ git branch -d "$($_.Trim())" }}

This will remove any local branches that have been merged into master, while you are on the master branch.

git checkout master to switch.


I have turned the accepted answer into a robust script. You'll find it in my git-extensions repository.

$ git-prune --help
Remove old local branches that do not exist in <remote> any more.
With --test, only print which local branches would be deleted.
Usage: git-prune [-t|--test|-f|--force] <remote>

I reached this page seeking the answer for "how do I delete locally checked out branches that no longer have an upstream branch"

I also did not care whether or not the local branch had been merged in yet, since piping into git branch -d will simply warn instead of deleting unmerged local branches.

git branch -a | grep origin | tr -s ' ' | cut -d '/' -f3 | egrep -v -f /dev/fd/0 <(git branch -a | grep -v origin) | grep branch_prefix_that_I_care_about | xargs git branch -d

# translation
# git branch -a | grep origin | tr -s ' ' | cut -d '/' -f3
## this finds all remote branch names minus the "remote/origin/" part
#
# <(git branch -a | grep -v origin)
## this finds all local branch names and redirects it into the previous command
#
# egrep -v -f /dev/fd/0 STUFF
## this is doing some weird magic that I'm grokking as "take the set difference from whatever was piped in"
#
#
# overall translation: (STUFF TO CONSIDER) | egrep magic <(STUFF TO REMOVE FROM CONSIDERATION) | do cool things with resulting stuff

In Powershell:

git branch -D (git branch --merged |% { $_.trim() } )

Delete any branch that isn't up to date with master

git co master && git branch | sed s/\*/\ / | xargs git branch -d 2> /dev/null

I'm pretty sure that git remote prune origin is what you want.

You can run it as git remote prune origin --dry-run to see what it would do without making any changes.


Using the GUI? Manual procedure, but quick and easy.

$ git gui

Select "Branch -> Delete". You can select multiple branches with ctrl-click (windows) and remove all of them.

참고URL : https://stackoverflow.com/questions/13064613/how-to-prune-local-tracking-branches-that-do-not-exist-on-remote-anymore

반응형