git-svn: apa yang setara dengan `svn switch --relocate`?


89

Repositori svn yang saya tiru melalui git-svn telah mengubah URL.

Di vanilla svn yang baru saja Anda lakukan svn switch --relocate old_url_base new_url_base.

Bagaimana saya bisa melakukan ini menggunakan git-svn?

Cukup mengubah url svn di file konfigurasi gagal.


Anda harus mencoba dan mungkin menerima jawaban ini: stackoverflow.com/a/4061493/1221661
Fritz

Jawaban terbaru: stackoverflow.com/a/40523789/537554 . Pertanyaan yang sama, tetapi ditanyakan dari sudut pandang pengguna Git.
ryenus

Jawaban:


61

Ini menangani situasi saya dengan cukup baik:

https://git.wiki.kernel.org/index.php/GitSvnSwitch

Saya mengkloning menggunakan file://protokol, dan ingin beralih ke http://protokol.

Anda tergoda untuk mengedit urlpengaturan di [svn-remote "svn"]bagian .git/config, tapi ini tidak berhasil. Secara umum, Anda perlu mengikuti prosedur berikut:

  1. Alihkan urlpengaturan remote-svn ke nama baru.
  2. Lari git svn fetch. Ini perlu mengambil setidaknya satu revisi baru dari svn!
  3. Ubah pengaturan svn-remote urlkembali ke URL asli.
  4. Jalankan git svn rebase -luntuk melakukan rebase lokal (dengan perubahan yang datang dengan operasi pengambilan terakhir).
  5. Ubah pengaturan svn-remote urlkembali ke URL baru.
  6. Sekarang, git svn rebaseharus bekerja lagi.

Jiwa petualang mungkin ingin mencoba --rewrite-root.


2
agar adil, ini sebenarnya gagal bagi saya, dan saya akhirnya mengkloning ulang repo. Sulit untuk mendapatkan git untuk menanganinya ketika direktori svn diganti namanya.
Gregg Lind

Saya lebih suka menerima artikel yang lebih rinci, tetapi cukup adil, saya akan menerimanya sampai jawaban baru datang.
kch

2
Berikut deskripsi lain dari prosedur yang: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray

tautan yang diberikan dalam jawaban yang diterima sudah usang dan yang baru saat ini adalah: git.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.html Saya mengikuti "Kasus Umum" dan itu sederhana dan sangat bekerja dengan baik.
TcMaster

2
@TcMaster: bekerja untuk saya juga ... tapi itulah mengapa jawaban tidak boleh hanya berisi tautan, mereka menjadi usang dan menjadi tidak berguna ... Saya akan menambahkan jawaban wiki komunitas.
UncleZeiv

38

Anda dapat melihat apakah berikut ini berfungsi dengan baik:

  1. Jika svn-remote.svn.rewriteRoottidak ada di file config ( .git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. Jika svn-remote.svn.rewriteUUIDtidak ada di file konfigurasi:

    git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
    

    The currentRepositoryUUIDdapat diperoleh dari .git/svn/.metadata.

  3. git config svn-remote.svn.url <newRepositoryURL>


Fantastis - terima kasih, ini bekerja dengan baik untuk saya (dikloning melalui file://, beralih ke svn+ssh); hanya mencatat bahwa: prosedur ini tidak perlu "mengambil setidaknya satu revisi baru dari svn"; juga ./.git/svn/.metadatasetelah yang pertama svn rebaseberisi <newRepository>as reposRoot- tetapi ini tidak cukup untuk menghapus rewrite*kunci dari .git/config; jadi kunci-kunci itu harus disimpan secara permanen di sana, sejauh yang saya mengerti.
sdaau

1
Itu berhasil juga bagiku, seperti pesona. OP harus mencoba yang ini dan menganggapnya sebagai jawaban yang benar.
Rafareino

Sempurna. Saya memiliki proyek besar dengan ribuan komitmen dalam sejarah sehingga klon baru akan menghancurkan sejarah (atau membutuhkan waktu sangat lama untuk checkout). Saya menggunakan svn+ssh://dan svn-server kami baru saja mengubah domain dari .semenjadi .comuntuk membersihkan penamaan internal kami.
UlfR

Bekerja dengan baik untuk saya. Memiliki repo berusia 2 tahun dengan 1.000-an komit, repo dipindahkan ke host baru, jadi ini menghindari klon svn penuh (yang ditakuti).
David Victor

21

Sayangnya sebagian besar tautan di jawaban ini tidak berfungsi, jadi saya akan menduplikasi sedikit informasi dari git wiki untuk referensi di masa mendatang.

Solusi ini berhasil untuk saya:

  • Edit svn-remote url(atau fetchjalur) di .git/configuntuk mengarah ke domain / url / jalur baru

  • Jalankan git git svn fetch. Ini perlu mengambil setidaknya satu revisi baru dari svn!

  • Jika Anda mencoba git svn rebasesekarang, Anda akan mendapatkan pesan kesalahan seperti ini:

    Unable to determine upstream SVN information from working tree history
    

    Saya rasa ini karena git svndibingungkan oleh fakta bahwa komit terbaru Anda sebelum pengambilan akan git-svn-idmengarah ke jalur lama, yang tidak cocok dengan yang ditemukan di .git/config.

  • Sebagai solusinya, ubah svn-remote url(atau fetchjalur) kembali ke domain / url / jalur asli

  • Sekarang jalankan git svn rebase -llagi untuk melakukan rebase lokal dengan perubahan yang datang dengan operasi pengambilan terakhir. Kali ini akan berhasil, tampaknya karena git svntidak akan bingung dengan fakta bahwa git-svn-idkepala baru tidak cocok dengan yang ditemukan di .git/config.

  • Terakhir, ubah svn-remote url(atau fetchjalur) kembali ke domain / url / jalur baru

  • Pada titik ini git svn rebaseharus bekerja lagi!

Informasi asli ditemukan di sini .



2

git filter-branch

Skrip ini , diambil dari entri blog , telah berhasil untuk saya. Berikan URL repo lama dan baru sebagai parameter, seperti untuk svn switch --relocate.

Skrip memanggil git filter-branchuntuk menggantikan URL Subversion di git-svn-iddalam pesan komit, pembaruan .git/config, dan juga memperbarui git-svnmetadata dengan membuat ulang menggunakan git svn rebase. Meskipun git svn clonemungkin merupakan solusi yang lebih kuat, filter-branchpendekatan ini bekerja lebih cepat untuk repositori besar (jam vs. hari).

#!/bin/sh

# Must be called with two command-line args.
# Example: git-svn-relocate.sh http://old.server https://new.server
if [ $# -ne 2 ]
then
  echo "Please invoke this script with two command-line arguments (old and new SVN URLs)."
  exit $E_NO_ARGS
fi

# Prepare URLs for regex search and replace.
oldUrl=`echo $1 | awk '{gsub("[\\\.]", "\\\\\\\&");print}'`
newUrl=`echo $2 | awk '{gsub("[\\\&]", "\\\\\\\&");print}'`

filter="sed \"s|^git-svn-id: $oldUrl|git-svn-id: $newUrl|g\""
git filter-branch --msg-filter "$filter" -- --all

sed -i.backup -e "s|$oldUrl|$newUrl|g" .git/config

rm -rf .git/svn
git svn rebase

1

git_fast_filter

Namun lebih cepat dari git-filter-branch(yaitu, menit, bukan jam), tetapi serupa dalam semangat, adalah menggunakan git_fast_filter. Namun, ini membutuhkan sedikit lebih banyak pengkodean, dan tidak ada solusi siap pakai yang rapi. Berbeda dengan git-filter-branch, ini akan membuat repo baru dari yang lama . Diasumsikan bahwa mastermenunjuk ke komit SVN terakhir.

  1. Klon git_fast_filterdari repo Gitorious.
  2. Buat skrip Python di direktori yang sama tempat Anda mengkloning git_fast_filterberdasarkan Gist ini , setel bit yang dapat dieksekusi menggunakan chmod +x. Sesuaikan jalur repositori lama dan baru. (Isi skrip juga ditempel di bawah.)
  3. Inisialisasi repositori target baru menggunakan git init, ubah direktori kerja ke repo baru ini.
  4. Jalankan pipa berikut:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Salin .git/config, dan mungkin file lain yang relevan .git/infodari repo lama ke repo baru.

  6. Hapus .git/svn.
  7. Membuat git-svnmenyadari pemetaan angka revisi baru

    1. Menjalankan git branch refs/remotes/git-svn master

      • Remote git-svn Anda mungkin disebut berbeda dari refs/remotes/git-svn, berkonsultasi .git/config, svn-remotebagian
    2. Jalankan git svn info. Jika perintah ini macet, ada yang salah. Ini harus membangun kembali pemetaan nomor revisi.

    3. Hapus cabang palsu refs/remotes/git-svn, itu akan dibuat ulang olehgit-svn

  8. Sinkronisasi dengan menelepon git svn rebase.

Di bawah ini adalah isi commit_filter.py, ganti nilai IN_REPOdan yang OUT_REPOsesuai:

#!/usr/bin/python

from git_fast_filter import Commit, FastExportFilter
import re
import sys

IN_REPO = "https://svn.code.sf.net/p/matsim/code"
OUT_REPO = "https://svn.code.sf.net/p/matsim/source"

IN_REPO_RE = re.compile("^git-svn-id: %s" % re.escape(IN_REPO), re.M)
OUT_REPO_RE = "git-svn-id: %s" % OUT_REPO

def my_commit_callback(commit):
  commit.message = IN_REPO_RE.sub(OUT_REPO_RE, commit.message)
  sys.stderr.write(".")

filter = FastExportFilter(commit_callback = my_commit_callback)
filter.run()

0

git svn rebase -lSolusi di atas tidak berhasil untuk saya. Saya memutuskan untuk melakukannya dengan cara yang berbeda:

  1. Kloning repo SVN lama menjadi git repo olddan SVN baru ke dalam git reponew
  2. Ambil oldkenew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newdi atas old(semestinya berhasil karena pohon di akar newdan ujungnya oldidentik)
    • git checkout master(Asumsikan bahwa mastercabang menunjuk ke kepala SVN. Ini akan menjadi kasus dengan klon bersih; jika tidak lakukan sebelum Anda memulai.)
    • git rebase --root --onto old
  4. Membangun kembali metadata git-svn newuntuk memperhitungkan rebase
    • git update-ref --no-deref refs/remotes/git-svn master(sesuaikan referensi jarak jauh tergantung pada bagaimana Anda mengkloning, misalnya bisa jadi refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info

1. Apakah Anda memulai dengan klon baru dari lokasi baru ke yang baru? Jika ya, mengapa Anda belum selesai pada saat itu? 2. Jika Anda rebase baru pada yang lama, apakah komit lama Anda semua menyebutkan URL lama dalam entri log komit svn-id mereka? 3. Apakah ada dokumentasi yang disimpan untuk menghapus .git / svn? (3b: perintah mana yang membangun kembali metadata git-svn, info git svn?)
Micha Wiedenmann

0

Berdasarkan beberapa tanggapan lain untuk pertanyaan ini, saya telah menemukan skrip Ruby yang menangani relokasi git-svn. Anda dapat menemukannya di https://gist.github.com/henderea/6e779b66be3580c9a584 .

Ini menangani relokasi tanpa memeriksa salinan lain, dan bahkan menangani kasus di mana ada perubahan yang tidak didorong di satu atau lebih cabang (karena itu merusak logika reguler). Ini menggunakan hal-hal dari jawaban git filter-branch (untuk logika utama) dan jawaban tentang menyalin cabang dari satu contoh repo ke yang lain (untuk menyalin cabang dengan perubahan yang tidak didorong).

Saya telah menggunakan ini untuk merelokasi sekelompok repo git-svn yang saya miliki untuk bekerja, dan versi skrip ini (saya telah melalui iterasi yang tak terhitung jumlahnya) tampaknya berhasil untuk saya. Ini tidak super cepat, tetapi tampaknya menangani semua kasus yang saya temui dan menghasilkan repo yang sepenuhnya dipindahkan.

Skrip memberi Anda opsi untuk membuat salinan repo sebelum membuat perubahan apa pun, sehingga Anda dapat menggunakan opsi ini untuk membuat cadangan. Membuat salinan diperlukan jika Anda memiliki perubahan yang tidak didorong di cabang mana pun.

Skrip tidak menggunakan permata atau pustaka lain yang tidak termasuk dalam instalasi normal MRI Ruby. Itu menggunakan library readline dan fileutils yang disertakan dalam MRI.

Semoga naskah saya terbukti bermanfaat bagi orang lain. Jangan ragu untuk melakukan perubahan pada skrip.

CATATAN: Saya hanya menguji skrip ini dengan git 2.3.0 / 2.3.1 dan Ruby 2.2.0 di OS X 10.10 Yosemite (karena itulah lingkungan yang saya gunakan), tetapi saya berharap ini juga berfungsi di lingkungan lain. Tidak ada jaminan tentang Windows.

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.