Lacak semua cabang git jarak jauh sebagai cabang lokal

175

Melacak satu cabang jarak jauh sebagai cabang lokal cukup mudah.

$ git checkout --track -b ${branch_name} origin/${branch_name}

Mendorong semua cabang lokal ke jarak jauh, membuat cabang jarak jauh baru sesuai kebutuhan juga mudah.

$ git push --all origin

Saya ingin melakukan yang sebaliknya. Jika saya memiliki nomor X cabang jarak jauh di satu sumber:

$ git branch -r 
branch1
branch2
branch3
.
.
.

Dapatkah saya membuat cabang pelacakan lokal untuk semua cabang jarak jauh tanpa perlu membuat masing-masing cabang secara manual? Katakan sesuatu seperti:

$ git checkout --track -b --all origin

Saya sudah googled dan RTM, tetapi sejauh ini telah naik ranjang.

Janson
sumber
3
Bahkan ada cara yang lebih sederhana untuk melacak cabang terpencil tunggal sebagai cabang lokal:git checkout --track origin/branchname
Cerran
Ini tidak persis seperti yang Anda minta, tetapi bekerja untuk saya: dapatkan penyelesaian git: github.com/git/git/blob/master/contrib/completion/… . Kemudian ketik git pull origin dan tekan tab, untuk mendapatkan daftar cabang jauh. Kemudian lanjutkan mengetik dan tekan return.
Max Heiber

Jawaban:

111

Menggunakan bash:

setelah git 1.9.1
for i in `git branch -a | grep remote | grep -v HEAD | grep -v master`; do git branch --track ${i#remotes/origin/} $i; done

kredit: Val Blant, elias, dan Hugo

sebelum git 1.9.1

Catatan: kode berikut jika digunakan dalam versi git (> v1.9.1) yang lebih baru menyebabkan

  1. (bug) Semua cabang dibuat untuk melacak master
  2. (gangguan) Semua nama cabang lokal dibuat untuk diawali dengan origin/
for remote in `git branch -r `; do git branch --track $remote; done

Perbarui cabang, dengan asumsi tidak ada perubahan pada cabang pelacakan lokal Anda:

for remote in `git branch -r `; do git checkout $remote ; git pull; done

Abaikan peringatan refname ambigu, git tampaknya lebih memilih cabang lokal sebagaimana mestinya.

Otto
sumber
2
Terima kasih atas informasi tentang peringatan refname. Itu sangat membantu.
Paul
1
Terima kasih Otto, saya curiga bahwa scripting akan menjadi satu-satunya solusi. Anda telah memberikan yang cukup sederhana.
Janson
1
@ Alasannya masih hari ini scripting satu-satunya solusi?
cregox
1
@Cawas: Anda harus membuat cabang pelacakan secara manual, tetapi git pullmemiliki --allsakelar, yang akan mengambil + menggabungkan semua cabang yang dilacak.
naught101
13
Ini tidak berfungsi untuk saya di Git 1.9.1. "git branch --track <banch_name>" membuat cabang baru <branch_name> yang melacak master cabang lokal, alih-alih cabang jarak jauh yang kami inginkan. Jadi skrip ini menciptakan banyak cabang lokal yang semuanya menunjuk ke master lokal. Saya akan memposting solusinya di bawah ini.
Val Blant
183

Jawaban yang diberikan oleh Otto baik, tetapi semua cabang yang dibuat akan memiliki "asal /" sebagai awal nama. Jika Anda hanya ingin bagian terakhir (setelah / terakhir) menjadi nama cabang Anda, gunakan ini:

for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

Ini juga bermanfaat untuk tidak memberi Anda peringatan tentang referensi yang ambigu.

tjmcewan
sumber
Git tidak akan menambahkan "asal" ke nama cabang pelacakan lokal.
Adam Dymitruk
14
@ adymitruk: Sebenarnya ini berlaku persis seperti yang saya katakan untuk saya di OSX 10.6.4, menggunakan git 1.7.2.2 (stable terbaru pada komentar ini). Otto bahkan menyebutkan peringatan refname yang ambigu - peringatan itu tidak perlu ada jika "asal /" bukan bagian dari setiap nama cabang lokal. Inilah keluaran 'git branch' setelah menjalankan perintah Otto: [master, origin / HEAD, origin / chart, origin / master, origin / production, origin / staging]. Dan perintah saya: [grafik, master, produksi, pementasan].
tjmcewan
1
+ Edit: ditemukan article.gmane.org/gmane.comp.version-control.git/112575 menjelaskan alasannya.
Philip Oakley
8
Saya setuju - ini adalah solusi yang lebih baik daripada apa yang saat ini jawaban "diterima".
tobias.mcnulty
2
Alih-alih grep -v master, bagaimana grep -v /HEAD? Ini tampaknya menyaring cabang default, tanpa perlu penyesuaian
dashrb
22

Sebagian besar jawaban di sini lebih rumit dari penguraian output git branch -r. Anda dapat menggunakan forloop berikut untuk membuat cabang pelacakan terhadap semua cabang di remote seperti itu.

Contoh

Katakanlah saya punya cabang terpencil ini.

$ git branch -r
  origin/HEAD -> origin/master
  origin/development
  origin/integration
  origin/master
  origin/production
  origin/staging

Konfirmasikan bahwa kami tidak melacak apa pun selain master, secara lokal:

$ git branch -l    # or using just git branch
* master

Anda dapat menggunakan liner satu ini untuk membuat cabang pelacakan:

$ for i in $(git branch -r | grep -vE "HEAD|master"); do 
    git branch --track ${i#*/} $i; done
Branch development set up to track remote branch development from origin.
Branch integration set up to track remote branch integration from origin.
Branch production set up to track remote branch production from origin.
Branch staging set up to track remote branch staging from origin.

Sekarang konfirmasikan:

$ git branch
  development
  integration
* master
  production
  staging

Untuk menghapusnya:

$ git br -D production development integration staging 
Deleted branch production (was xxxxx).
Deleted branch development (was xxxxx).
Deleted branch integration (was xxxxx).
Deleted branch staging (was xxxxx).

Jika Anda menggunakan -vvsakelar ini, git branchAnda dapat mengonfirmasi:

$ git br -vv
  development xxxxx [origin/development] commit log msg ....
  integration xxxxx [origin/integration] commit log msg ....
* master      xxxxx [origin/master] commit log msg ....
  production  xxxxx [origin/production] commit log msg ....
  staging     xxxxx [origin/staging] commit log msg ....

Kerusakan untuk loop

Loop pada dasarnya memanggil perintah git branch -r, memfilter setiap HEAD atau cabang master di output menggunakan grep -vE "HEAD|master". Untuk mendapatkan nama hanya cabang dikurangi origin/substring kami menggunakan manipulasi string Bash ${var#stringtoremove}. Ini akan menghapus string, "stringtoremove" dari variabel $var. Dalam kasus kami, kami menghapus string origin/dari variabel $i.

CATATAN: Atau Anda dapat menggunakan git checkout --track ...untuk melakukan ini juga:

$ for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); do 
    git checkout --track $i; done

Tapi saya tidak terlalu peduli dengan metode ini, karena ini akan mengalihkan Anda di antara cabang-cabang saat melakukan checkout. Ketika selesai itu akan meninggalkan Anda di cabang terakhir yang dibuatnya.

Referensi

slm
sumber
1
Berfungsi sempurna dengan git versi 2.3.2 (Apple Git-55)
AndrewD
22

Perbarui Q1 2020: Mohsen Abasi mengusulkan di komentar , berdasarkan 2014 slm 's jawabannya , alternatif sederhana:

for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); 

Dan itu menggunakan $()backticks usang .

Seperti yang saya sebutkan di jawaban tua lain , menggunakan git for-each-refadalah mungkin lebih cepat .
Dan saya akan menggunakan yang baru (Git 2.23+) git switchperintah , yang menggantikan membingungkangit checkout .

for i in $(git for-each-ref --format=%(refname:short) \
  --no-merged=origin/HEAD refs/remotes/origin); do \
    git switch --track $i; \
done

Dengan begitu, tidak grepperlu.


Old (2011) jawaban asli:

Inilah one-liner yang saya gunakan (dalam bash shell, diuji dengan msysgit1.7.4):

Untuk salin-tempel:

remote=origin ; for brname in `git branch -r | grep $remote | grep -v master | grep -v HEAD | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream-to $remote/$brname $brname; done

Untuk lebih mudah dibaca:

remote=origin ; // put here the name of the remote you want
for brname in `
    git branch -r | grep $remote | grep -v master | grep -v HEAD 
    | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'
`; do 
    git branch --set-upstream-to $remote/$brname $brname; 
done
  • itu hanya akan memilih cabang upstream dari remote yang Anda tentukan dalam remotevariabel (itu bisa ' origin' atau nama apa pun yang telah Anda tetapkan untuk salah satu remote dari repo Git Anda saat ini).
  • itu akan mengekstrak nama cabang: origin/a/Branch/Name => a/Branch/Namemelalui awkekspresi.
  • itu akan mengatur cabang upstream melalui --set-upstream-to(atau -u) , bukan --track:
    Keuntungannya adalah, jika cabang sudah ada, itu tidak akan gagal dan itu tidak akan mengubah asal cabang itu, itu hanya akan mengonfigurasi branch.xxx.(remote|merge)pengaturan.

    branch.aBranchName.remote=origin
    branch.aBranchName.merge=refs/heads/a/Branch/Name
    

Perintah itu akan membuat cabang lokal untuk semua cabang hulu jarak jauh, dan mengatur pengaturan jarak jauh dan menggabungkannya ke cabang jarak jauh itu.

VONC
sumber
5
Ini memberi saya "fatal: cabang 'apa pun' tidak ada" untuk setiap cabang yang hanya ada di remote dan tidak memiliki cabang lokal yang sesuai.
Chris Dodd
saya pikir jika nama cabang berisi / misalnya: fitur / rc-41-bckend, solusi ini tidak berfungsi !!!!
Mohsen Abasi
@VonC Berdasarkan jawaban "slm": $ untuk saya dalam $ (cabang git -r | grep -vE "HEAD | master" | sed 's / ^ [] \ + //'); lakukan checkout git --track $ i; selesai
Mohsen Abasi
@MohsenAbasi Terlihat bagus. Dalam jawaban saya, saya sebutkan menggunakan --set-upstream-tobukan --track.
VonC
@MohsenAbasi Saya telah memasukkan alternatif Anda dalam jawaban untuk lebih banyak visibilitas. Saya telah menambahkan cara lain yang mungkin untuk membuat daftar cabang jarak jauh, dan menggunakannya git switchsebagai gantinya git checkout. Tapi ide Anda (sangat bagus) tetap ada.
VonC
14

Anda dapat menulis dengan cukup mudah, tetapi saya tidak tahu kapan itu akan berharga. Cabang-cabang itu akan dengan cepat tertinggal, dan Anda harus memperbaruinya setiap saat.

Cabang-cabang jarak jauh secara otomatis akan terus diperbarui, jadi paling mudah hanya dengan membuat cabang lokal pada titik di mana Anda sebenarnya ingin mengerjakannya.

Dustin
sumber
2
Itu poin yang bagus. Kasus penggunaan utama yang saya pikirkan adalah menyiapkan lingkungan dev lokal berdasarkan repositori git jarak jauh. Jadi ketika saya melakukan klon awal saya, saya juga ingin melacak semua cabang terpencil seperti pada saat itu.
Janson
1
Berguna git upmemperbarui semua cabang lokal.
Hugo
untuk menggabungkan dua repo dan menghapus remote
endolith
9
for i in `git branch -a | grep remote`; do git branch --track ${i#remotes/origin/} $i; done
Val Blant
sumber
4
Saya harus menambahkan | grep -v HEADpipa agar berfungsi dengan benar.
Elias Dorneles
9

tanpa skrip apa pun (dalam direktori kosong):

$ git clone --bare repo_url .git
$ git config core.bare false
$ git checkout

setelah itu, semua cabang terpencil akan dianggap lokal.


asli (dalam bahasa Rusia) .

aleksandr barakin
sumber
Ini adalah solusi paling sederhana dan berhasil untuk saya di 2.21.0.windows.1
Rotsiser Mho
7

Jika Anda ingin menggunakan PowerShell dan remote Anda disebut asal. Maka ini bekerja.

git fetch    
git branch -r  | %{$_ -replace "  origin/"} | %{git branch --track $_ "origin/$_"}
BigMiner
sumber
Ini sangat membantu, saya akhirnya menggunakan sedikit variasi untuk membuatnya bekerja dengan git svn clone'drepo saya :git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"}
Nate
Saya juga membuat sedikit variasi karena cabang lokal saya sudah ada:git branch -r | %{$_ -replace " origin/"} | %{git branch -u "origin/$_" $_}
ch271828n
3
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do  git branch --track ${branch##*/} $branch; done

Gunakan ini dan Anda tidak akan memiliki peringatan seperti: refname 'origin / dev' ambigu

bruziuz
sumber
3

Inilah solusi saya untuk perintah BASH yang dirujuk oleh @tjmcewan:

for remote in `git branch -r | grep -v /HEAD `; do git branch --track ${remote/"origin/"/""}; done

Tujuan saya adalah untuk memecahkan masalah bahwa semua cabang yang dibuat akan memiliki "asal /" sebagai awal nama, karena saya menguji bahwa variabel $ remote masih termasuk "asal /":

for remote in `git branch -r | grep -v /HEAD`; do echo $remote ; done
Nick Tsai
sumber
Setelah saya menguji BASH @tjmcewan saya menemukan bahwa semua nama cabang dilacak tanpa 'asal /' pada lokal, saya tidak tahu mengapa.
Nick Tsai
1
Perintah pertama menciptakan bran yang melacak "master". Itu bukan barang yang kebanyakan orang inginkan.
Alexei Osipov
@AlexeiOsipov Terima kasih!
Nick Tsai
2

Untuk melakukan hal yang sama dengan jawaban tjmcewan tetapi pada Windows, panggil ini dari file batch :

for /f "delims=" %%r in ('git branch -r ^| grep -v master') do git checkout --track %%r

Atau ini dari baris perintah :

for /f "delims=" %r in ('git branch -r ^| grep -v master') do git checkout --track %r
Hugo
sumber
1

Dari git 2.23 dan selanjutnya:

for branch in `git branch -r | grep origin/`; do git switch -t -C ${branch#origin/} $branch; git pull; done

The -Cbendera untuk git switchmenciptakan atau reset jika sudah ada.

dokumentasi switch git

AeroX
sumber
0

Jika Anda sudah memiliki beberapa cabang diperiksa dan ingin

  • periksa semua cabang yang tersisa dari remote
  • pastikan semua cabang lokal melacak cabang jarak jauh

Anda dapat menggunakan skrip yang kompatibel dengan bash dan zsh:

git branch -r | while read b; do if git branch | grep -q " ${b##*/}$"; then git branch --set-upstream ${b##*/} $b; else git branch --track ${b##*/} $b; fi; done
simonair
sumber
0
for rembranch in `git remote update 2>&1 > /dev/null ; git branch -r|egrep -wv "HEAD|master"`
do 
    git checkout --track -b `echo $rembranch|awk -F\/ '{print $2}'` $rembranch; 
done

Penjelasan:

baris 1: 'git branch -r' (diikuti oleh 'git remote update' untuk memperbarui info tentang perubahan pada remote) mencantumkan semua cabang jarak jauh; 'egrep -vw' digunakan untuk mengetuk entri yang memiliki HEAD dan master dalam hasilnya.

baris 3: Lacak cabang jarak jauh bernama sambil memeriksanya secara lokal. Awk sederhana digunakan untuk menghindari 'asal /' menjadi akhiran untuk cabang lokal.

ksvrgh
sumber
0

Menggunakan bash, Jika Anda ingin checkout semua cabang:

for remote in `git branch -r`; do git checkout $(echo $remote | cut -d'/' -f 2); done

Penting untuk dicatat bahwa ketika Anda melakukan pengambilan yang menurunkan cabang-cabang pelacakan jarak jauh baru, Anda tidak secara otomatis memiliki salinannya yang dapat diedit secara lokal.

Jason Chen
sumber