แสดงแต่ละสาขาและวันที่แก้ไขล่าสุดใน Git


138

ฉันต้องการลบสาขาเก่าและไม่มีการลบออกจากที่เก็บข้อมูลระยะไกลของเรา ฉันกำลังพยายามหาวิธีที่จะแสดงรายการสาขาระยะไกลตามวันที่แก้ไขล่าสุดของพวกเขาและฉันไม่สามารถ

มีวิธีง่าย ๆ ในการแสดงรายการสาขาระยะไกลด้วยวิธีนี้หรือไม่?



3
คำตอบสำหรับ: stackoverflow.com/questions/5188320/…ทั้งหมดดีกว่าคำตอบที่นี่
วิศวกรซอฟต์แวร์

คำตอบ:


172

commandlinefuมี 2 ​​ข้อเสนอที่น่าสนใจ:

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

หรือ:

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

สำหรับสาขาท้องถิ่นในรูปแบบ Unix การใช้git branch -rคุณสามารถแสดงสาขาระยะไกลในทำนองเดียวกัน:

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กล่าวถึงในความคิดเห็นที่ zsh ต้องการทางหนีสำหรับsedนิพจน์:

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 

kontinuityเพิ่มในความคิดเห็น :

หากคุณต้องการเพิ่ม zshrc ของคุณจำเป็นต้องมีการหลีกเลี่ยงต่อไปนี้

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'

ในหลายบรรทัด:

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'

หมายเหตุ: คำตอบของn8trอ้างอิงจากว่าสะอาดกว่า และเร็วขึ้น ดูเพิ่มเติม " ชื่อตัวเลือกเดียวสำหรับ? "git for-each-ref refs/heads
git branch --list

โดยทั่วไปTripleeeเตือนเราในความคิดเห็นที่ :

  • ต้องการ$(command substitution)ไวยากรณ์ที่ทันสมัยมากกว่าไวยากรณ์ backtick ที่ล้าสมัย

(ฉันแสดงให้เห็นถึงจุดนั้นในปี 2014 ด้วย " ความแตกต่างระหว่าง$(command)และ`command`ในการเขียนโปรแกรมเชลล์คืออะไร ")

  • forอย่าอ่านบรรทัดด้วย
  • อาจเปลี่ยนเป็นgit for-each-ref refs/remoteรับชื่อสาขาระยะไกลในรูปแบบที่เครื่องอ่านได้

1
@hansen j: น่าสนใจใช่มั้ย มันเปิดตัวไม่กี่เดือนหลังจากการปล่อยสแต็คโอเวอร์โฟลว์ ( codeinthehole.com/archives/… ) สาธารณะและได้รับแรงบันดาลใจจาก SO ดูเพิ่มเติมcommandlinefu.com/commands/tagged/67/gitสำหรับcommandlinefu git เพิ่มเติม;)
VonC

คำตอบนี้เตะstackoverflow.com/questions/5188320/... 's ตูด :)
Spundun

@SebastianG ไม่แน่ใจ: นั่นจะเป็นคำถามที่ดีของตัวเอง
VonC

+1 น่ากลัวมากที่คุณสามารถเพิ่ม/jsonท้ายcommandlinefu.com URL ใด ๆและคุณจะได้รับคำสั่งทั้งหมดเป็น JSON
Noah Sussman

1
@tripleee ขอบคุณ ฉันได้แก้ไขคำตอบและรวมความคิดเห็นของคุณเพื่อให้มองเห็นได้มากขึ้น
VonC

121

นี่คือสิ่งที่ฉันใช้:

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

นี่คือผลลัพธ์:

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

สำหรับสาขารีโมตให้ใช้ "refs / remotes" แทน "refs / heads":

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

การสร้างคำตอบของ n8trหากคุณสนใจผู้เขียนคนสุดท้ายในสาขาและหากคุณมีเครื่องมือ "คอลัมน์" คุณสามารถใช้:

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

ซึ่งจะให้:

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

คุณอาจต้องการเรียก "git fetch --prune" ก่อนเพื่อรับข้อมูลล่าสุด


5
การใช้งานที่ดีสำหรับการอ้างอิงแต่ละครั้งและตัวเลือกรูปแบบ +1 ฟังดูง่ายกว่าคำสั่งที่ฉันอ้างอิงในคำตอบของฉันเอง
VonC

2
ปรับแต่งเล็กน้อย: ------- คอมไพล์สำหรับแต่ละอ้างอิง --sort = '- authordate: iso8601' --format = '% (authordate: ญาติ)% 09% (refname: short)' refs / heads ------- ให้วันที่ที่เกี่ยวข้องกับคุณและกำจัดการอ้างอิง / หัว
n8tr

1
สำหรับผู้ที่ไม่ชัดเจนในทันทีฉันคิดว่านี่แสดงข้อมูล สำหรับสาขาท้องถิ่นอย่างเคร่งครัด
hBrent

@ hBrent คุณพูดถูกมันไม่ตอบคำถามแน่ชัด ฉันได้แก้ไขคำตอบของฉันแล้ว
ocroquette

เรียงลำดับและแสดงรายการสาขาตามauthordate(ซึ่งจะปรากฏเมื่อสร้างสาขาครั้งแรก) หากคุณเปลี่ยนauthordateเป็นcommitterdateคุณจะเห็นวันที่กระทำล่าสุดในแต่ละสาขา เช่นเดียวกับ:git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads
Logan Besecker

23

การสร้างจากOlivier Croquetteฉันชอบใช้วันที่ที่เกี่ยวข้องและทำให้ชื่อสาขาสั้นลงเช่นนี้:

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

ซึ่งให้ผลลัพธ์:

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

ฉันแนะนำให้สร้างไฟล์ Bash เพื่อเพิ่มนามแฝงที่คุณชื่นชอบทั้งหมดแล้วแชร์สคริปต์ให้ทีมของคุณ นี่คือตัวอย่างการเพิ่มอันนี้:

#!/bin/sh

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

จากนั้นคุณสามารถทำเช่นนี้เพื่อรับรายการรูปแบบสาขาและจัดเรียงอย่างดี:

git branches

20

เพียงเพิ่มความคิดเห็นโดย @VonC นำโซลูชันที่คุณต้องการและเพิ่มไปยังรายการนามแฝง ~ / .gitconfig เพื่อความสะดวก:

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

จากนั้น "git branchdate" แบบง่ายจะพิมพ์รายการให้คุณ ...


3
+1 สำหรับแสดงวิธีใช้กับ. gitconfig! นอกจากนี้ฉันยังเปลี่ยนรูปแบบสตริงเป็น: --format='%(authordate)%09%(objectname:short)%09%(refname)'ซึ่งได้รับแฮชแบบสั้นของแต่ละสาขาเช่นกัน
Noah Sussman

ดี ฉันจะเพิ่ม "| tac" ต่อท้ายเพื่อให้เรียงลำดับกลับกันเพื่อให้กิ่งที่เพิ่งสัมผัสถูกมองเห็นได้อย่างรวดเร็ว
เบ็น

1
คุณไม่จำเป็นต้อง| tacเพียง--sort='authordate'แทน-authordate
Kristjan

4

นี่คือสิ่งที่ฉันมาด้วยหลังจากนั้นก็ตรวจสอบนี้

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

PREV_REFตรวจสอบคือการลบรายการที่ซ้ำกันถ้ามีมากกว่าหนึ่งจุดที่ชี้ไปที่การกระทำเดียวกัน (เช่นเดียวกับในสาขาท้องถิ่นที่มีอยู่ในระยะไกลเช่นกัน)

โปรดทราบว่าตามคำขอ OP git branch --mergedและgit branch --no-mergedมีประโยชน์ในการระบุสาขาที่สามารถลบได้อย่างง่ายดาย

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


3

จัดเรียงสาขาระยะไกลและวันที่กระทำครั้งสุดท้ายสำหรับแต่ละสาขา

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
ขอบคุณสำหรับการตอบคำถาม OP เกี่ยวกับรีโมท
arcseldon

1

ผมทำสองสายพันธุ์ขึ้นอยู่กับคำตอบของ VonC

รุ่นแรกของฉัน:

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 "|"

นี้จัดการสาขาในประเทศและระยะไกล ( -a), จัดการสถานะเดี่ยว - หัว (คำสั่ง sed ที่ยาวกว่า, แม้ว่าการแก้ปัญหาจะเป็นชนิดหยาบ - มันเพียงแค่แทนที่ข้อมูลสาขาแยกออกด้วยคำหลัก HEAD) เพิ่มในหัวเรื่องกระทำ (% s ) column -t -s "|"และทำให้สิ่งที่เป็นตัวอักษรผ่านทางคอลัมน์ท่ออักษรในสตริงรูปแบบและผ่านการสิ้นผลไป (คุณสามารถใช้อะไรก็ได้เป็นตัวคั่นตราบใดที่มันเป็นสิ่งที่คุณไม่คาดหวังในส่วนที่เหลือของเอาท์พุท)

ตัวแปรที่สองของฉันค่อนข้างแฮ็ค แต่ฉันต้องการบางสิ่งที่ยังคงมีตัวบ่งชี้ว่า "นี่เป็นสาขาที่คุณกำลังใช้งานอยู่" เหมือนที่คำสั่งสาขาทำ

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 "|"

สิ่งนี้จะเปลี่ยนสิ่ง*ที่ทำเครื่องหมายสาขาปัจจุบันเป็นคำหลักและเมื่อเนื้อความลูปเห็นคำหลักมันจะตั้งค่าแฟล็กและเอาท์พุทอะไรแทน การตั้งค่าสถานะใช้เพื่อระบุว่าควรใช้การจัดรูปแบบทางเลือกสำหรับบรรทัดถัดไป อย่างที่ฉันบอกว่ามันแฮ็คทั้งหมด แต่ใช้งานได้! (ส่วนใหญ่ด้วยเหตุผลบางประการคอลัมน์สุดท้ายของฉันกำลังจะล้าสมัยในบรรทัดสาขาปัจจุบัน)


น่าเสียดายที่ข้อมูลในคำตอบของ VonC ไม่ใช่รากฐานที่ดีสำหรับการเขียนสคริปต์ ดูที่นี่git-blame.blogspot.com/2013/06/…
Andrew C

อืมมม นั่นแสดงวิธีรับชื่อของสาขาปัจจุบันหากมีชื่อ มีวิธีที่ [ที่ต้องการ] เพื่อให้ได้รายการสาขาที่เป็นมิตรกับเครื่องจักรหรือไม่? (และวิธีที่จะแยกสาขาปัจจุบันไม่ว่าจะเป็นจากเอาท์พุทโดยตรงหรือผ่านการขอ git "เป็นอ้างอิงเดียวกันกับ HEAD?")
benkc

git for-each-refเป็นวิธีที่ใช้งานง่ายในการประมวลผลสาขา คุณต้องใช้สัญลักษณ์อ้างอิงหนึ่งครั้งเพื่อรับสาขาปัจจุบัน
Andrew C

+1 สำหรับความพยายาม แต่นั่นเป็นคำตอบเดิมของฉัน stackoverflow.com/a/16971547/6309หรือ (สมบูรณ์มากขึ้น) stackoverflow.com/a/19585361/6309อาจเกี่ยวข้องกับ 'sed' น้อยกว่า
VonC

1

ฉันทำนามแฝงอย่างง่ายไม่แน่ใจว่านี่เป็นสิ่งที่ถามมาจริงหรือไม่ แต่มันง่าย

ฉันทำสิ่งนี้เพราะฉันต้องการที่จะแสดงรายการกิ่งไม้ทั้งหมดไม่เพียง แต่สาขาท้องถิ่นของฉันซึ่งคำสั่งข้างต้นทำเท่านั้น

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

คุณสามารถไปที่ด้านบนgrep originเพื่อรับต้นกำเนิดเท่านั้น

รายการนี้แสดงรายการสาขาทั้งหมดพร้อมกับวันที่แก้ไขล่าสุดช่วยให้ฉันตัดสินใจได้ว่าควรเลือกสาขาใดสำหรับรุ่นล่าสุด

ผลลัพธ์นี้แสดงประเภทด้านล่าง

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

ลองและแจ้งให้เราทราบหากมันช่วย gitting มีความสุข


ดีและเรียบง่าย ไม่มีซอสพิเศษ
MrMas

0

หรือคุณสามารถใช้สคริปต์ PHP ของฉัน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

นี่คือฟังก์ชันที่คุณสามารถเพิ่มใน bash_profile เพื่อให้ง่ายขึ้น

การใช้งานเมื่ออยู่ในที่เก็บ Git:

  • branch พิมพ์สาขาท้องถิ่นทั้งหมด
  • branch -r พิมพ์สาขาระยะไกลทั้งหมด

ฟังก์ชั่น:

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

ใน PowerShell ข้อมูลต่อไปนี้จะแสดงสาขาในรีโมทที่ผสานไปแล้วและอย่างน้อยสองสัปดาห์ ( author:relativeรูปแบบเริ่มแสดงสัปดาห์แทนวันที่สองสัปดาห์):

$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}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.