Bagaimana saya bisa melihat cabang Git mana yang melacak cabang terpencil / hulu?

825

Saya tahu saya bisa melakukannya git branch --all , dan itu menunjukkan kepada saya cabang lokal dan remote, tetapi itu tidak berguna dalam menunjukkan kepada saya hubungan di antara mereka.

Bagaimana cara mendaftar cabang dengan cara yang memperlihatkan cabang lokal mana yang melacak jarak jauh?

joachim
sumber

Jawaban:

1146

Perintah porselen sangat banyak, tidak baik jika Anda menginginkan ini untuk scripting:

git branch -vv   # doubly verbose!

Perhatikan bahwa dengan git 1.8.3, cabang hulu itu ditampilkan dengan warna biru (lihat " Apa pelacakan cabang ini (jika ada) di git? ")


Jika Anda ingin output bersih, lihat jawaban arcresu - ini menggunakan perintah porselen yang saya tidak percaya ada pada saat saya awalnya menulis jawaban ini, jadi ini sedikit lebih ringkas dan bekerja dengan cabang-cabang yang dikonfigurasi untuk rebase, bukan hanya menggabungkan.

Cascabel
sumber
3
Metode pertama di atas tidak memberikan informasi yang diinginkan untuk saya. Yang kedua ... tampaknya berlebihan, terutama karena jawaban Kubi bekerja. Apakah saya melewatkan sesuatu?
garyp
3
@garyp Anda bukan orang yang mengajukan pertanyaan. Yang pertama memberikan apa OP yang dibutuhkan, dan yang kedua disediakan persis apa yang ia butuhkan, dalam hal ia ingin dalam bentuk bersih untuk scripting, atau ingin hanya menyimpan sebagai alias. ("Overkill" baik-baik saja jika itu memberi Anda apa yang Anda inginkan dan Anda tidak perlu mengulanginya.) Dari sudut pandang pertanyaan ini, jawaban kubi memberikan beberapa informasi yang tidak berhubungan, dan jika ada lebih dari satu jarak jauh, itu tidak dapat menunjukkan semuanya, tetapi jika memenuhi kebutuhan Anda, tentu saja gunakan itu.
Cascabel
2
Saya berutang permintaan maaf. Ketika saya awalnya menjalankan metode pertama, saya tidak mendapat informasi tentang apa yang melacak apa, dan saya harus menyatakannya secara eksplisit. Tapi sekarang saya melihat info pelacakan, jadi saya pasti ada yang salah dengan pengaturan saya. Jadi saya sedang kehilangan sesuatu.
garyp
2
FWIW saya bingung karena -v dan -vv menunjukkan output yang sama. Cabang yang dilacak ditampilkan dalam tanda kurung setelah hash dan sebelum komit terbaru (pada instalasi homebrew OSX default saya).
jerclarke
3
Semua ini bagi saya adalah mencetak hash dan komentar komit terakhir untuk setiap cabang.
capybaralet
263

git remote show origin

Ganti 'asal' dengan apa pun nama remote Anda.

kubi
sumber
11
Meskipun perintah porselen ini bekerja untuk manusia (tidak terlalu banyak untuk skrip, karena harus mengurai output porselen), apa yang saya tidak suka tentang pendekatan ini adalah bahwa git remote showperintah sebenarnya terhubung ke repo jarak jauh ... dan karenanya gagal jika Anda offline atau tidak dapat terhubung ke repo untuk alasan apa pun ...
pvandenberk
17
@ pvandenberk Anda dapat menggunakan git remote show -n originuntuk mendapatkan beberapa informasi bahkan saat offline. Dari dokumentasi remote git : "Dengan opsi -n, head remote tidak ditanyai terlebih dahulu dengan git ls-remote <name>; informasi yang di-cache malah digunakan."
Cerran
5
Satu hal aneh tentang perintah ini: ia mencantumkan cabang jarak jauh sebagai "dilacak", bahkan jika tidak ada cabang lokal yang dikonfigurasikan untuk menarik / mendorong. Saya selalu menemukan ini membingungkan. Saya sebenarnya tidak jelas tentang apa yang dimaksud "dilacak" dalam output ini. Git docs pada subjek membuatnya terdengar seperti cabang jarak jauh "dilacak" hanya ketika itu terhubung / terikat ke cabang lokal untuk push / pull ...
Hawkeye Parker
Masalahnya adalah saya harus memanggil ini untuk semua nama jarak jauh sampai saya melihat apa yang sebenarnya saya cari.
jolvi
2
@ jolvi Anda dapat berlari git remote show | xargs git remote show -nuntuk melihat info pelacakan gabungan untuk semua remote.
Synoli
107

Jika Anda melihat halaman manual untuk git-rev-parse, Anda akan melihat sintaks berikut dijelaskan:

<branchname>@{upstream}, Misalnya master@{upstream},@{u}

Akhiran @{upstream}ke nama cabang (bentuk pendek <branchname>@{u}) merujuk ke cabang yang cabang yang ditentukan oleh nama cabang diatur untuk membangun di atas. Branchname yang hilang default ke yang sekarang.

Karenanya untuk menemukan hulu cabang master, Anda akan melakukan:

git rev-parse --abbrev-ref master@{upstream}
# => origin/master

Untuk mencetak informasi untuk setiap cabang, Anda dapat melakukan sesuatu seperti:

while read branch; do
  upstream=$(git rev-parse --abbrev-ref $branch@{upstream} 2>/dev/null)
  if [[ $? == 0 ]]; then
    echo $branch tracks $upstream
  else
    echo $branch has no upstream configured
  fi
done < <(git for-each-ref --format='%(refname:short)' refs/heads/*)

# Output:
# master tracks origin/master
# ...

Ini lebih bersih daripada mem-parsing referensi dan mengkonfigurasi secara manual.

Carl Suster
sumber
Saya tidak bisa mengerti sedikit dalam rev-parse meskipun menemukannya, jadi terima kasih atas penjelasan yang jelas!
Alice Purcell
3
Bagi kita yang menggunakan git-flow, dengan cabang bernama "fitur / blahblah", pernyataan penutup dari while loop harus berbunyi: done < <(git for-each-ref --format='%(refname:short)' refs/heads/**)Perhatikan dua tanda bintang di akhir pola glob.
markeissler
2
git rev-parse --abbrev-ref HEAD@{upstream}tampaknya berfungsi dengan baik untuk cabang saat ini. Itu juga membuat alias git bagus.
Digikata
The whilesintaks lingkaran terlihat agak aneh bagi saya. Anda bisa menggunakan git for-each-ref ... | while read branch; do ...yang tidak membutuhkan FIFO dan berjalan dalam urutan yang sama seperti perintah yang ditulis.
Daniel Böhmer
Setidaknya sejak git 2.5.1, Anda memiliki satu-liner dengangit for-each-ref --format='%(refname:short) tracks %(upstream:short)' refs/heads/*
Mat M
81

Alternatif jawaban kubi adalah dengan melihat .git/configfile yang memperlihatkan konfigurasi repositori lokal:

cat .git/config

Abizern
sumber
6
Juga git config --get-regex branch
Tamir Daniely
6
Atau, lebih khusus lagi, 'git config --get-regexp branch. * Merge'
yoyo
41
git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

akan menampilkan garis untuk setiap cabang lokal. Cabang pelacakan akan terlihat seperti:

master <- origin/master

Yang tidak terlacak akan terlihat seperti:

test <- 
Aurelien
sumber
Bagus, untuk menambahkan beberapa pemesanan dan keluaran TAB-bed: git untuk masing-masing ref --sort upstream --format = '% (refname: short)% 09 <-% (upstream: short)' ref / head
dimir
Ringkas dan hasilnya benar-benar jauh lebih mudah dibaca daripada yang diterima git branch -vv. 🙏
joki
Satu-satunya masalah adalah bahwa saya tidak dapat mengingat ini, jadi saya menggunakangit config --global alias.track 'for-each-ref --format='\''%(refname:short) <- %(upstream:short)'\'' refs/heads'
joki
38

Untuk cabang saat ini , berikut adalah dua pilihan bagus:

% git rev-parse --abbrev-ref --symbolic-full-name @{u}
origin/mainline

atau

% git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)
origin/mainline

Jawaban itu juga ada di sini , untuk pertanyaan yang sedikit berbeda yang (salah) ditandai sebagai duplikat.

cdunn2001
sumber
5
Berdasarkan itu, semua cabang dapat terdaftar secara ramah skrip: git for-each-ref --shell --format='%(refname:short) %(upstream:short)' refs/heads.
Daniel James
15

Untuk cabang saat ini, Anda juga bisa mengatakan git checkout(tanpa cabang apa pun). Ini adalah no-op dengan efek samping untuk menampilkan informasi pelacakan, jika ada, untuk cabang saat ini.

$ git checkout 
Your branch is up-to-date with 'origin/master'.
Eugene Yarmash
sumber
Cukup adil, tetapi Anda dapat mengetik secara tidak sengaja git checkout ., yang bukan larangan.
Tomasz Gandor
6

Saya menggunakan alias ini

git config --global alias.track '!f() { ([ $# -eq 2 ] && ( echo "Setting tracking for branch " $1 " -> " $2;git branch --set-upstream $1 $2; ) || ( git for-each-ref --format="local: %(refname:short) <--sync--> remote: %(upstream:short)" refs/heads && echo --Remotes && git remote -v)); }; f'

kemudian

git track
Olivier Refalo
sumber
5
Saya pikir patut dicatat bahwa dengan dua parameter perintah Anda mengkonfigurasi cabang trek.
albfan
3

Berdasarkan jawaban Olivier Refalo

if [ $# -eq 2 ] 
then
    echo "Setting tracking for branch " $1 " -> " $2
    git branch --set-upstream $1 $2
else
    echo "-- Local --" 
    git for-each-ref --shell --format="[ %(upstream:short) != '' ] && echo -e '\t%(refname:short) <--> %(upstream:short)'" refs/heads | sh
    echo "-- Remote --" 
    REMOTES=$(git remote -v) 
    if [ "$REMOTES" != '' ]
    then
        echo $REMOTES
    fi  
fi

Ini menunjukkan hanya lokal dengan trek yang dikonfigurasi.

Tulis di skrip bernama git-track di jalur Anda dan Anda akan mendapatkan git-track perintah

Versi yang lebih rumit di https://github.com/albfan/git-showupstream

Albfan
sumber
1

git config --get-regexp "branch\.$current_branch\.remote"

akan memberi Anda nama remote yang dilacak

git config --get-regexp "branch\.$current_branch\.merge"

akan memberi Anda nama cabang jarak jauh yang dilacak.

Anda harus mengganti $ current_branch dengan nama cabang Anda saat ini. Anda bisa mendapatkannya secara dinamisgit rev-parse --abbrev-ref HEAD

Skrip mini berikut menggabungkan hal-hal itu. Masukkan ke dalam file bernama git-tracking, buat itu bisa dieksekusi, dan pastikan itu ada di jalur Anda.

maka Anda bisa mengatakannya

$ git  tracking
<current_branch_name>-><remote_repo_name>/<remote_branch_name>

perhatikan bahwa nama cabang jarak jauh dapat berbeda dari nama cabang lokal Anda (walaupun biasanya tidak). Sebagai contoh:

$git tracking 
xxx_xls_xslx_thing -> origin/totally_bogus

seperti yang Anda lihat dalam kode, kunci untuk ini adalah mengekstraksi data dari konfigurasi git. Saya hanya menggunakan sed untuk menghapus data asing.

#!/bin/sh

current_branch=$(git rev-parse --abbrev-ref HEAD)
remote=$(git config --get-regexp "branch\.$current_branch\.remote" | sed -e "s/^.* //")
remote_branch=$(git config --get-regexp "branch\.$current_branch\.merge" | \
  sed -e "s/^.* //" -e "s/refs\/.*\///")

echo "$current_branch -> $remote/$remote_branch"
masukomi
sumber
1

Ini yang rapi dan sederhana. Dapat memeriksa git remote -v, yang menunjukkan semua asal dan hulu dari cabang saat ini.

MJeremy
sumber