Bagaimana saya memberi tahu git-svn tentang cabang jarak jauh yang dibuat setelah saya mengambil repo?

193

Saya menggunakan git-svnuntuk bekerja melawan repositori pusat Subversion perusahaan saya. Kami baru-baru ini membuat cabang fitur baru di repo pusat.

Bagaimana saya memberi tahu Git tentang hal itu? Ketika saya menjalankan, git branch -rsaya hanya bisa melihat cabang yang ada ketika saya berlari fetchmelawan repo Subversion untuk menginisialisasi repo Git saya?

Hank Gay
sumber
Jawaban dari sini: stackoverflow.com/questions/13376917/… mungkin juga berguna.
Tomasz Gandor

Jawaban:

294

Anda dapat secara manual menambahkan cabang jarak jauh,

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch
vangus
sumber
3
cukup menambahkan tautan ini ke dokumen sebagai referensi kernel.org/pub/software/scm/git/docs/git-svn.html
slf
1
Dari .git / config, cukup mudah untuk memahami bagaimana cabang jarak jauh dapat dikonfigurasikan dari repositori tunggal / multipel.
Mikael Lepistö
6
Jika saya bisa mengungguli ini sebanyak delapan kali, saya akan melakukannya. Akhirnya, cara untuk menambahkan cabang svn yang ditambahkan di lokasi yang tidak standar!
Tim Keating
7
Saya mendapatkan fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.pada langkah checkout git.
phpguru
17
@phpguru Coba hapus flag opsi -t sehingga menjadi 'git checkout -b local-newbranch newbranch' jangan lupa menyertakan awalan remote ke newbranch (mis. origin / newbranch).
mj1531
96

Jika Anda ingin melacak SEMUA cabang svn jauh, maka solusinya semudah:

git svn fetch

Ini akan mengambil SEMUA cabang jarak jauh yang belum diambil.

Kiat ekstra: jika Anda hanya memeriksa trunk pada awalnya, dan kemudian Anda ingin melacak SEMUA cabang, kemudian edit .git/configagar terlihat seperti ini dan jalankan kembali git svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

Poin-poin kunci adalah urlharus menunjuk ke root repositori, dan jalur yang didefinisikan fetchdan branchesharus relatif terhadap url.

Jika Anda ingin mengambil hanya cabang tertentu dan bukan SEMUA, ada contoh yang bagus di git svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

Dengan versi yang lebih lama git-svn, setelah Anda menentukan cabang seperti ini, Anda mungkin tidak bisa mendapatkan cabang baru git svn fetch. Satu solusi adalah menambahkan lebih banyak fetchbaris, seperti ini:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

Solusi lain oleh @AndyEstes: edit .git/svn/.metadatadan ubah nilai branches-maxRevatau tags-maxRevke revisi sebelum cabang atau tag yang baru ditentukan dibuat. Setelah Anda selesai melakukannya, jalankan git svn fetchuntuk melacak cabang jauh svn baru.

janos
sumber
1
Jika Anda telah mengambil revisi yang dilakukan percabangan svn sebelum Anda mengatur pengaturan itu, Anda mungkin ingin melakukan git svn reset.
kcm1700
3
Editing .git/svn/.metadatasangat membantu! Saya menambahkan cabang tambahan di kantor saya .git/config, yang git svn fetchtidak aktif - karena nomor revisi metadata "terlalu jauh ke depan". Dalam satu kasus, hanya komit terakhir dari cabang yang diambil. Saya secara manual menyingkirkan cabang yang salah (diganti namanya .git/svn/refs/remotes/svn/qa/XYZmenjadi .git/svn/refs/remotes/svn/qa/XYZ~, hilangkan keberadaannya di .git/packed-refs, dll) ... memilih nomor revisi "sebelumnya" untuk metadata ... dijalankan git svn fetchuntuk akhirnya mendapatkan sejarah penuh dengan grafik yang terhubung.
starlocke
8
INI HARUS MENJADI JAWABAN YANG DITERIMA! @janos, Anda baru saja menyelamatkan saya dari sakit kepala beberapa jam! Jika Anda datang ke India, saya akan mengajak Anda minum bir!
Roopesh Shenoy
1
Atau: git svn fetch --all.
kenorb
1
Jawaban ini luar biasa, karena menjawab sekitar 7 pertanyaan yang tidak dapat saya temukan jawabannya, dan melakukannya tanpa menulis narasi 6 halaman.
Droj
53

Tampaknya saya hanya perlu git svn fetch; entah bagaimana saya telah meyakinkan diri saya sendiri bahwa akan mengambil seluruh repo bukan hanya perubahan.

Hank Gay
sumber
7
@mitjak Mengapa itu bukan jawaban yang benar, jika itu solusinya? Saya tidak mengerti kehalusan responnya.
rholmes
'solusi' mungkin bukan 'solusi'
slf
1
@ rholmes: Saya yakin mitjak berarti itu adalah solusi untuk masalah Anda tetapi bukan jawaban atas pertanyaan yang Anda ajukan. (Karena Anda mengajukan pertanyaan yang salah; ketika Anda salah mengartikan masalah pada saat itu.)
Mike Nelson
Ini berfungsi ketika cabang ada saat Anda mengkloning svn repositori ke git. Ini tidak akan berfungsi jika cabang di repositori svn dibuat sesudahnya.
Petr Gladkikh
3
Ini berfungsi dengan baik ketika cabang dibuat setelah klon, saya selalu melakukannya.
Tim Gautier
15

Mungkin aku mengacaukannya entah bagaimana tetapi aku mengikuti instruksi dalam jawaban vjangus dan itu hampir berhasil. Satu-satunya masalah adalah bahwa cabang baru tampaknya tidak bercabang dari bagasi. Di gitk, itu semacam "mengambang" sendiri; ia tidak memiliki leluhur yang sama dengan belalainya.

Solusi untuk ini adalah:

  1. Temukan SHA1 dari komit terakhir yang terjadi di bagasi sebelum cabang dibuat.
  2. Temukan SHA1 dari komit pertama di cabang baru (pesan mungkin "Dibuat cabang baru, disalin dari trunk @ 12345" atau sesuatu)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- seharusnya tidak ada output. Jika ada output, Anda mungkin telah memilih komit yang salah.
  4. git checkout local-newbranchkemudian git rebase <sha1 from step 1>. Ini akan rebase local-newbranchke pohon baru tetapi remotes/newbranchmasih akan terputus.
  5. Buka file .git/refs/remotes/newbranchdan edit untuk mengandung SHA1 lengkap dari komit baru (pada rebased newbranch) yang sesuai dengan komit lama yang saat ini ditunjukinya. (Atau mungkin digunakan git-update-ref refs/remotes/newbranch <new-SHA>. Terima kasih inger.)
  6. Lain kali Anda git svn dcommitmelakukannya newbranch, Anda akan mendapatkan banyak pesan tentang hal itu memperbarui beberapa log. Ini normal menurut saya.

Saya sarankan untuk tetap gitk --allmembuka sepanjang waktu dan menyegarkannya untuk melacak apa yang Anda lakukan. Saya masih semacam baru untuk git dan git svn jadi tolong sarankan perbaikan metode ini.

MatrixFrog
sumber
2
Terima kasih, ini kedengarannya berguna. Tentang 5. mungkin 'git-update-ref ref / remote / newbranch <new-SHA>' adalah opsi yang lebih aman.
inger
Hanya mencoba cara vjangus lagi dan itu bekerja dengan sempurna. Saya akan meninggalkan ini di sini karena itu mungkin berharga bagi seseorang ...
MatrixFrog
1
solusi vjangus selalu membuat cabang baru terputus dari bagasi. Saya berasumsi ini karena cara SVN sendiri tidak memiliki petunjuk tentang bagaimana konten aktual disalin.
bogdan.mustiata
Pengalaman saya dengan repo git-svn besar adalah bahwa cabang svn selalu dibuat di git terlepas dari trunk. Seharusnya ada cara untuk menghubungkan mereka, tapi saya belum meluangkan waktu untuk mencari tahu. AFAIK, Anda tidak dapat rebase cabang git yang terhubung ke cabang svn, karena itu akan mengacaukan logika dcommit. Kami baru saja belajar untuk hidup dengannya.
Spencer
7

Penyederhanaan jawaban vjangus:

Jika Anda menggunakan tata letak standar di SVN dan telah melakukan init svn seperti biasa, git-svn akan melakukan hal-hal konfigurasi untuk Anda. Hanya:

  1. Temukan revisi cabang-salinan di SVN
  2. Ambil revisi itu dengan git-svn
  3. Buat remote pelacakan cabang lokal baru

Sebuah contoh. URL SVN adalah svn+ssh://[email protected]/repo. Cabang SVN yang saya cari adalah newbranch. Cabang git lokal (pelacakan jarak jauh newbranch) akan git-newbranch.

Langkah 1: cari revisi cabang-salinan

    # svn log --stop-di-salin svn + ssh: //[email protected]/repo/branches/newbranch | ekor -4
    r7802 | seseorang | 2014-03-21 18:54:58 +0000 (Jum, 21 Mar 2014) | 1 baris

    percabangan KEPALA ke cabang baru
    -------------------------------------------------- ----------------------

Jadi titik cabang di SVN adalah revisi 7802.

Langkah 2: Ambil revisi

    # git svn fetch -r 7802
    Ditemukan titik cabang yang memungkinkan: svn + ssh: //[email protected]/repo/trunk => svn + ssh: //[email protected]/repo/branches/newbranch, 7801
    Ditemukan induk cabang: (ref / remote / trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Mengikuti induk dengan do_switch
    Berhasil mengikuti orang tua
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (ref / remote / newbranch)

git-svn melakukan semua pekerjaan dan sekarang tahu tentang remote:

    # git show-ref | ambil cabang baru
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c ref / remote / newbranch

Langkah 3: Buat cabang lokal baru Anda melacak yang jauh:

    # git checkout -b git-newbranch -t newbranch
    Memeriksa file: 100% (413/413), selesai.
    Cabang git-newbranch didirikan untuk melacak referensi / remote / ref cabang lokal.
    Beralih ke cabang baru 'git-newbranch'
Gil Hamilton
sumber
Setelah ini akhirnya membuat saya mengerti ( show-reftidak ternilai)! Bagi siapa pun yang terjebak dengan rujukan yang salah cabang jauh, Anda dapat menghapusnya (saya harus melakukan git branch -d newbranchdan kemudian paksa menghapus dir ref .git/svn/refs/remotes/newbranch) dan kemudian mulai lagi pada langkah 2 (di atas).
tutuDajuju
5

Saya belum menemukan dokumentasi tentang fitur ini, tetapi sepertinya konfigurasi git svn mendukung banyak entri pengambilan. Dengan cara ini Anda juga dapat menambahkan cabang secara terpisah tanpa perlu menambahkan entri repositori svn jarak jauh lain ke konfigurasi Anda atau menggunakan wildcard untuk mendapatkan semua cabang direktori tertentu.

Asumsikan bahwa pohon SVN Anda benar-benar jahat memiliki banyak cabang tanpa logika bagaimana mereka berada, misalnya memiliki cabang dan sub-direktori yang mengandung lebih banyak bercabang.

yaitu

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

dan Anda hanya ingin memilih sendiri beberapa cabang yang akan dimasukkan ke repositori git Anda.

Anda mungkin pertama-tama init repositori Anda dengan hanya trunk tanpa cabang tambahan:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

Setelah itu Anda akan melihat konfigurasi berikut:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

kapan pun Anda ingin mengambil cabang baru dari MyRepo Anda bisa menambahkan entri ambil baru ke konfigurasi dengan:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

Atau Anda dapat mengedit konfigurasi yang sama di .git / config

Untuk mengambil cabang baru setelah menambahkannya ke konfigurasi cukup jalankan:

git svn fetch -r 10000:HEAD

[Sunting] Kadang-kadang tampaknya perlu menjalankan fetch dengan --all parameter untuk mengambil cabang yang baru ditambahkan:

git svn fetch --all -r 10000:HEAD
Mikael Lepistö
sumber
4

Alih-alih berurusan dengan kebiasaan git-svn, Anda dapat mencoba SubGit .

Kita harus menginstal SubGit ke dalam repositori Subversion. Setelah itu orang dapat menggunakan alur kerja git standar alih-alih menggunakan perintah git-svn khusus:

  1. Mendorong komitmen baru:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Mengambil perubahan yang masuk

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Membuat cabang baru:

    git-svn:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

Lihat dokumentasi SubGit untuk lebih jelasnya.

vadishev
sumber
1
SubGit memiliki kelemahan yaitu membuat dua repositori - satu svn, dan satu repositori git "bayangan". Ini mungkin menjadi masalah bagi repositori SVN besar ...
Udo
@Udo Jika repositori SVN memiliki beberapa proyek, satu dapat menentukan hanya satu dari mereka dan menyinkronkannya dengan repositori Git. Dalam hal ini tidak perlu mengubah seluruh repositori Subversion menjadi Git. Tetapi jika seseorang memiliki proyek SVN yang besar dalam repositori ini, seseorang tidak boleh mengonversi seluruh sejarah repositori ini tetapi sejarahnya dimulai dari beberapa revisi minimal. Ini memungkinkan untuk mengurangi ukuran repositori Git yang diterjemahkan.
vadishev
1
@Udo - perusahaan mana pun yang tidak mau membeli server repositori mereka, hard drive memiliki prioritas mereka kacau. Tetapi sebagian besar tempat dengan repositori besar mengambil repositori mereka dengan cukup serius, dan persyaratan ruang disk untuk repositori umumnya bukan masalah besar, bahkan untuk perusahaan dengan sejarah puluhan tahun dan puluhan juta baris kode dan ratusan ribu revisi. Ini bentuk paling konkret perusahaan dari aset intelektual inti mereka, dan ruang disk cukup murah. Mungkin memicu kebutuhan untuk meningkatkan pengontrol RAID, tetapi meskipun demikian, peningkatan produktivitas ...
Bob Kerns
@ Bob Kerns - Intinya adalah "ukuran bijaksana" SVN dan Git dan tidak kompatibel. Ini bukan masalah penyimpanan disk atau lebih. Tetapi Anda dapat bekerja dengan repositori SVN yang besar karena biasanya Anda perlu keluar hanya beberapa file / proyek. Tetapi Anda tidak dapat mengkloning repositori Git yang besar - setidaknya tidak mengasyikkan ;-) Dengan "besar" maksud saya beberapa Gigs.
Udo
2

Untuk menambah jawaban vjangus, yang membantu saya, saya juga merasa berguna untuk menambahkan menggunakan git cangkok untuk mengikat cabang ke bagasi pada titik yang tepat - memungkinkan git untuk melihat sejarah dan melakukan penggabungan dengan benar.

Ini hanyalah kasus penambahan garis .git/info/graftsdengan hash:

<initial branch commit> <parent commit in trunk>

misalnya.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Kredit untuk http://evan-tech.livejournal.com/255341.html

(Saya akan menambahkan ini sebagai komentar, tetapi saya tidak memiliki reputasi yang cukup.)

CD Haddon.
sumber
0

Jika Anda tidak memeriksa dengan tata letak yang valid, Anda tidak akan dapat checkout cabang jauh.

Inilah yang saya lakukan:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

Setelah itu, Anda dapat beralih ke cabang jarak jauh:

git checkout --track -b branch_name branch_name

Maka Anda akan secara otomatis beralih ke cabang Anda.

MikeHoss
sumber