Cantumkan setiap cabang dan tanggal revisi terakhirnya di Git


138

Saya perlu menghapus cabang lama dan tidak terawat dari repositori jarak jauh kami. Saya mencoba menemukan cara untuk membuat daftar cabang jarak jauh berdasarkan tanggal modifikasi terakhir mereka, dan saya tidak bisa.

Apakah ada cara mudah untuk membuat daftar cabang jarak jauh dengan cara ini?



3
Jawaban untuk: stackoverflow.com/questions/5188320/… semuanya lebih baik daripada jawaban di sini
Insinyur Perangkat Lunak

Jawaban:


172

commandlinefu memiliki 2 proposisi menarik:

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

atau:

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

Itu untuk cabang lokal, dalam sintaksis Unix. Dengan menggunakan git branch -r, Anda juga dapat menampilkan cabang jarak jauh:

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 menyebutkan dalam komentar bahwa zsh membutuhkan pelarian untuk sedekspresi:

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 menambahkan dalam komentar :

Jika Anda ingin menambahkannya zshrc Anda maka dibutuhkan escape berikut.

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'

Dalam banyak baris:

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'

Catatan: n8tr 's jawaban , berdasarkan git for-each-ref refs/headslebih bersih. Dan lebih cepat .
Lihat juga " Opsi hanya nama untuk git branch --list? "

Secara lebih umum, tripleee mengingatkan kita dalam komentar :

  • Lebih suka $(command substitution)sintaksis modern daripada sintaks backtick usang.

(Saya menggambarkan titik itu pada tahun 2014 dengan " Apa perbedaan antara $(command)dan `command`dalam pemrograman shell? ")

  • Jangan membaca baris denganfor .
  • Mungkin beralih ke git for-each-ref refs/remoteuntuk mendapatkan nama cabang jarak jauh dalam format yang dapat dibaca mesin

1
@hansen j: menarik, bukan? Ini diluncurkan beberapa bulan setelah rilis publik Stack Overflow ( codeinthehole.com/archives/… ), dan agak terinspirasi oleh SO. Lihat juga commandlinefu.com/commands/tagged/67/git untuk lebih lanjut git commandlinefu;)
VonC

Jawaban ini menendang pantat stackoverflow.com/questions/5188320/… . :)
Spundun

@SebastianG tidak yakin: itu akan menjadi pertanyaan yang bagus.
VonC

+1 Cukup mengagumkan bagaimana Anda bisa menambahkan /jsonke akhir URL commandlinefu.com dan Anda akan mendapatkan semua perintah sebagai JSON.
Noah Sussman

1
@ tripleee Terima kasih. Saya telah mengedit jawaban dan memasukkan komentar Anda untuk visibilitas yang lebih banyak.
VonC

121

Inilah yang saya gunakan:

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

Ini hasilnya:

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

Untuk cabang jarak jauh, cukup gunakan "ref / remote" alih-alih "ref / head":

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

Membangun jawaban n8tr , jika Anda juga tertarik dengan penulis terakhir di cabang, dan jika Anda memiliki alat "kolom" yang tersedia, Anda dapat menggunakan:

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

Yang akan memberi Anda:

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

Anda mungkin ingin memanggil "git fetch --prune" sebelum memiliki informasi terbaru.


5
Penggunaan yang bagus untuk setiap ref dan opsi format. +1. Terdengar lebih mudah daripada perintah yang saya rujuk dalam jawaban saya sendiri.
VonC

2
tweaking sedikit: ------- git untuk-masing-masing ref --sort = '- authordate: iso8601' --format = '% (authordate: relatif)% 09% (refname: short)' ref / head ------- memberi Anda tanggal relatif dan menghilangkan referensi / kepala
n8tr

1
Bagi mereka yang belum jelas, saya pikir ini menunjukkan info. khusus untuk cabang lokal.
hBrent

@ hBrent kamu benar, itu tidak menjawab pertanyaan yang sebenarnya. Saya telah mengedit jawaban saya sesuai dengan itu.
ocroquette

Ini mengurutkan dan mendaftar cabang dengan authordate(yang tampaknya ketika cabang pertama kali dibuat?). Jika Anda mengubah authordateke committerdatemaka Anda akan melihat tanggal terbaru komit dalam setiap cabang. Seperti itu:git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads
Logan Besecker

23

Membangun Olivier Croquette , saya suka menggunakan tanggal relatif dan memperpendek nama cabang seperti ini:

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

Yang memberi Anda output:

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

Saya sarankan membuat file Bash untuk menambahkan semua alias favorit Anda dan kemudian membagikan skrip ke tim Anda. Berikut ini contoh untuk menambahkan yang ini:

#!/bin/sh

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

Kemudian Anda bisa melakukan ini untuk mendapatkan daftar cabang lokal yang diformat dan diurutkan dengan baik:

git branches

20

Hanya untuk menambahkan komentar oleh @VonC, ambil solusi pilihan Anda dan tambahkan ke daftar alias ~ / .gitconfig Anda untuk kenyamanan:

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

Kemudian "git branchdate" sederhana mencetak daftar untuk Anda ...


3
+1 untuk menunjukkan cara menggunakannya dengan .gitconfig! Juga saya mengubah format string menjadi: --format='%(authordate)%09%(objectname:short)%09%(refname)'yang mendapatkan hash pendek dari masing-masing cabang juga.
Noah Sussman

Bagus. Saya akan menambahkan "| tac" di akhir untuk membuatnya diurutkan dalam urutan terbalik sehingga cabang yang baru disentuh dengan cepat terlihat.
Ben

1
Anda tidak perlu | tac, hanya --sort='authordate'bukan-authordate
Kristján

4

Inilah yang saya hasilkan setelah meninjau ini juga .

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

Itu PREV_REF cek adalah untuk menghapus duplikat jika lebih dari satu cabang poin yang sama komit. (Seperti di cabang lokal yang ada di jarak jauh juga.)

Perhatikan bahwa sesuai permintaan OP, git branch --mergeddan git branch --no-mergedberguna dalam mengidentifikasi cabang mana yang dapat dengan mudah dihapus.

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


3

Cabang jarak jauh yang diurutkan dan tanggal komit terakhir untuk setiap cabang.

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
Terima kasih telah menjawab pertanyaan OP tentang remote.
arcseldon

1

Saya membuat dua varian, berdasarkan jawaban VonC .

Varian pertama saya:

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

Ini menangani cabang lokal dan jarak jauh ( -a), menangani keadaan kepala terpisah (semakin lama perintah, meskipun solusinya agak mentah - itu hanya mengganti info cabang yang terlepas dengan kata kunci KEPALA), menambahkan dalam subjek komit (% s ), dan menempatkan sesuatu ke dalam kolom melalui karakter pipa literal dalam string format dan meneruskan hasil akhir ke column -t -s "|". (Anda bisa menggunakan apa pun sebagai pemisah, selama itu adalah sesuatu yang tidak Anda harapkan di sisa output.)

Varian kedua saya cukup rumit, tetapi saya benar-benar menginginkan sesuatu yang masih memiliki indikator "ini adalah cabang Anda saat ini" seperti yang dilakukan perintah cabang.

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

Ini mengubah *yang menandai cabang saat ini menjadi kata kunci, dan ketika badan loop melihat kata kunci itu malah menetapkan bendera dan tidak menghasilkan apa-apa. Bendera digunakan untuk menunjukkan bahwa pemformatan alternatif harus digunakan untuk baris berikutnya. Seperti yang saya katakan, ini benar-benar retas, tetapi berhasil! (Sebagian besar. Untuk beberapa alasan, kolom terakhir saya semakin ketinggalan zaman pada baris cabang saat ini.)


Sayangnya informasi dalam jawaban VonCs bukanlah fondasi yang bagus untuk penulisan skrip. Lihat di sini git-blame.blogspot.com/2013/06/...
Andrew C

Hmm. Itu menunjukkan cara untuk mendapatkan nama cabang saat ini, jika memiliki nama. Apakah ada cara [yang disukai] untuk mendapatkan daftar cabang yang ramah mesin? (Dan beberapa cara untuk membedakan cabang saat ini, baik dari keluaran itu secara langsung atau melalui entah bagaimana bertanya git "apakah ini referensi yang sama dengan KEPALA?")
referensi yang

git for-each-refadalah cara yang mudah untuk memproses cabang. Anda harus menjalankan ref simbolik sekali untuk mendapatkan cabang saat ini.
Andrew C

Memberi +1 untuk upaya ini, tapi itu memang jawaban lama saya. stackoverflow.com/a/16971547/6309 atau (lebih lengkap) stackoverflow.com/a/19585361/6309 dapat melibatkan sedikit 'sed'.
VonC

1

Saya melakukan alias sederhana, tidak yakin apakah ini yang sebenarnya ditanyakan, tetapi sederhana

Saya melakukan ini karena saya ingin mendaftar semua cabang bukan hanya cabang lokal saya, yang hanya melakukan perintah di atas

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

Anda dapat pipa di atas ke grep origin untuk mendapatkan asal-usul saja

Ini mencantumkan semua cabang bersama dengan tanggal terakhir yang dimodifikasi, membantu saya memutuskan mana yang harus saya tarik untuk versi terbaru

Ini menghasilkan jenis tampilan di bawah ini

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

Coba dan beri tahu saya jika itu membantu, senang gitting


Bagus dan sederhana. Tidak ada saus spesial.
MrMas

0

Atau Anda dapat menggunakan skrip PHP saya, 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

Inilah fungsi yang dapat Anda tambahkan ke bash_profile Anda untuk mempermudah ini.

Penggunaan saat dalam repositori Git:

  • branch mencetak semua cabang lokal
  • branch -r mencetak semua cabang jarak jauh

Fungsi:

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

Di PowerShell, berikut ini memperlihatkan cabang pada remote yang sudah digabungkan dan setidaknya berumur dua minggu ( author:relativeformat mulai menampilkan minggu bukannya hari dua minggu):

$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}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.