Liệt kê tất cả các chi nhánh địa phương mà không cần điều khiển từ xa


91

Vấn đề: Tôi muốn có một cách để xóa tất cả các nhánh cục bộ mà tôi có mà không có điều khiển từ xa. Thật dễ dàng để gộp tên các nhánh thành a git branch -D {branch_name}, nhưng làm cách nào để lấy danh sách đó ngay từ đầu?

Ví dụ:

Tôi tạo một nhánh mới mà không có điều khiển:

$ git co -b no_upstream

Tôi liệt kê tất cả các chi nhánh của mình và chỉ có một chi nhánh có điều khiển từ xa

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

Tôi có thể chạy lệnh nào để nhận được no_upstreamcâu trả lời?

Tôi có thể chạy git rev-parse --abbrev-ref --symbolic-full-name @{u}và điều đó sẽ cho thấy rằng nó không có điều khiển từ xa:

$ 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>...]'

Nhưng vì đây là một lỗi, nó sẽ không cho phép tôi sử dụng nó hoặc chuyển nó sang các lệnh khác. Tôi đang có ý định sử dụng nó như một bí danh shell script git-delete-unbranchedhoặc có thể tạo ra một viên ngọc siêu đơn giản nhưgit-branch-delete-orphans



Câu trả lời:


103

Gần đây tôi đã phát hiện ra git branch -vvđó là phiên bản "rất dài dòng" của git branchlệnh.

Nó xuất ra các nhánh cùng với các nhánh ở xa nếu chúng tồn tại, ở định dạng sau:

  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

Khi bạn có đầu ra được định dạng độc đáo này, thật dễ dàng như chuyển nó qua cutawklấy danh sách của bạn:

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

Kết quả trong đầu ra sau:

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

Các cutphần chỉ bình thường hóa dữ liệu bằng cách loại bỏ hai ký tự đầu tiên (bao gồm *) từ đầu ra trước khi đi qua nó để awk.

Các awkphần in cột đầu tiên nếu không có khung vuông trong cột thứ ba.

Phần thưởng: Tạo bí danh

Giúp dễ dàng chạy bằng cách tạo bí danh trong .gitconfigtệp chung của bạn (hoặc bất cứ nơi nào):

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

Quan trọng: Dấu gạch chéo ngược cần phải được thoát trong bí danh, nếu không bạn sẽ có tệp gitconfig không hợp lệ.

Phần thưởng: Lọc từ xa

Nếu vì lý do nào đó, bạn có nhiều điều khiển từ xa theo dõi cho các chi nhánh khác nhau, bạn có thể dễ dàng chỉ định điều khiển từ xa nào bạn muốn kiểm tra. Chỉ cần nối tên từ xa vào mẫu awk. Trong trường hợp của tôi, origintôi có thể làm điều này:

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

Đó là cái WIP:gì ..? đó không phải là những gì một lệnh lưu trữ tạo ra ..?
igrek

@igrek Đó chỉ là tiền tố tôi đã sử dụng trong thông báo cam kết. Không có gì cụ thể cho git.
Jeremy Baker

khi tôi làm vậy git branch -vv, ngay cả khi một nhánh từ xa tồn tại và khớp với nhánh cục bộ của tôi, tôi sẽ không thấy [origin/branch-name]cùng với kết quả. Tôi đã phải đến diffhai danh sách các chi nhánh để thực sự tìm ra đâu là chỉ địa phương.
ryantuck

git branch -vv | grep -v origin/đối với tôi là đủ rồi
đừng hoảng sợ

2
Điều này không bỏ lỡ các chi nhánh từ xa được đánh dấu gone?
Reid

36

git branch (không có bất kỳ tùy chọn nào) chỉ liệt kê các chi nhánh cục bộ, nhưng bạn không biết liệu họ có đang theo dõi một chi nhánh từ xa hay không.

Thông thường những nhánh cục bộ đó sẽ bị xóa sau khi hợp nhất vào master(như đã thấy trong vấn đề git-scan này ):

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

Điều này không hoàn chỉnh như bạn muốn, nhưng nó là một sự khởi đầu.

Với --merged, chỉ các nhánh được hợp nhất vào cam kết đã đặt tên (tức là các nhánh có cam kết đầu có thể truy cập được từ cam kết đã đặt tên) mới được liệt kê.


1
Để bao gồm các chi nhánh từ xa mà không có chi nhánh cục bộ, hãy sử dụng git branch -a --merged.
Acumenus

21

Tôi có một vấn đề tương tự. Tôi muốn xóa tất cả các chi nhánh cục bộ đang theo dõi các chi nhánh từ xa hiện đã bị xóa. Tôi thấy rằng git remote prune originkhông đủ để loại bỏ các nhánh mà tôi muốn đi. Khi điều khiển từ xa bị xóa, tôi cũng muốn cục bộ biến mất. Đây là những gì đã làm việc cho tôi:

Từ của tôi ~/.gitconfig:

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

Đây là một git config --global ...lệnh để dễ dàng thêm điều này như 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'

LƯU Ý : Tôi đã thay đổi -dthành -Dtrong cấu hình thực của mình, vì tôi không muốn nghe Git phàn nàn về các nhánh chưa được hợp nhất. Bạn cũng có thể muốn chức năng này. Nếu vậy, chỉ cần sử dụng -Dthay vì -dở cuối lệnh đó.

Ngoài ra, FWIW, tệp cấu hình chung của bạn hầu như sẽ luôn như vậy ~/.gitconfig.

(Sửa chữa OS X)

Như đã viết, điều này không hoạt động trên OS X vì việc sử dụng xargs -r(cảm ơn, Korny ).

Các -rlà để ngăn chặn xargschạy git branch -dmà không có một tên chi nhánh, mà sẽ cho kết quả trong một thông báo lỗi " fatal: branch name required". Nếu bạn không bận tâm đến thông báo lỗi, bạn có thể chỉ cần xóa -rđối số xargsvà bạn đã sẵn sàng.

Tuy nhiên, nếu bạn không muốn thấy thông báo lỗi (và thực sự, ai có thể đổ lỗi cho bạn) thì bạn sẽ cần một thứ khác để kiểm tra đường ống trống. Nếu bạn có thể sử dụng ifne từ moreutils . Bạn sẽ chèn ifnetrước xargsđó, điều này sẽ ngừng xargschạy với dữ liệu trống. LƯU Ý : ifnecoi bất kỳ thứ gì là không trống, điều này bao gồm các dòng trống, vì vậy bạn vẫn có thể thấy thông báo lỗi đó. Tôi chưa thử nghiệm điều này trên OS X.

Đây là git configdòng với 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
Có thể chuyển đổi lệnh này thành lệnh "git config --global ..." không? Từ một lệnh / how-to-wiki-cho-núm vú cao su chỉ nhìn nó rất dễ dàng để vượt qua trên thay vì nói "Tìm hiểu file git config của bạn, biên tập viên sử dụng để chỉnh sửa nó lệnh sau đó chạy"
Kannan Ekanath


Tốt để biết. Tôi không biết tùy chọn "không chạy nếu trống" sẽ là gì đối với OSX.
Karl Wilbur

18

Chỉnh sửa muộn:

Tốt hơn là

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

Trên GNU / mọi thứ

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

Nếu có thể có nhiều hơn một số nhánh, thì sẽ có nhiều cách tốt hơn, sử dụng comm -23đầu ra của 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

Điều này phù hợp với tôi:

git branch -vv | grep -v origin

(nếu điều khiển từ xa của bạn được đặt tên khác với nguồn gốc, hãy thay thế điều đó).

Điều này sẽ liệt kê tất cả các nhánh không theo dõi điều khiển từ xa, điều này có vẻ giống như những gì bạn đang tìm kiếm.


2
Điều này sẽ liệt kê các nhánh đã từng có điều khiển từ xa nhưng không còn nữa ngay cả khi bạn chạy git fetch --prune.
RusinaRange

2
IMO, nó được tốt hơn tìm kiếm ": biến mất]" thay vì lọc ra những "nguồn gốc"
fiorentinoing

4

Tôi tổng hợp lệnh Git của riêng mình để lấy các origin/***: gonenhánh:

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 sẽ in các nhánh ở chế độ tiết.

cut -c 3- sẽ xóa các ký tự đầu tiên.

grep ': gone]'sẽ chỉ in các chi nhánh đã biến mất .

awk '{print $1}' sẽ in tên chi nhánh.

xargs -n1 -r echo git branch -dsẽ in git branch -dlệnh để loại bỏ các nhánh (-n1 sẽ quản lý một lệnh mỗi lần, -r để tránh ra lệnh nếu không có nhánh nào).

GỢI Ý: loại bỏ lệnh "echo" để chạy các lệnh thay vì chỉ in, tôi để điều này trong lệnh để kiểm tra các lệnh trước khi cấp cho git.

GỢI Ý 2: vấn đề git branch -Dnếu và chỉ khi bạn chắc chắn muốn loại bỏ các nhánh chưa hợp nhất


từ việc này, tôi đã thực hiện git
fiorentinoing

1
Đây là bởi đến nay các giải pháp sạch tôi đã tìm thấy, tốt đẹp! Tôi chưa bao giờ dành thời gian cho việc học awk, tôi không biết bạn có thể làm được điều đó.
adamjc

2

Đây là một cái gì đó tôi đã sử dụng trong PowerShell với các nhận xét để giải thích những gì nó đang làm. Trong một nỗ lực để làm rõ điều gì đang xảy ra, tôi đã không sử dụng bất kỳ lệnh PowerShell viết tắt nào (bí danh). Hãy nén nó đến mức độ khó hiểu mong muốn của bạn :)

$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

Kết hợp một số câu trả lời hiện có:

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

Ví dụ:

$ 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.