Liệt kê từng chi nhánh và ngày sửa đổi cuối cùng của nó trong Git


138

Tôi cần xóa các nhánh cũ và không xác định khỏi kho lưu trữ từ xa của chúng tôi. Tôi đang cố gắng tìm cách liệt kê các chi nhánh từ xa vào ngày sửa đổi cuối cùng của họ và tôi không thể.

Có một cách dễ dàng để liệt kê các chi nhánh từ xa theo cách này?



3
Các câu trả lời cho: stackoverflow.com/questions/5188320/ tất cả đều tốt hơn các câu trả lời ở đây
Kỹ sư phần mềm

Câu trả lời:


172

Commandlinefu có 2 mệnh đề thú vị:

for k in `git branch | perl -pe s/^..//`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

hoặc là:

for k in `git branch | sed s/^..//`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k --`\\t"$k";done | sort

Đó là cho các nhánh cục bộ, theo cú pháp Unix. Sử dụng git branch -r, bạn có thể hiển thị tương tự các chi nhánh từ xa:

for k in `git branch -r | perl -pe 's/^..(.*?)( ->.*)?$/\1/'`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

Michael Forrest đề cập trong các ý kiến rằng zsh yêu cầu thoát cho sedbiểu thức:

for k in git branch | perl -pe s\/\^\.\.\/\/; do echo -e git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1\\t$k; done | sort -r 

liên tục thêm vào trong các ý kiến :

Nếu bạn muốn thêm nó, zshrc của bạn, lối thoát sau là cần thiết.

alias gbage='for k in `git branch -r | perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r'

Trong nhiều dòng:

alias gbage='for k in `git branch -r | \
  perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; \
  do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | \
     head -n 1`\\t$k; done | sort -r'

Lưu ý: câu trả lời của n8tr , dựa trên là sạch hơn. Và nhanh hơn . Xem thêm " Tên chỉ tùy chọn cho ?git for-each-ref refs/heads
git branch --list "

Tổng quát hơn, tripleee nhắc nhở chúng ta trong các ý kiến :

  • Thích $(command substitution)cú pháp hiện đại hơn cú pháp backtick lỗi thời.

(Tôi đã minh họa điểm đó vào năm 2014 với " Sự khác biệt giữa $(command)`command`trong lập trình shell là gì? ")


1
@hansen j: thú vị phải không? Nó đã ra mắt vài tháng sau khi phát hành công khai Stack Overflow ( codeinthehole.com/archives/ ,) và được truyền cảm hứng bởi SO. Xem thêm Commandlinefu.com/commands/tagged/67/git để biết thêm git Commandlinefu;)
VonC

Câu trả lời này đá stackoverflow.com/questions/5188320/ ass của. :)
Spundun

@SebastianG không chắc chắn: đó sẽ là một câu hỏi hay của riêng nó.
VonC

+1 Khá tuyệt vời về cách bạn có thể thêm /jsonvào cuối bất kỳ URL nào của dòng lệnh và bạn sẽ nhận được tất cả các lệnh dưới dạng JSON.

1
@tripleee Cảm ơn bạn. Tôi đã chỉnh sửa câu trả lời và bao gồm các ý kiến ​​của bạn để dễ nhìn hơn.
VonC

121

Đây là những gì tôi sử dụng:

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads

Đây là đầu ra:

2014-01-22 11:43:18 +0100       refs/heads/master
2014-01-22 11:43:18 +0100       refs/heads/a
2014-01-17 12:34:01 +0100       refs/heads/b
2014-01-14 15:58:33 +0100       refs/heads/maint
2013-12-11 14:20:06 +0100       refs/heads/d/e
2013-12-09 12:48:04 +0100       refs/heads/f

Đối với các chi nhánh từ xa, chỉ cần sử dụng "refs / remote" thay vì "refs / Heads":

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/remotes

Dựa trên câu trả lời của n8tr , nếu bạn cũng quan tâm đến tác giả cuối cùng trên chi nhánh và nếu bạn có sẵn công cụ "cột", bạn có thể sử dụng:

git for-each-ref --sort='-committerdate:iso8601' --format='%(committerdate:relative)|%(refname:short)|%(committername)' refs/remotes/ | column -s '|' -t

Mà sẽ cung cấp cho bạn:

21 minutes ago  refs/remotes/a        John Doe
6 hours ago     refs/remotes/b        Jane Doe
6 days ago      refs/remotes/master   John Doe

Bạn có thể muốn gọi "git fetch --prune" trước để có thông tin mới nhất.


5
Sử dụng tốt cho mỗi-ref và các tùy chọn định dạng. +1. Âm thanh dễ dàng hơn các lệnh tôi tham khảo trong câu trả lời của riêng tôi.
VonC

2
tinh chỉnh một chút: ------- git for-Each-ref --sort = '- authordate: iso8601' --format = '% (authordate: tương đối)% 09% (refname: short)' refs / Heads ------- cung cấp cho bạn một ngày tương đối và loại bỏ các ref / người đứng đầu
n8tr

1
Đối với những người không rõ ràng ngay lập tức, tôi nghĩ rằng điều này hiển thị thông tin. nghiêm ngặt cho các chi nhánh địa phương.
hBrent

@hBrent bạn nói đúng, nó không trả lời chính xác câu hỏi. Tôi đã chỉnh sửa câu trả lời của tôi cho phù hợp.
ocroquette

Điều này sắp xếp và liệt kê các nhánh theo authordate(dường như là khi nhánh đầu tiên được tạo?). Nếu bạn thay đổi authordatethành committerdatethì bạn sẽ thấy ngày của cam kết gần đây nhất trong mỗi chi nhánh. Giống như vậy:git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads
Logan Besecker

23

Xây dựng Olivier Croquette , tôi thích sử dụng một ngày tương đối và rút ngắn tên chi nhánh như thế này:

git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads

Cung cấp cho bạn đầu ra:

21 minutes ago  nathan/a_recent_branch
6 hours ago        master
27 hours ago    nathan/some_other_branch
29 hours ago    branch_c
6 days ago      branch_d

Tôi khuyên bạn nên tạo một tệp Bash để thêm tất cả các bí danh yêu thích của bạn và sau đó chia sẻ tập lệnh ra cho nhóm của bạn. Đây là một ví dụ để thêm chỉ cái này:

#!/bin/sh

git config --global alias.branches "!echo ' ------------------------------------------------------------' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------'"

Sau đó, bạn chỉ có thể làm điều này để có được một danh sách chi nhánh địa phương được định dạng và sắp xếp độc đáo:

git branches

20

Chỉ cần thêm vào nhận xét của @VonC, lấy giải pháp ưa thích của bạn và thêm nó vào danh sách bí danh ~ / .gitconfig để thuận tiện:

[alias]  
    branchdate = !git for-each-ref --sort='-authordate' --format='%(refname)%09%(authordate)' refs/heads | sed -e 's-refs/heads/--'

Sau đó, một "git Branchdate" đơn giản sẽ in danh sách cho bạn ...


3
+1 để hiển thị cách sử dụng với .gitconfig! Ngoài ra fwiw tôi đã thay đổi chuỗi định dạng thành: --format='%(authordate)%09%(objectname:short)%09%(refname)'cũng có hàm băm ngắn của mỗi nhánh.

Đẹp. Tôi đã thêm "| tac" vào cuối để sắp xếp nó theo thứ tự ngược lại để các nhánh được chạm gần đây nhanh chóng hiển thị.
Ben

1
Bạn không cần | tac, chỉ --sort='authordate'thay vì-authordate
Kristján

4

Đây là những gì tôi đã đưa ra sau khi xem xét này .

for REF in $(git for-each-ref --sort=-committerdate --format="%(objectname)" \
    refs/remotes refs/heads)
do
    if [ "$PREV_REF" != "$REF" ]; then
        PREV_REF=$REF
        git log -n1 $REF --date=short \
            --pretty=format:"%C(auto)%ad %h%d %s %C(yellow)[%an]%C(reset)"
    fi
done

Các PREV_REF kiểm tra là để loại bỏ các bản sao nếu có nhiều hơn một điểm chi nhánh với cùng cam kết. (Giống như trong một nhánh cục bộ tồn tại ở xa.)

LƯU Ý rằng theo yêu cầu OP git branch --mergedgit branch --no-mergedrất hữu ích trong việc xác định các nhánh nào có thể dễ dàng xóa.

[ https://git-scm.com/docs/git-branch]


3

Sắp xếp các nhánh từ xa và ngày cam kết cuối cùng cho mỗi nhánh.

for branch in `git branch -r | grep -v HEAD`;do echo -e `git show --format="%ci %cr" $branch | head -n 1` \\t$branch; done | sort -r

1
Cảm ơn bạn đã trả lời câu hỏi OP liên quan đến điều khiển từ xa.
arcseldon

1

Tôi đã thực hiện hai biến thể, dựa trên câu trả lời của VonC .

Biến thể đầu tiên của tôi:

for k in `git branch -a | sed -e s/^..// -e 's/(detached from .*)/HEAD/'`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`;done | sort | column -t -s "|"

Điều này xử lý các nhánh cục bộ và từ xa ( -a), xử lý trạng thái tách rời (lệnh sed dài hơn, mặc dù giải pháp này khá thô sơ - nó chỉ thay thế thông tin nhánh tách rời bằng từ khóa HEAD), thêm vào chủ đề cam kết (% s ) và đặt mọi thứ vào các cột thông qua các ký tự ống theo nghĩa đen trong chuỗi định dạng và chuyển kết quả cuối cùng cho column -t -s "|". (Bạn có thể sử dụng bất cứ thứ gì làm dấu phân cách, miễn là đó là thứ bạn không mong đợi trong phần còn lại của đầu ra.)

Biến thể thứ hai của tôi khá hack, nhưng tôi thực sự muốn một cái gì đó vẫn có chỉ báo "đây là nhánh bạn đang sử dụng" giống như lệnh nhánh.

CURRENT_BRANCH=0
for k in `git branch -a | sed -e 's/\*/CURRENT_BRANCH_MARKER/' -e 's/(detached from .*)/HEAD/'`
do
    if [ "$k" == 'CURRENT_BRANCH_MARKER' ]; then
        # Set flag, skip output
        CURRENT_BRANCH=1
    elif [ $CURRENT_BRANCH == 0 ]; then
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`
    else
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset* %Cgreen$k%Creset |%s" $k --`
        CURRENT_BRANCH=0
    fi
done | sort | column -t -s "|"

Điều này biến *cái đánh dấu nhánh hiện tại thành một từ khóa và khi thân vòng lặp nhìn thấy từ khóa, nó thay vào đó đặt cờ và không cho ra kết quả gì. Cờ được sử dụng để chỉ ra rằng một định dạng thay thế nên được sử dụng cho dòng tiếp theo. Như tôi đã nói, nó hoàn toàn hacky, nhưng nó hoạt động! (Chủ yếu. Vì một số lý do, cột cuối cùng của tôi đang bị lỗi thời trên dòng nhánh hiện tại.)


Thật không may, thông tin trong câu trả lời của VonC không phải là nền tảng tuyệt vời cho kịch bản. Xem tại đây git-blame.blogspot.com/2013/06/ Kẻ
Andrew C

Hừm. Điều đó cho thấy một cách để có được tên của chi nhánh hiện tại, nếu nó có một tên. Có cách [ưa thích] nào để có được danh sách các chi nhánh thân thiện với máy không? (Và một số cách để phân biệt các chi nhánh hiện tại, hoặc từ đầu ra trực tiếp hoặc thông qua bằng cách nào đó hỏi git "đây là ref giống như HEAD?")
benkc

git for-each-reflà cách thân thiện với kịch bản xử lý các nhánh. Bạn sẽ phải chạy ref-tượng trưng một lần để có được chi nhánh hiện tại.
Andrew C

+1 cho nỗ lực, nhưng đó thực sự là một câu trả lời của tôi. stackoverflow.com/a/16971547/6309 hoặc (đầy đủ hơn) stackoverflow.com/a/19585361/6309 có thể liên quan đến ít 'sed' hơn.
VonC

1

Tôi đã làm một bí danh đơn giản, không chắc đây có phải là câu hỏi chính xác không, nhưng nó đơn giản

Tôi đã làm điều này vì tôi muốn liệt kê tất cả các nhánh không chỉ các nhánh cục bộ của tôi, mà các lệnh trên chỉ làm

alias git_brs="git fetch && git branch -av --format='\''%(authordate)%09%(authordate:relative)%09%(refname)'\'"

Bạn có thể đặt ống ở trên để grep originchỉ lấy nguồn gốc

Điều này liệt kê tất cả các chi nhánh cùng với ngày cuối cùng được sửa đổi, giúp tôi quyết định nên chọn cái nào cho phiên bản mới nhất

Điều này dẫn đến loại màn hình dưới đây

Wed Feb 4 23:21:56 2019 +0230   8 days ago      refs/heads/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/heads/master
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/heads/bar
Wed Feb 11 16:34:00 2019 +0230  2 days ago      refs/heads/xyz
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/HEAD
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/remotes/origin/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/master
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/bar
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/xyz

Hãy thử và cho tôi biết nếu nó giúp, gits hạnh phúc


Đẹp và đơn giản. Không có nước sốt đặc biệt.
MrMas

0

Hoặc bạn có thể sử dụng tập lệnh PHP của tôi, https://gist.github.com/2780984

#!/usr/bin/env php
<?php
    $local = exec("git branch | xargs $1");
    $lines = explode(" ", $local);
    $limit = strtotime("-2 week");
    $exclude = array("*", "master");
    foreach ($exclude as $i) {
        $k = array_search($i, $lines);
        unset($lines[$k]);
    }
    $k = 0;
    foreach ($lines as $line) {
        $output[$k]['name'] = $line;
        $output[$k]['time'] = exec('git log '.$line.' --pretty=format:"%at" -1');
        if ($limit>$output[$k]['time']) {
            echo "This branch should be deleted $line\n";
            exec("git branch -d $line");
        }
        $k++;
    }
?>

0

Đây là một chức năng bạn có thể thêm vào bash_profile của mình để làm cho việc này dễ dàng hơn.

Cách sử dụng khi trong kho Git:

  • branch in tất cả các chi nhánh địa phương
  • branch -r in tất cả các chi nhánh từ xa

Chức năng:

branch() {
   local pattern="s/^..//"
   local arg=""
   if [[ $@ == "-r" ]]; then
      pattern="s/^..(.*?)( ->.*)?$/\1/"
      arg=" -r "
      echo '-r provided'
   fi
   for k in $(git branch $arg | perl -pe "$pattern"); do
      echo -e $(git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1)\\t$k
   done | sort -r
}

0

Trong PowerShell, phần sau đây hiển thị các nhánh trên điều khiển từ xa đã được hợp nhất và ít nhất hai tuần tuổi ( author:relativeđịnh dạng bắt đầu hiển thị tuần thay vì ngày ở hai tuần):

$safeBranchRegex = "origin/(HEAD|master|develop)$";
$remoteMergedBranches = git branch --remote --merged | %{$_.trim()};
git for-each-ref --sort='authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/remotes | ?{$_ -match "(weeks|months|years) ago" -and $_ -notmatch "origin/(HEAD|master|qa/)"} | %{$_.substring($_.indexof("origin/"))} | ?{$_ -in $remoteMergedBranches}
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.