ฉันจะรับรายชื่อสาขา Git ได้รับคำสั่งจากการกระทำล่าสุดได้อย่างไร


1322

ฉันต้องการรับรายชื่อสาขาทั้งหมดในที่เก็บ Git ที่มีสาขา "สดที่สุด" ที่ด้านบนซึ่งสาขา "สดที่สุด" เป็นสาขาที่ได้รับการมุ่งมั่นที่จะล่าสุด (และดังนั้นจึงมีแนวโน้มที่จะเป็นหนึ่ง ฉันต้องการที่จะใส่ใจกับ)

มีวิธีที่ฉันสามารถใช้ Git เพื่อ (a) เรียงลำดับรายชื่อสาขาตามการกระทำล่าสุดหรือ (b) รับรายการสาขาพร้อมกับวันสุดท้ายที่กระทำแต่ละครั้งในรูปแบบที่เครื่องอ่านได้หรือไม่?

กรณีที่เลวร้ายที่สุดฉันสามารถเรียกใช้git branchรายการสาขาทั้งหมดแยกวิเคราะห์ผลลัพธ์จากนั้นgit log -n 1 branchname --format=format:%ciสำหรับแต่ละสาขาเพื่อรับวันที่ส่งมอบของแต่ละสาขา แต่สิ่งนี้จะทำงานบนกล่อง Windows ซึ่งการหมุนกระบวนการใหม่ค่อนข้างแพงดังนั้นการเปิดใช้งาน Git หนึ่งครั้งต่อสาขาอาจช้าลงหากมีสาขาจำนวนมาก มีวิธีทำทั้งหมดนี้ด้วยคำสั่งเดียว?


2
stackoverflow.com/a/2514279/1804124มีคำตอบที่ดีกว่า
Spundun

12
@Spunun คุณสูญเสียฉันไปแล้ว การรวมกันของหลายคำสั่งรวมถึงสิ่งที่ส่งผ่าน perl และ sed อย่างไร "ดีกว่า" กว่าการใช้คำสั่งที่ Git มีอยู่แล้ว
Joe White

36
@Spundun เกี่ยวกับคำตอบgit for-each-refจาก Jakub Narębski: คุณสามารถผ่านสาขาที่ห่างไกลrefs/remotes/แทนrefs/heads/(หรือคุณสามารถผ่านทั้งสองแยกจากกันด้วยช่องว่าง); refs/tags/สำหรับแท็กหรือเพียงrefs/สำหรับทั้งสามชนิด
jakub.g

4
เริ่มต้นคอมไพล์ 2.7 (Q4 2558), ไม่มีอีกแล้วfor-each-ref! คุณจะใช้โดยตรงgit branch --sort=-committerdate: ดูคำตอบของฉันด้านล่าง
VonC

1
อาจเป็นข้อมูลซ้ำซ้อนของstackoverflow.com/questions/9236219/…
Ondra Žižka

คำตอบ:


1874

ใช้--sort=-committerdateตัวเลือกของgit for-each-ref;

มีให้ตั้งแต่ Git 2.7.0สำหรับgit branch:

การใช้งานพื้นฐาน:

git for-each-ref --sort=-committerdate refs/heads/

# Or using git branch (since version 2.7.0)
git branch --sort=-committerdate  # DESC
git branch --sort=committerdate  # ASC

ผลลัพธ์:

ผลลัพธ์

การใช้งานขั้นสูง:

git for-each-ref --sort=committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'

ผลลัพธ์:

ผลลัพธ์


15
ที่สมบูรณ์แบบ! ฉันยังสามารถ จำกัด --format=%(refname)การส่งออกไปเพียงชื่อโทษโดยท้าย
Joe White

35
นี่จะดีกว่าสำหรับฉัน:git for-each-ref --sort=-committerdate refs/heads/ --format='%(refname) %(committerdate) %(authorname)' | sed 's/refs\/heads\///g'
saeedgnu

2
@ilius: ทำไมไม่ใช้:shortname?
Jakub Narębski

37
@ilius: เป็น @BeauSmith git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads/wrote: คอมไพล์สำหรับแต่ละโทษ (1) manpage กล่าวว่าสำหรับชื่อสั้น ๆ :shortที่ไม่ใช่คลุมเครือของการผนวกโทษ
Jakub Narębski

76
นี่เป็นเวอร์ชั่นที่มีสีสันรวมถึงแฮชข้อความสั่งขึ้นจากวันที่ส่งมอบพร้อมอายุที่สัมพันธ์กันของการส่งครั้งล่าสุดในแต่ละสาขา ฉันขโมยความคิดทั้งหมดจากพวกคุณข้างต้น มันอยู่ใน. gitconfig ของฉันใน[alias]ส่วนและฉันรักมัน br = for-each-ref --sort=committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'
Michael Percy

124

รายการชื่อสาขา Git เรียงลำดับโดยการคอมมิทล่าสุด ...

ขยายคำตอบของ Jakubและคำแนะนำของ Joeต่อไปนี้จะตัด "refs / heads /" ดังนั้นผลลัพธ์จะแสดงเฉพาะชื่อสาขา:


คำสั่ง:

git for-each-ref --count=30 --sort=-committerdate refs/heads/ --format='%(refname:short)'

ผลลัพธ์:

สาขา Git ล่าสุด


4
นอกจากนี้คุณยังสามารถใช้แทนการพึ่งพิง--format=%(refname:short) cut
Chaitanya Gupta

3
มีวิธีการทำเช่นนี้สำหรับพื้นที่เก็บข้อมูลระยะไกล?
Allan Bowe

10
aah - @ jakub.g ได้อธิบายไปแล้ว: คุณสามารถรับสาขาจากระยะไกลผ่านการอ้างอิง / รีโมท / แทนการอ้างอิง / หัว / ที่สมบูรณ์แบบ !!
Allan Bowe

ฉันเช่นนี้ถ้าคุณกำลังพยายามที่จะนามแฝงมันซึ่งผมจะgit rbจำไว้ว่าให้ล้อมรอบคำสั่งในคำพูด:git config --global alias.rb "for-each-ref --count=20 --sort=-committerdate refs/heads/ --format=\'%(refname:short)\'"
ไมเคิล Discenza

2
และตอนนี้คุณสามารถทำสิ่งนี้git branchได้ดังนั้นการทำงานในพื้นที่ห่างไกลหรือสาขาทั้งหมดทำงานได้ดีบน git-branch (เช่น -r, -a) git branch -r --sort=committerdate --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'
phord

89

นี่คือรหัสที่ดีที่สุดซึ่งรวมคำตอบอีกสองข้อเข้าด้วยกัน:

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

10
แม้แต่ตัวเล็ก ๆ ที่ปรับให้เหมาะสมเพื่อให้ได้ผลลัพธ์แบบตาราง:git for-each-ref --sort=-committerdate refs/heads/ --format='%(committerdate:short) %(authorname) %(refname:short)'
schoetbi

2
ด้วยเหตุผลบางอย่างที่ผมต้องใช้คำพูดคู่บนหน้าต่าง แต่อย่างอื่นเหล่านี้ทำงานได้ดี :)
amenthes

1
@schoetbi รหัสนั้นดูเหมือนกับ nikolay รหัสอะไรที่คุณเปลี่ยนเพื่อทำให้เป็นตาราง?
Enrico

@Enrico และคนอื่น ๆ ที่อาจสงสัยเกี่ยวกับสิ่งเดียวกัน นิโคไลเปลี่ยนคำตอบของเขาโดยใช้คำแนะนำ schoetbis เมื่อย้ายวันที่ก่อนซึ่งมีความยาวเท่ากันผลลัพธ์จะดูเป็นตารางมากกว่า
johnny

83

นี่คือคำสั่งง่ายๆที่แสดงรายการสาขาทั้งหมดที่มีคอมมิทล่าสุด

git branch -v

หากต้องการสั่งซื้อโดยกระทำล่าสุดให้ใช้

git branch -v --sort=committerdate

ที่มา: http://git-scm.com/book/en/Git-Branching-Branch-Management


11
git branch -avถ้าคุณต้องการดูสาขาที่ไม่ใช่ในท้องถิ่นด้วย
Scott Stafford

34
สิ่งนี้ไม่ได้จัดเรียงตามวันที่ส่งมอบตามคำถาม
Cas

1
มันง่ายที่git branch -vจะรวมถึงวันที่ของแต่ละการกระทำที่ระบุไว้?
dumbledad

1
<pre> git branch -v --sort = committerdate </pre> เป็นอย่างไร
iraj jelodari

2
นี่มันเจ๋งมาก. ฉันชอบที่git branch -va --sort=-committerdateจะแสดงสาขาที่ไม่ใช่ในท้องที่โดยมีสาขาที่เปลี่ยนแปลงล่าสุดที่ด้านบน
Clinton Blackmore

61

ฉันใช้นามแฝงต่อไปนี้:

recent = "!r(){git for-each-ref --sort=-committerdate refs/heads --format='%(HEAD)%(color:yellow)%(refname:short)|%(color:bold green)%(committerdate:relative)|%(color:blue)%(subject)|%(color:magenta)%(authorname)%(color:reset)'|column -ts'|'}; r"

ซึ่งผลิต:

ผลลัพธ์

ใช้ '|' เพื่อแยก


1
นามแฝงที่ยอดเยี่ยม! ฉันอยากจะแนะนำcolumn -ts'|'และไพพ์อักขระถ้าเครื่องหมายจุลภาคสามารถเกิดขึ้นได้ภายใน timestamps สัมพันธ์ในตำแหน่งที่ตั้งของคุณ
Björn Lindqvist

1
นามแฝงที่ดีขอบคุณมาก คุณสามารถปรับปรุงเพื่อแสดงสาขาปัจจุบันด้วยสีอื่นหรือด้วย * ที่จุดเริ่มต้นได้หรือไม่
elhadi dp ıpɐɥןǝ

2
อย่างน้อยใน git เวอร์ชันล่าสุดคุณสามารถเพิ่ม'%(HEAD) ...'ที่จุดเริ่มต้นของสตริงรูปแบบเพื่อให้ได้เอฟเฟกต์เดียวกันโดยไม่ต้องผ่านsedคำสั่ง
Joshua Skrzypek

5
ฉันไม่สามารถคอมไพล์สิ่งนี้เพื่อทำงานเป็นนามแฝงคอมไพล์ ฉันต้องใช้[alias] recent = !git for-each-ref --sort=-committerdate refs/heads --format='%(HEAD)%(color:yellow)%(refname:short)|%(color:bold green)%(committerdate:relative)|%(color:blue)%(subject)|%(color:magenta)%(authorname)%(color:reset)'|column -ts'|'
Wesley Smith

11
ฉันต้องเพิ่ม --color = เสมอเพื่อให้ได้สี git for-each-ref --sort=-committerdate refs/heads --format='%(HEAD)%(color:yellow)%(refname:short)|%(color:bold green)%(committerdate:relative)|%(color:blue)%(subject)|%(color:magenta)%(authorname)%(color:reset)' --color=always|column -ts'|'}
user3342930

40

ฉันสามารถอ้างอิงตัวอย่างก่อนหน้าเพื่อสร้างสิ่งที่ดีที่สุดสำหรับฉัน

คอมไพล์สำหรับแต่ละอ้างอิง --sort = - อ้างอิง refs / หัว / - รูปแบบ = '% (authordate: สั้น)% (สี: สีแดง)% (ชื่อ: สั้น)% (สี: สีเหลือง)% (ชื่อ: สั้น )% (color: reset) (% (color: green)% (committerdate: ญาติ)% (color: reset)) '

สกรีนช็อตของเอาต์พุต


1
ที่มีลักษณะดีมีสีสันมากขึ้นกว่าการใช้คอมไพล์สาขาโดยตรงเป็นผมแนะนำในstackoverflow.com/a/33163401/6309 +1
VonC

2
อันนี้ใช้ได้นอกกรอบสำหรับฉันไม่เหมือนคนอื่น ๆ ดังนั้นฉันจึงโหวตให้
Casey

1
ทำงานเป็นอย่างดีจริงๆ! ขอบคุณ! :-)
FrozenTarzan

1
Ditto - อันนี้ทำงานนอกกรอบเหมือนที่ฉันลอง ขอบคุณ
Dan Nissenbaum

2
อันนี้สะอาดและเรียบร้อย บางครั้งฉันก็เพิ่มรีโมตและชื่ออัตโนมัติเป็นดังนี้: git for-each-ref --sort=-committerdate refs/heads/ refs/remotes --format='%(authordate:short) %(authorname) %(color:red)%(objectname:short) %(color:yellow)%(refname:short)%(color:reset) (%(color:green)%(committerdate:relative)%(color:reset))'
ywu

38

ฉันยังต้องการสีแท็กและการอ้างอิงระยะไกลโดยไม่ซ้ำกัน:

for ref in $(git for-each-ref --sort=-committerdate --format="%(refname)" refs/heads/ refs/remotes ); do git log -n1 $ref --pretty=format:"%Cgreen%cr%Creset %C(yellow)%d%Creset %C(bold blue)<%an>%Creset%n" | cat ; done | awk '! a[$0]++'

เนื่องจากการอ้างถึงอาจทำได้ยากนี่คือชื่อแทนของ Bash:

alias glist='for ref in $(git for-each-ref --sort=-committerdate --format="%(refname)" refs/heads/ refs/remotes ); do git log -n1 $ref --pretty=format:"%Cgreen%cr%Creset %C(yellow)%d%Creset %C(bold blue)<%an>%Creset%n" | cat ; done | awk '"'! a["'$0'"]++'"

$ <คำสั่งของคุณที่นี่> awk: ข้อผิดพลาดทางไวยากรณ์ใกล้กับบรรทัดที่ 1 awk: การประกันตัวออกใกล้กับบรรทัดที่ 1
Jamie Mason

@GotNoSugarBaby คุณใช้เครื่องหมายคำพูดเดี่ยวเหมือนตัวอย่างใช่ไหม คุณใช้เปลือกไหนอยู่? Bash ทำให้ตัวละครนั้นมีความหมายพิเศษเป็นอย่างอื่น
estani

เฮ้ฉันวิ่งบน / bin / bash (GNU bash, รุ่น 4.0.28 (1) - ปล่อย (i386-pc-solaris2.11)) พร้อมสำเนาตรงและวางตัวอย่างของคุณ - แต่หลังจากนั้นฉันก็วิ่ง มันอยู่ใน / bin / bash (GNU bash, รุ่น 3.2.48 (1) - ปล่อย (x86_64-apple-darwin12) และมันใช้งานได้ดังนั้นฉันจะลบการลงคะแนน ขอบคุณมาก estani
Jamie Mason

@GotNoSugarBaby ฉันใช้ 4.2.25 (1) -release (x86_64-pc-linux-gnu) nad ลองใช้งาน 3.x และทำงาน ฉันไม่แน่ใจว่ามันเป็นปัญหาอะไร ... แต่มันอาจมีปัญหาที่เกี่ยวข้องกับรุ่น git แทนที่จะเป็น bash หนึ่ง ไม่ว่าในกรณีใดฉันดีใจที่ได้ผลกับคุณ!
estani

1
@MichaelDiscenza เพียงท่อทุกอย่างที่จะมุ่งหน้า ที่จะเพิ่ม| head -n20ในตอนท้าย หากคุณกำลังใช้นามแฝงตรวจสอบให้แน่ใจว่าสิ่งนี้อยู่ภายในเครื่องหมายคำพูด
estani

24

คำตอบอื่น ๆ ดูเหมือนจะไม่อนุญาตให้ส่งผ่าน-vvเพื่อรับเอาต์พุต verbose

ดังนั้นนี่คือหนึ่งซับที่เรียงgit branch -vvตามวันที่กระทำ, รักษาสี ฯลฯ :

git branch -vv --color=always | while read; do echo -e $(git log -1 --format=%ct $(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g') 2> /dev/null || git log -1 --format=%ct)"\t$REPLY"; done | sort -r | cut -f 2

หากคุณต้องการพิมพ์วันที่ส่งมอบเพิ่มเติมคุณสามารถใช้เวอร์ชันนี้แทน:

git branch -vv --color=always | while read; do echo -e $(git log -1 --format=%ci $(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g') 2> /dev/null || git log -1 --format=%ci)" $REPLY"; done | sort -r | cut -d ' ' -f -1,4-

ตัวอย่างผลลัพธ์:

2013-09-15   master                  da39a3e [origin/master: behind 7] Some patch
2013-09-11 * (detached from 3eba4b8) 3eba4b8 Some other patch
2013-09-09   my-feature              e5e6b4b [master: ahead 2, behind 25] WIP

มันอาจจะอ่านได้ง่ายขึ้นแบ่งออกเป็นหลายบรรทัด:

git branch -vv --color=always | while read; do
    # The underscore is because the active branch is preceded by a '*', and
    # for awk I need the columns to line up. The perl call is to strip out
    # ansi colors; if you don't pass --color=always above you can skip this
    local branch=$(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g')
    # git log fails when you pass a detached head as a branch name.
    # Hide the error and get the date of the current head.
    local branch_modified=$(git log -1 --format=%ci "$branch" 2> /dev/null || git log -1 --format=%ci)
    echo -e "$branch_modified $REPLY"
# cut strips the time and timezone columns, leaving only the date
done | sort -r | cut -d ' ' -f -1,4-

สิ่งนี้ควรทำงานร่วมกับข้อโต้แย้งอื่น ๆgit branchเช่น-vvrเพื่อแสดงรายการสาขาการติดตามระยะไกลหรือ-vvaเพื่อแสดงรายการทั้งการติดตามระยะไกลและสาขาท้องถิ่น


-vvจะมีประโยชน์แน่นอนขอบคุณ อย่างไรก็ตามวิธีนี้ยังคงวางไข่กระบวนการใหม่สำหรับแต่ละสาขาซึ่ง OP ต้องการหลีกเลี่ยง
musiphil

ที่จริงgit branchไม่ได้โดยเฉพาะการกำหนดความหมายของ-vvแต่ของ-vดังนั้นควรจะมีเช่นเดียวกับ-vv -v
musiphil

2
นี่คือสิ่งที่ดีที่สุด. และการเพิ่ม -avv ทำให้คำนึงถึงสาขาระยะไกลเช่นกัน ขอบคุณสำหรับสิ่งนี้!
Gopherkhan

@musiphil manpage สาขาคอมไพล์ของฉันส่วน-v, -vv, --verboseมีดังต่อไปนี้:If given twice, print the name of the upstream branch, as well
Perleone

@Perleone: ฉันไม่รู้ว่าฉันได้รับข้อมูลนั้นอย่างไร แต่คุณพูดถูกและฉันก็แก้ไขได้ ขอบคุณ!
musiphil

23

git 2.7 (Q4 2015) จะแนะนำการจัดเรียงสาขาโดยใช้โดยตรงgit branch:
ดูการกระทำ aa3bc55 , กระทำ aedcb7d , กระทำ 1511b22 ,กระทำ f65f139 , ... (23 ก.ย. 2558), กระทำ aedcb7d , กระทำ 1511b22 , กระทำ ca41799 (24 ก.ย. 2558), และกระทำ f65f139 ... (23 กันยายน 2015) โดยคาร์ทิคยัก (KarthikNayak )
(ผสานโดยJunio ​​C Hamano - gitster-ในการกระทำ 7f11b48 , 15 ต.ค. 2558)

โดยเฉพาะอย่างยิ่งกระทำ aedcb7d :

branch.c: ใช้ ' ref-filter' APIs

ทำAPI ' branch.c' ใช้ ' ref-filter' เพื่อทำซ้ำผ่านการเรียงลำดับอ้างอิง สิ่งนี้จะลบรหัสส่วนใหญ่ที่ใช้ใน ' branch.c' แทนที่ด้วยการเรียกไปยังref-filterไลบรารี ''

มันเพิ่มตัวเลือก--sort=<key> :

จัดเรียงตามคีย์ที่กำหนด
คำนำหน้า-เพื่อเรียงลำดับจากมากไปน้อยของค่า

คุณสามารถใช้--sort=<key>ตัวเลือกได้หลายครั้งซึ่งในกรณีนี้คีย์สุดท้ายจะกลายเป็นคีย์หลัก

ปุ่มที่รองรับนั้นเหมือนกับgit for-each-refปุ่มระบบ
เรียงลำดับค่าเริ่มต้นเป็นเรียงตามชื่อเต็ม (รวมถึงrefs/...คำนำหน้า) รายการนี้แสดง HEAD ที่แยกออก (ถ้ามี) ก่อนจากนั้นจึงแยกสาขาท้องถิ่นและสาขาติดตามระยะไกล

ที่นี่:

git branch --sort=-committerdate 

หรือ (ดูด้านล่างด้วย Git 2.19)

# if you are sure to /always/ want to see branches ordered by commits:
git config --global branch.sort -committerdate
git branch

ดูเพิ่มเติมกระทำ 9e46833 (30 ตุลาคม 2015) โดยคาร์ทิคยัก (KarthikNayak )
ช่วยเหลือโดย: Junio ​​C Hamano ( gitster) )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 415095f , 3 พฤศจิกายน 2015)

เมื่อเรียงตามค่าตัวเลข (เช่น--sort=objectsize) จะไม่มีการเปรียบเทียบทางเลือกเมื่อทั้งสองอ้างอิงมีค่าเดียวกัน สิ่งนี้สามารถทำให้เกิดผลลัพธ์ที่ไม่คาดคิด (เช่นลำดับของการอ้างอิงรายการที่มีค่าเท่ากันไม่สามารถกำหนดล่วงหน้าได้) ดังที่โจฮันเนสซิกท์ชี้ ( $ gmane / 280117 )

ดังนั้นfallback ที่จะเปรียบเทียบตัวอักษรบนพื้นฐาน refname เมื่อใดก็ตามที่เกณฑ์อื่น ๆ จะมีค่าเท่ากับ

$ git branch --sort=objectsize

*  (HEAD detached from fromtag)
      branch-two
      branch-one
      master

ด้วย Git 2.19 การเรียงลำดับสามารถตั้งค่าได้ตามค่าเริ่มต้น
git branchสนับสนุนการตั้งค่าbranch.sortเช่นเดียวกับที่ได้มีการกำหนดค่าgit tag ดูกระทำ 560ae1c (16 สิงหาคม 2018) โดยซามูเอล Maftoul ( ``) (ผสานโดยJunio ​​C Hamano - -tag.sort

gitsterในการกระทำ d89db6f , 27 สิงหาคม 2018)

branch.sort:

ตัวแปรนี้ควบคุมการเรียงลำดับของสาขาเมื่อแสดงโดย git-branchตัวแปรนี้จะควบคุมการสั่งซื้อการจัดเรียงของสาขาเมื่อแสดงโดย
หากไม่มี--sort=<value>ตัวเลือก "" ค่าของตัวแปรนี้จะถูกใช้เป็นค่าเริ่มต้น


git branch -r --sort=objectsizeการแสดงรายชื่อสาขาที่ห่างไกลการใช้งาน การ-rตั้งค่าสถานะทำให้รายการสาขาระยะไกลแทนสาขาท้องถิ่น


ด้วย Git 2.27 (Q2 2020), "git branchfor-each-refตัวแปร " และอื่น ๆ " " ยอมรับ--sort=<key>ตัวเลือกหลายตัวในลำดับที่เพิ่มขึ้นของลำดับความสำคัญ แต่มันมีข้อผิดพลาดเล็กน้อยเกี่ยวกับการ--ignore-caseจัดการ "" และผูกกับ refname ซึ่งได้รับการแก้ไขแล้ว

ดูกระทำ 7c5045f , กระทำ 76f9e56 (3 พฤษภาคม 2020) โดยเจฟฟ์คิง (peff )
(ผสานโดยJunio ​​C Hamano - gitster-ในการกระทำ 6de1630 , 08 พฤษภาคม 2020)

ref-filter: ใช้การจัดเรียง refname ทางเลือกหลังเฉพาะทุกประเภทผู้ใช้

ลงชื่อออกโดย: Jeff King

กระทำ9e468334b4 (" ref-filter: ทางเลือกในการเปรียบเทียบตามตัวอักษร", 2015-10-30, Git v2.7.0-rc0 - ผสานอยู่ในชุดที่ 10 ) สอนการจัดเรียงเตะกรองเพื่อ fallback เพื่อ refnames เปรียบเทียบ
แต่ทำในระดับที่ไม่ถูกต้องแทนที่ผลการเปรียบเทียบสำหรับ--sortคีย์เดียวจากผู้ใช้" " แทนที่จะใช้คีย์การเรียงลำดับทั้งหมดหมดแล้ว

สิ่งนี้ทำงานอย่างถูกต้องสำหรับ "--sortตัวเลือก " แต่ไม่ใช่สำหรับหลาย ๆ ตัว
เราจะทำลายความสัมพันธ์ใด ๆ ในคีย์แรกด้วย refname และไม่เคยประเมินคีย์ที่สองเลย

เพื่อให้เรื่องน่าสนใจยิ่งขึ้นเราใช้บางครั้งทางเลือกนี้!
สำหรับเขตข้อมูลเช่น " taggeremail" ซึ่งต้องการการเปรียบเทียบสตริงเราจะส่งคืนผลลัพธ์อย่างแท้จริงstrcmp()แม้ว่าจะเป็น 0
แต่สำหรับvalueฟิลด์ตัวเลข " " เช่น "taggerdate " เราได้ใช้การย้อนกลับ และนั่นคือสาเหตุที่การทดสอบหลายประเภทของเราพลาดสิ่งนี้: มันใช้taggeremailเป็นการเปรียบเทียบหลัก

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

นั่นแสดงข้อผิดพลาดและการแก้ไขนั้นง่าย: เลื่อนทางเลือกไปด้านนอก compare_refs()ฟังก์ชั่นหลังจากที่ref_sortingปุ่มทั้งหมดหมดลง

โปรดทราบว่าในฟังก์ชั่นด้านนอกเราไม่มี"ignore_case"ธงเพราะมันเป็นส่วนหนึ่งของแต่ละref_sortingองค์ประกอบ เป็นที่ถกเถียงกันว่าควรเลือกทางเลือกอย่างไรเนื่องจากเราไม่ได้ใช้กุญแจของผู้ใช้ในการจับคู่
แต่จนถึงขณะนี้เราได้พยายามเคารพธงนั้นดังนั้นสิ่งที่รุกรานน้อยที่สุดคือพยายามทำเช่นนั้นต่อไป
เนื่องจากผู้เรียกทั้งหมดในรหัสปัจจุบันตั้งค่าสถานะสำหรับคีย์ทั้งหมดหรือไม่มีเลยเราจึงสามารถดึงค่าสถานะจากคีย์แรก ในโลกสมมุติที่ผู้ใช้สามารถพลิกตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ของคีย์แยกกันเราอาจต้องการขยายรหัสเพื่อแยกความแตกต่างระหว่างตัวพิมพ์ใหญ่กับผ้าห่ม " --ignore-case"


ในการแสดงรายการรีโมตด้วยตัวเลือกนี้เพิ่ม-r
Troy Daniels

@TroyDaniels เห็นด้วย คุณสามารถแก้ไขคำตอบ ฉันจะตรวจสอบการแก้ไขของคุณ
VonC

19

ฉันชอบใช้วันที่สัมพันธ์กันและทำให้ชื่อสาขาสั้นลงเช่นนี้:

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

ปรับปรุง: ทำเช่นนี้หากคุณต้องการระบายสี:

#!/bin/sh
#
(echo ' ------------------------------------------------------------‌​' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------‌​') | grep --color -E "$(git rev-parse --abbrev-ref HEAD)$|$"

สิ่งนี้ทำให้ฉันfatal: unknown field name: '-authordate:iso8601'
Factor Mystic

1
เอาต์พุตสีแฟนซีนั้นแฟนซี แต่นี่เป็นสิ่งที่เรียบง่ายและเป็นสิ่งที่ฉันกำลังมองหา แทนที่refs/headsด้วยrefs/remotesเพื่อดูสาขาระยะไกล
Lambart

คำสั่งนั้นน่ารัก แต่นามแฝงพ่นข้อผิดพลาด:expansion of alias 'branches' failed; 'echo' is not a git command
Philip Kahn

ได้ผลสำหรับฉัน จะเกิดอะไรขึ้นถ้าคุณเพียงแค่คัดลอกวางลงในเทอร์มินัล (echo ' ------------------------------------------------------------‌​' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------‌​') | grep --color -E "$(git rev-parse --abbrev-ref HEAD)$|$"
n8tr

17

ตั้งแต่ Git 2.19 คุณสามารถ:

git branch --sort=-committerdate

นอกจากนี้คุณยังสามารถ:

git config branch.sort -committerdate

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

ถ้าเมื่อใดก็ตามที่คุณแสดงรายการสาขาคุณต้องการให้เรียงลำดับตาม comitterdate:

git config --global branch.sort -committerdate

ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนคุณสมบัตินี้ใน Git และฉันใช้งานเมื่อฉันเห็นคำถามนี้


2
คำตอบล่าสุดส่วนใหญ่ง่ายกว่าการใช้สคริปต์หรือนามแฝงที่ซับซ้อน👌
mtefi

ใช้ด้วยความระมัดระวัง! ระวังทุกคนนี่ไม่ใช่คำสั่งที่จะแสดงรายการสาขา มันเป็นคำสั่งให้เปลี่ยนการกำหนดค่าของ Git และจะมีผลกระทบถาวรทั่วโลก
Jazimov

1
@Jazimov คุณถูกต้องฉันแก้ไขคำตอบเพื่อให้ชัดเจนยิ่งขึ้น
user801247

11

เพิ่มสีบางส่วน (เนื่องจากpretty-formatไม่มีให้ใช้งาน)

[alias]
    branchdate = for-each-ref --sort=-committerdate refs/heads/ --format="%(authordate:short)%09%(objectname:short)%09%1B[0;33m%(refname:short)%1B[m%09"

9

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

$ twig

                              issue  status       todo            branch
                              -----  ------       ----            ------
2013-01-26 18:00:21 (7m ago)  486    In progress  Rebase          optimize-all-the-things
2013-01-26 16:49:21 (2h ago)  268    In progress  -               whitespace-all-the-things
2013-01-23 18:35:21 (3d ago)  159    Shipped      Test in prod  * refactor-all-the-things
2013-01-22 17:12:09 (4d ago)  -      -            -               development
2013-01-20 19:45:42 (6d ago)  -      -            -               master

นอกจากนี้ยังช่วยให้คุณเก็บคุณสมบัติแบบกำหนดเองสำหรับแต่ละสาขาเช่นรหัสตั๋ว, สถานะ, to-do, และกรองรายการสาขาตามคุณสมบัติเหล่านี้ ข้อมูลเพิ่มเติม: http://rondevera.github.io/twig/


5
ชื่อนั้นอาจไม่ช่วยได้เพราะฉันค่อนข้างมั่นใจว่ามีซอฟต์แวร์บางส่วนที่มีชื่อเดียวกัน
59

8

ฉันใช้คำสั่งต่อไปนี้ (สำหรับ Git 2.13 ขึ้นไป):

git branch -r --sort=creatordate \
    --format "%(creatordate:relative);%(committername);%(refname:lstrip=-1)" \
    | grep -v ";HEAD$" \
    | column -s ";" -t

หากคุณไม่มีcolumnคุณสามารถแทนที่บรรทัดสุดท้ายด้วย

    | sed -e "s/;/\t/g"

ผลลัพธ์ดูเหมือนว่า

6 years ago             Tom Preston-Werner  book
4 years, 4 months ago   Parker Moore        0.12.1-release
4 years ago             Matt Rogers         1.0-branch
3 years, 11 months ago  Matt Rogers         1.2_branch
3 years, 1 month ago    Parker Moore        v1-stable
12 months ago           Ben Balter          pages-as-documents
10 months ago           Jordon Bedwell      make-jekyll-parallel
6 months ago            Pat Hawks           to_integer
5 months ago            Parker Moore        3.4-stable-backport-5920
4 months ago            Parker Moore        yajl-ruby-2-4-patch
4 weeks ago             Parker Moore        3.4-stable
3 weeks ago             Parker Moore        rouge-1-and-2
19 hours ago            jekyllbot           master

ฉันเขียนบล็อกโพสต์เกี่ยวกับการทำงานของชิ้นส่วนต่าง ๆ


ดี +1 มันไม่ใช้git branch --sortผมกล่าวถึงในstackoverflow.com/a/33163401/6309
VonC

@DanNissenbaum ตรวจสอบให้แน่ใจว่าคุณใช้ Git 2.13 (เผยแพร่พฤษภาคม 2017) หรือใหม่กว่า
bdesham

7

FYI หากคุณต้องการรับรายชื่อสาขาที่เช็คเอาท์เมื่อเร็ว ๆ นี้(ตรงข้ามกับข้อตกลงล่าสุด) คุณสามารถใช้ reflog ของ Git:

$ git reflog | egrep -io "moving from ([^[:space:]]+)" | awk '{ print $3 }' | head -n5
master
stable
master
some-cool-feature
feature/improve-everything

ดูเพิ่มเติม: ฉันจะรับรายชื่อสาขา Git ที่ฉันเพิ่งเช็คเอาต์ได้อย่างไร


5

นี่เป็นสคริปต์เล็กน้อยที่ฉันใช้เพื่อสลับระหว่างสาขาล่าสุด:

#!/bin/bash
# sudo bash

re='^[0-9]+$'

if [[ "$1" =~ $re ]]; then
    lines="$1"
else
    lines=10
fi
branches="$(git recent | tail -n $lines | nl)"
branches_nf="$(git recent-nf | tail -n $lines | nl)"
echo "$branches"

# Prompt which server to connect to
max="$(echo "$branches" | wc -l)"
index=
while [[ ! ( "$index" =~ ^[0-9]+$ && "$index" -gt 0 && "$index" -le "$max" ) ]]; do
    echo -n "Checkout to: "
    read index
done

branch="$( echo "$branches_nf" | sed -n "${index}p" | awk '{ print $NF }' )"
git co $branch
clear

ใช้นามแฝงทั้งสองที่:

recent = for-each-ref --sort=committerdate refs/heads/ --format=' %(color:blue) %(authorname) %(color:yellow)%(refname:short)%(color:reset)'
recent-nf = for-each-ref --sort=committerdate refs/heads/ --format=' %(authorname) %(refname:short)'

เพียงแค่เรียกมันว่าในพื้นที่เก็บข้อมูล Git และมันจะแสดงกิ่งสาขาสุดท้าย (10 ตามค่าเริ่มต้น) และแยกแต่ละหมายเลข ป้อนหมายเลขสาขาและเช็คเอาท์:

ป้อนคำอธิบายภาพที่นี่


4

โดยปกติเราพิจารณาสาขาระยะไกลเมื่อเร็ว ๆ นี้ ดังนั้นลองสิ่งนี้

git fetch
git for-each-ref --sort=-committerdate refs/remotes/origin

4

นี่คือสคริปต์อื่นที่ทำในสิ่งที่สคริปต์อื่นทำ ในความเป็นจริงมันมีฟังก์ชั่นสำหรับเปลือกของคุณ

การมีส่วนร่วมของมันคือมันดึงบางสีจากการกำหนดค่า Git ของคุณ

# Git Branch by Date
# Usage: gbd [ -r ]
gbd() {
    local reset_color=`tput sgr0`
    local subject_color=`tput setaf 4 ; tput bold`
    local author_color=`tput setaf 6`

    local target=refs/heads
    local branch_color=`git config --get-color color.branch.local white`

    if [ "$1" = -r ]
    then
        target=refs/remotes/origin
        branch_color=`git config --get-color color.branch.remote red`
    fi

    git for-each-ref --sort=committerdate $target --format="${branch_color}%(refname:short)${reset_color} ${subject_color}%(subject)${reset_color} ${author_color}- %(authorname) (%(committerdate:relative))${reset_color}"
}

3

สิ่งนี้ขึ้นอยู่กับเวอร์ชั่นของ saeedgnuแต่มีสาขาปัจจุบันที่แสดงด้วยดาวและสีและแสดงเฉพาะสิ่งที่ไม่ได้อธิบายว่า "เดือน" หรือ "ปี" ที่ผ่านมา:

current_branch="$(git symbolic-ref --short -q HEAD)"
git for-each-ref --sort=committerdate refs/heads \
  --format='%(refname:short)|%(committerdate:relative)' \
  | grep -v '\(year\|month\)s\? ago' \
  | while IFS='|' read branch date
    do
      start='  '
      end=''
      if [[ $branch = $current_branch ]]; then
        start='* \e[32m'
        end='\e[0m'
      fi
      printf "$start%-30s %s$end\\n" "$branch" "$date"
    done

2

ผลลัพธ์ที่ดีที่สุดของฉันเป็นสคริปต์:

git for-each-ref --sort=-committerdate refs/heads/ --format='%(refname:short)|%(committerdate:iso)|%(authorname)' |
    sed 's/refs\/heads\///g' |
    grep -v BACKUP  | 
    while IFS='|' read branch date author
    do 
        printf '%-15s %-30s %s\n' "$branch" "$date" "$author"
    done

1
สคริปต์ชนิดใด ทุบตี?
Peter Mortensen



1

นี่คือรูปแบบที่ฉันกำลังมองหา:

git for-each-ref --sort=-committerdate --format='%(committerdate)%09%(refname:short)' refs/heads/ | tail -r

ที่tail -rย้อนกลับรายการดังนั้นล่าสุดcommiterdateเป็นครั้งสุดท้าย


3
นอกจากนี้คุณยังสามารถเปลี่ยน --sort = -committerdate เป็น --sort = committerdate เพื่อทำสิ่งนี้ให้สำเร็จ
รูปใหม่

ซึ่งtailมี-r?
Christoffer Hammarström

1

ฉันไพพ์เอาต์พุตจากคำตอบที่ยอมรับลงในdialogเพื่อให้รายการโต้ตอบ:

#!/bin/bash

TMP_FILE=/tmp/selected-git-branch

eval `resize`
dialog --title "Recent Git Branches" --menu "Choose a branch" $LINES $COLUMNS $(( $LINES - 8 )) $(git for-each-ref --sort=-committerdate refs/heads/ --format='%(refname:short) %(committerdate:short)') 2> $TMP_FILE

if [ $? -eq 0 ]
then
    git checkout $(< $TMP_FILE)
fi

rm -f $TMP_FILE

clear

บันทึกเป็น (เช่น) ~/bin/git_recent_branches.shและchmod +xมัน จากนั้นgit config --global alias.rb '!git_recent_branches.sh'ให้ฉันgit rbคำสั่งใหม่


1

ฉันรู้ว่ามีคำตอบมากมายอยู่แล้ว แต่นี่คือสองเซนต์ของฉันสำหรับนามแฝงง่ายๆ (ฉันชอบที่จะมีสาขาล่าสุดของฉันที่ด้านล่าง):

[alias]
        br = !git branch --sort=committerdate --color=always | tail -n15
[color "branch"]
        current = yellow
        local = cyan
        remote = red

สิ่งนี้จะให้ภาพรวมที่ดีของ 15 สาขาล่าสุดของคุณเป็นสีโดยมีการเน้นสาขาปัจจุบันของคุณ (และมีเครื่องหมายดอกจัน)


1

มีปัญหาในการจัดการอัญประกาศเดี่ยวเดี่ยวบน Mac ใน bash_profile เมื่อพยายามตั้งชื่อแทน คำตอบนี้ช่วยแก้ไขได้ " วิธีการหลีกเลี่ยงการอ้างอิงคำพูดเดียวภายในสตริงที่ยกมาเดี่ยว

วิธีการทำงาน:

alias gb='git for-each-ref --sort=committerdate refs/heads/ --format='"'"'%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'"'"''

ป.ล. ไม่สามารถแสดงความคิดเห็นได้เนื่องจากชื่อเสียงของฉัน


0

git for-each-ref --sort=committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))' นี่คือสิ่งที่คุณต้องการ


0

Git v2.19แนะนำbranch.sortตัวเลือกการกำหนดค่า (ดูbranch.sort )

ดังนั้นgit branchจะเรียงตามวันที่ส่ง (เรียง) ตามค่าเริ่มต้นด้วย

# gitconfig
[branch]
    sort = -committerdate     # desc

สคริปต์:

$ git config --global branch.sort -committerdate

ปรับปรุง:

ดังนั้น,

$ git branch
* dev
  master
  _

และ

$ git branch -v
* dev    0afecf5 Merge branch 'oc' into dev
  master 652428a Merge branch 'dev'
  _      7159cf9 Merge branch 'bashrc' into dev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.