Mevcut bir Git deposunu SVN'ye gönderme


384

Git'te tüm işlerimi yapıyorum ve GitHub'a itiyorum. Hem yazılımdan hem de siteden çok memnun kaldım ve bu noktada çalışma pratiklerimi değiştirmek istemiyorum.

Doktora danışmanım, tüm öğrencilerden çalışmalarını üniversitede barındırılan bir SVN deposunda tutmasını istiyor. Mevcut bir SVN deposunu Git'e çekmek için tonlarca belge ve öğretici buldum, ancak Git deposunu yeni bir SVN deposuna itmekle ilgili hiçbir şey yok. Ben git-svn ve taze bir şube ve yeniden basma ve tüm bu harika terimlerin bir kombinasyonu ile bunu yapmak için bir yol olması gerektiğini umuyorum, ama ben bir Git newbie ve bunlardan hiçbirine güvenmiyorum.

Daha sonra, seçtiğimde bu SVN deposuna taahhütleri iletmek için birkaç komut çalıştırmak istiyorum. Git'i kullanmaya devam etmek ve Git'teki SVN veri havuzuna sahip olmak istiyorum.

Fark yaratırsa, SVN'ye taahhüt eden tek kişi ben olacağım.


1
Not: Bunu yaptığınızda muhtemelen orijinal tarih pullarınızı kaybedersiniz. Yeni tarihler, Subversion'a aktarma zamanını temel alacaktır.
nobar

Daha güncel bilgiler arayanlar için otomasyon arayışı sırasında aşağıdaki yazı yararlı olabilir: deliciousbrains.com/deploying-wordpress-plugins-travis
Josh Habdas 13:07

Yanıtlar:


402

Buna da ihtiyacım vardı ve Bombe'nin cevabı + etrafta dolaşmakla işe başladım. İşte tarif:

İçe Aktar Git -> Alt Sürüm

1. cd /path/to/git/localrepo
2. svn mkdir --parents protocol:///path/to/repo/PROJECT/trunk -m "Importing git repo"
3. git svn init protocol:///path/to/repo/PROJECT -s
4. git svn fetch
5. git rebase origin/trunk
5.1.  git status
5.2.  git add (conflicted-files)
5.3.  git rebase --continue
5.4.  (repeat 5.1.)
6. git svn dcommit

# 3'ten sonra böyle şifreli bir mesaj alacaksınız:

Daha yüksek URL seviyesi kullanma: protocol:///path/to/repo/PROJECT => protocol:///path/to/repo

Sadece görmezden gel.

# 5 çalıştırdığınızda, çakışmalar yaşayabilirsiniz . Durum "birleştirilmemiş" dosyaları ekleyerek ve rebase devam ettirerek bunları çözün. Sonunda, işiniz bitti; daha sonra kullanarak SVN deposuna geri senkronize edin dcommit. Bu kadar.

Depoları senkronize tutma

Şimdi aşağıdaki komutları kullanarak SVN'den Git'e senkronize edebilirsiniz:

git svn fetch
git rebase trunk

Git'ten SVN'ye senkronize etmek için şunu kullanın:

git svn dcommit

Son not

Canlı bir veri havuzuna başvurmadan önce bunu yerel bir kopyada denemek isteyebilirsiniz. Git deponuzun geçici bir yere kopyasını alabilirsiniz; cp -rtüm veriler depoda olduğu için kullanın . Daha sonra aşağıdakileri kullanarak dosya tabanlı bir test havuzu oluşturabilirsiniz:

svnadmin create /home/name/tmp/test-repo

Ve aşağıdakileri kullanarak çalışan bir kopyayı kontrol edin:

svn co file:///home/name/tmp/test-repo svn-working-copy

Bu, kalıcı değişiklikler yapmadan önce bir şeylerle oynamanıza izin verecektir.

Zeyilname: Berbat olursanız git svn init

Yanlışlıkla git svn inityanlış URL ile çalışırsanız ve çalışmanızın yedeğini alacak kadar akıllı değilseniz (sormayın ...), aynı komutu tekrar çalıştıramazsınız. Ancak, aşağıdakileri yaparak değişiklikleri geri alabilirsiniz:

rm -rf .git/svn
edit .git/config

Ve bölüm [svn-remote "svn"]bölümünü kaldırın .

Daha sonra git svn inityeniden çalıştırabilirsiniz .


2
Güzel cevap. Bu aynı zamanda taahhüt tarihlerini de bozuyor mu?
Drew Noakes

4
Güzel sorular - Maalesef, cevabını da bilmiyorum. Bu daha çok işe yaradığımı gösteren pratik bir rehber. Tüm detayları tam olarak anlamıyorum. Teslim tarihlerine gelince, sanırım bir test yapabilir ve öğrenebilirsiniz. Bazı şeyleri test etmek için yerel (fs tabanlı) bir svn repo başlatabileceğinizi unutmayın.
troelskn

10
Adım 5 yerine "git rebase --onto trunk --root" kullanarak da aynı adımları izledim ve çok daha başarılı oldum . Ton yerine bir avuç birleştirme çatışması çözülecek.
kubi

5
Benim durumumda bu dizi işe yaramadı. Her zaman "HEAD geçmişinden gelen yukarı akış SVN bilgileri belirlenemedi" mesajı görüntülendi. Yani, dcommit mümkün değil.
Fedir RYKHTIK

2
Boşver, SVN standart kurulumunu (trunk / branch / tags /) takip etmek istemediğim için akıllı olmaya ve -s'yi atlamaya çalıştım. Onsuz çalışamazdı.
James McMahon

33

İşte böyle yaptık:

Git deponuzu makinenizin herhangi bir yerinde klonlayın.

.Git / config dosyasını açın ve aşağıdakileri ekleyin ( Git havuzunun salt okunur bir SVN aynasını koruma bölümünden ):

[svn-remote "svn"]
    url = https://your.svn.repo
    fetch = :refs/remotes/git-svn

Şimdi, bir konsol penceresinden şunu yazın:

git svn fetch svn
git checkout -b svn git-svn
git merge master

Şimdi, herhangi bir nedenle burada kırılırsa, şu üç satırı yazın:

git checkout --theirs .
git add .
git commit -m "some message"

Ve son olarak, SVN'yi taahhüt edebilirsiniz:

git svn dcommit

Not: Daha sonra o klasörü her zaman sıyırırım.


6
+1 bu aslında benim için çalıştı (ne olursa olsun gövde / baz yok), vermeye devam eden diğer cevapların aksineUnable to determine upstream SVN information from HEAD history.
stijn


2
Bu tekniği denedim, ama tarih ithal etmedi. Btw, "git merge master" şimdi "git merge --allow-ilgisiz-geçmişler ustası"
Berend de Boer

1
SVN'de olanların üzerine git ile birlikte yazmak istiyorsanız, kullanın git merge -s recursive -Xtheirs --allow-unrelated-histories master.
user1475814

28

git rebaseDoğrudan kullanmak ilk taahhüdü kaybedecektir. Git farklı davranır ve yeniden pazarlayamaz.

Tüm geçmişi koruyacak bir prosedür vardır: http://kerneltrap.org/mailarchive/git/2008/10/26/3815034

Çözümü burada yazacağım, ancak krediler Björn için.

Git-svn'yi başlat:

git svn init -s --prefix=svn/ https://svn/svn/SANDBOX/warren/test2

--Prefix size "svn / trunk" gibi uzaktan izleme şubeleri verir. Ve -sstandart gövde / etiketler / dallar düzeni için bir kısayoldur.

SVN'den ilk şeyleri alın:

git svn fetch

Şimdi kök taahhüdünüzün karmasına bakın (tek bir taahhüt göstermelidir):

git rev-list --parents master | grep '^.\{40\}$'

Sonra boş bagaj taahhüdünün karmasını alın:

git rev-parse svn/trunk

Grefti oluşturun:

echo <root-commit-hash> <svn-trunk-commit-hash> >> .git/info/grafts

Şimdi, "gitk" svn/trunkana dalınızın dayandığı ilk işlem olarak gösterilmelidir .

Grefti kalıcı hale getirin:

git filter-branch -- ^svn/trunk --all

Grefti bırakın:

rm .git/info/grafts

gitk hala svn/trunkefendinin soyunda gösterilmeli.

Geçmişinizi bagajın üstüne doğrusallaştırın:

git svn rebase

Ve şimdi "git svn dcommit -n" bunun gövdeye bağlanacağını söylemelidir.

git svn dcommit

Bu tekniğin yukarıdakinden nasıl farklı olduğunu daha net açıklayabilir misiniz?
cmcginty

3
"Git rev-parse svn / trunk" komutunu denediğimde, çalışma ağacında olmayan bilinmeyen bir düzeltme veya yol bildiriyor.
Adam Ness

Git filtre-şube ve damla greft gerekli değildi dışında benim için çalışan tek cevap bu: Greft oluşturduktan sonra bir rebase yaptım ve sonra git svn dcommit yaptım.
fc7

8

Projeniz için Subversion deposunda yeni bir dizin oluşturun.

# svn mkdir --parents svn://ip/path/project/trunk

Git tarafından yönetilen projenize geçin ve git-svn'yi başlatın.

# git svn init svn://ip/path/project -s
# git svn fetch

Bu, SVN proje dizininiz hala boş olduğu için tek bir taahhüt oluşturur. Şimdi bu taahhüdün üzerindeki herşeyi yeniden temellendirin git svn dcommitve yapılması gerekir. Ancak, taahhüt tarihlerinizi ciddi şekilde bertaraf edecektir.


Bu yanıtı hassox.blogspot.com/2007/12/using-git-with-svn.html adresindeki talimatlarla kullandım . Sonra: # git checkout -b local-svn trunk # git merge master # git svn dcommit .gitvore .svn dizinini unutmayın!
cflewis

Aynı işlemi yaptığım gibi, bir süre için (Ocak '09) git'in kök taahhüdünde rebase işlemi yapabileceğini açıkça belirtmek istedim. Bu, işlemi eski makalelerin birçoğundan daha kolay hale getirir, onun
Louis Jacomet

"-S" git svn init seçeneği ne işe yarar? Git svn için man sayfalarında bunu göremiyorum.
Nathan

Man sayfasını tekrar okuyun, belki orada olduğu için “-s” kelimesini aratın. “--Stdlayout” için bir takma addır.
Bombe

7

Git -> Tam taahhüt geçmişine sahip SVN

Bir Git projem vardı ve onu SVN'ye taşımak zorunda kaldım. Tüm taahhüt tarihini koruyarak böyle yaptım. Kaybolan tek şey, libSVN'nin yaptığımız yerel saati ayarlayacağı için orijinal işlem süresidir git svn dcommit.

Nasıl:

  1. Eşyalarımızı içeri aktarmak ve git-svn ile klonlamak istediğimiz bir SVN deponuz olsun:

    git svn clone https://path.to/svn/repository repo.git-svn`
    
  2. Oraya git:

    cd repo.git-svn
    
  3. Git deposunun uzaktan kumandasını ekleyin (bu örnekte C: /Projects/repo.git kullanıyorum ). SVN'ye göndermek ve ona old-git adını vermek istiyorsunuz:

    git remote add old-git file:///C/Projects/repo.git/
    
  4. Master-daldaki bilgileri, eski git deposundan geçerli depoya getirin:

    git fetch old-git master
    
  5. Eski git kumandanın ana dalını geçerli depoda eski adlı yeni bir dalda kullanıma alma:

    git checkout -b old old-git/master`
    
  6. HEAD'ı eski-git / master'ın üstüne koymak için yeniden başlayın. Bu, tüm taahhütlerinizi koruyacaktır. Bunun temelde yaptığı şey Git'teki tüm işlerinizi alıp SVN'den eriştiğiniz işin üstüne koymaktır.

    git rebase master
    
  7. Şimdi ana dalınıza geri dönün:

    git checkout master
    

    Ve temiz bir taahhüt geçmişiniz olduğunu görebilirsiniz. SVN'ye itmek istediğiniz budur.

  8. Çalışmanızı SVN'ye aktarın:

    git svn dcommit
    

Bu kadar. Çok temiz, kesmek yok ve her şey kutudan mükemmel çalışıyor. Zevk almak.



Görünüşe göre. Ancak, yolunu oldukça kafa karıştırıcı buluyorum ve benimki çok daha kısa (19/23'ten 8 adım). Belki onu doğru alamıyorum ama sanırım ikinci mermisinde svn ve git komutlarını karıştırıyor.
codingdave

Ah, evet, fark şu ki, işleminiz SVN deposunun köküne git, onun bir alt klasöre aktarması, bu yüzden birkaç git svnhazırlık gerekli.
TWiStErRob

7. adımda, eski bir git birleştirme olmamalı mı? Benim için değişmemiş bir ustalık dcommit yapıyor musunuz ?!
Alexander

@Alexander 'git rebase master' kullanarak hızlı ileri bir birleştirme sağlıyoruz, bu iki ebeveyn içeren bir birleştirme taahhüdü olmadan doğrusal bir birleştirme. Burada doğrusal bir geçmişe sahip olmak istiyoruz.
codingdave


3

Mevcut Git veri havuzumu boş bir SVN veri havuzuna koymam gerekiyordu.

Bunu nasıl yapmayı başardım:

$ git checkout master
$ git branch svn
$ git svn init -s --prefix=svn/ --username <user> https://path.to.repo.com/svn/project/
$ git checkout svn
$ git svn fetch
$ git reset --hard remotes/svn/trunk
$ git merge master
$ git svn dcommit

Sorunsuz çalıştı. Umarım bu birine yardımcı olur.

Kendimi SVN deposuna farklı bir kullanıcı adıyla yetkilendirmek zorunda olduğumdan ( originözel / genel anahtar kimlik doğrulaması kullanıyorum), --usernamemülkü kullanmak zorunda kaldım .


git-svnbu mümkün olmadan önce yüklemeniz gerekebilir , bkz. stackoverflow.com/questions/527037/git-svn-not-a-git-command
flexponsive

2

Eğer ana depo ve "ihracat" zaman zaman SVN revizyonları sadece ihtiyaç olarak Git ile çalışmaya devam etmek istiyorsanız şunu kullanabilirsiniz Tailor senkronize SVN deposunu tutmak. Farklı kaynak kontrol sistemleri arasındaki düzeltmeleri kopyalayabilir ve Git'te yaptığınız değişikliklerle SVN'yi güncelleyecektir.

Git-SVN dönüşümü denemedim, ancak SVN -> SVN örneği için bu cevaba bakınız .


2

Yine çalışan başka bir dizi (her adımda bazı yorumlarla):

  1. Kurulum git-svnve subversionaraç setleri:

    sudo apt-get install git-svn subversion
    
  2. İçinde geçiş yap PROJECT_FOLDER

    cd PROJECT_FOLDER
    
  3. Subversion sunucusunda proje yolunu oluşturun (maalesef mevcut git-svneklentinin TortoiseSVN ile karşılaştırıldığında bir kusuru var). Kaynak kodu doğrudanPROJECT_FOLDER . Bunun yerine, varsayılan olarak tüm kodu içine yükler PROJECT_FOLDER/trunk.

    svn mkdir --parents protokolü: /// path / to / repo / PROJECT_FOLDER / trunk -m "git repo yer tutucusu oluşturuluyor"

Bu, trunkyolun sonunda zorunlu olan yerdir

  1. Klasör git-svniçindeki eklenti içeriğini başlat.git

    git svn init -s protocol:///path/to/repo/PROJECT_FOLDER
    

    Burası trunkyolun sonunda gereksiz olan yer

  2. Boş bir Subversiondepo bilgilerini getir

    git svn fetch
    

    Bu adım, Subversion sunucusunu git-svneklentiyle senkronize etmeye yardımcı olur . Bu, git-svneklentinin remotes/originyolu oluşturduğu ve trunksunucu tarafındaki alt klasörle ilişkilendirdiği andır .

  3. Rebase eski Git taahhütleri, git-svneklenti sürece dahil edilmeden önce gerçekleşti (bu adım isteğe bağlıdır )

    git rebase origin/trunk
    
  4. Taahhüt edilecek yeni / değiştirilmiş dosyalar ekleyin (bu adım Git etkinlikleri için normaldir ve isteğe bağlıdır )

    git add .
    
  5. Yeni eklenen dosyaları yerel Git deposuna kaydedin (bu adım isteğe bağlıdır ve yalnızca 7. adım kullanılmışsa geçerlidir):

    git commit -m "Importing Git repository"
    
  6. Tüm proje değişiklik geçmişini Subversion sunucusuna göndermek:

    git svn dcommit
    

1

Yeni bir SVN deposu oluşturabilirsiniz. Git projenizi dışa aktarın (.git dosyalarını silin). Bunu SVN veri havuzuna ekleyin (depoyu Git'te şu ana kadar olanla başlatma). Ardından yeni bir Git projesinde SVN depolarını içe aktarmak için talimatları kullanın.

Ancak bu, önceki Git geçmişinizi kaybedecektir.



1

Scatter adlı WordPress topluluğunda kullanılan harika bir aracı paylaşmak istiyorum

Git WordPress eklentileri ve biraz akıl sağlığı dağılımı

Bu, kullanıcıların Git depolarını wordpress.org SVN'ye otomatik olarak gönderebilmelerini sağlar. Teorik olarak, bu kod herhangi bir SVN deposuna uygulanabilir.


Bağlantı etkili bir şekilde kesilmiş gibi görünüyor ( "evansolomon.me sunucusunun yanıt vermesi çok uzun sürüyor." ).
Peter Mortensen

1

Son zamanlarda birkaç Git deposunu SVN'ye taşımak zorunda kaldım ve bulabildiğim tüm çözümleri denedikten sonra, nihayet benim için işe yarayan Mercurial (evet, üçüncü bir VCS kullanarak ). Bu kılavuzu kullanarak , aşağıdaki işlemi buldum (Linux'ta, ancak temel fikir Windows'ta da çalışmalıdır).

  1. Gerekli paketler:

    $ sudo apt-get install git subversion mercurial python-subversion
    
  2. Mercurial şunlara eklenerek yapılandırılmalıdır ~/.hgrc:

    [extensions]
    hgext.convert=
    
  3. Bazı geçici çalışma dizinleri oluşturun (geçiş yapmak için birkaç havuzum vardı, bu yüzden onları ayrı tutmak için SVN ve Git sürümleri için dizinler oluşturdum):

    $ mkdir svn
    $ mkdir git
    
  4. Boş bir yerel SVN deposu oluşturun:

    $ svnadmin create svn/project
    
  5. Mevcut Git deposunu klonlayın:

    $ git clone server/path/project.git git/project
    
  6. Mercurial'ın işini yapmasına izin ver:

    $ hg convert --dest-type svn git/project svn/project
    
  7. Şimdi SVN deposu, tam zamanlama geçmişini içermelidir, ancak orijinal zaman damgalarıyla birlikte olmamalıdır. Bu bir sorun değilse, 11. adıma sonraki bölümü atlayın.

  8. Küçük bir çalışma ile her bir taahhüdün tarihi ve saati değiştirilebilir . Depolarım oldukça küçük olduğu için manuel olarak yapmam mümkün oldu. İlk olarak, pre-revprop-changegerekli özelliğin değiştirilmesine izin vermek için SVN deposunda aşağıdaki içeriğe sahip bir kanca oluşturun :

    #!/bin/bash
    exit 0;
    

    Bu komut dosyasının yürütülebilir olması gerekir:

    $ chmod +x svn/project/hooks/pre-revprop-change
    
  9. Mercurial, SVN deposunun project -wc adlı çalışan bir kopyasını oluşturdu , bu yüzden ona geçin ve işleme sürelerini düzenleyin:

    $ cd project-wc
    $ svn propedit svn:date --revprop -r 1
    

    Doğru tarih ve saati girin (saat dilimlerine dikkat edin!) Ve kaydedin. "Özellik svn: revizyon 1'deki tarih için yeni değer ayarla" iletisini almalısınız.
    Şimdi durulayın ve diğer tüm revizyonlar için tekrarlayın.

  10. İsteğe bağlı olarak, her şeyin yolunda gittiğinden emin olmak için taahhüt geçmişini kontrol edin:

    $ svn log -r 1:HEAD
    

    Ardından bir seviye yukarı çıkın:

    $ cd ..
    
  11. Havuzu boşaltın:

    $ svnadmin dump svn/project > project.dump
    
  12. Dökümü Subversion sunucunuza yükleyin. Bitti!

Bu işlem muhtemelen doğrudan uzak depolar arasında da işe yarayacaktır, ancak yerel olanlarla çalışmayı daha kolay buldum. İşlem zamanlarını düzeltmek çok işti, ancak genel olarak süreç bulduğum diğer yöntemlerden çok daha basitti.


1

üç yöntem var :

  1. rebase : diğer cevaplar gibi

  2. İlk id işlemek ve id taahhüt ilk git'e svn bulmak .git / bilgi / greft içine onların yankı: id işlemek echo "git_id svn_id}" > .git/info/graftssonragit svn dcommit

  3. her git komutunu kullanıma alma, dosyaları svn_repo'ya kopyalama

bash demo : github demosu

v1.x reb rebase kullan ve id kimliği

v2.x: kopya dosyalarını kullanın, sonra svn commit


0

Benim durumumda, SVN'den temiz bir proje başlatmak zorunda kaldım

$ Project> git svn init protocol://path/to/repo -s
$ Project> git svn fetch

tüm proje kaynaklarınızı ekleyin ...

$ Project> git add .
$ Project> git commit -m "Importing project sources"
$ Project> git svn dcommit

0

Deneyimlerimin bir kısmını kabul edilen cevapla paylaşmak istiyorum. Tüm adımları yaptım ve son adımı çalıştırmadan önce her şey yolundaydı:

git svn dcommit

$ git svn dcommit

Başlatılmamış $ u değerinin /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm 101 numaralı satırda (s ///) yerine kullanılması.

/Usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm satır 101'de bitiştirilmemiş (.) Veya dizgide başlatılmamış $ u değeri. Refs / remotes / origin / HEAD: ' https://192.168.2.101/ svn / PROJECT_NAME ',' 'içinde bulunamadı

Https://github.com/nirvdrum/svn2git/issues/50 iş parçacığını ve son olarak 101 /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm satırında aşağıdaki dosyaya uyguladığım çözümü buldum

Ben değiştirdim

$u =~ s!^\Q$url\E(/|$)!! or die

ile

if (!$u) {
    $u = $pathname;
} 
else {
       $u =~ s!^\Q$url\E(/|$)!! or die
      "$refname: '$url' not found in '$u'\n";
}

Bu benim sorunumu çözdü.


-1

Her şeyi taahhüt etmek istemezseniz ne olur? taahhüdü SVN deposuna vermek ? Ya sadece boruyu seçici olarak göndermek istiyorsanız? Daha iyi bir çözümüm var.

Yaptığım tek şeyin SVN'den almak ve birleştirmek olduğu bir yerel Git deposunu saklıyorum. Bu şekilde SVN ile aynı değişiklikleri dahil ettiğimden emin olabilirim, ancak taahhüt geçmişimi SVN'den tamamen ayrı tutuyorum.

Sonra ayrı bir klasörde ayrı bir SVN yerel çalışma kopyasını tutmak. SVN'ye geri verdiğim şey bu ve sadece bunun için SVN komut satırı yardımcı programını kullanıyorum.

Yerel Git veri havuzumun durumunu SVN'ye vermeye hazır olduğumda, tüm dosya karmaşasını yerel SVN çalışma kopyasına kopyalayıp Git yerine SVN'yi kullanarak oraya veriyorum.

Bu şekilde hiçbir zaman yeniden baslatma yapmak zorunda kalmam, çünkü yeniden basmak serbest taban gibidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.