ผลักดันที่เก็บ Git ที่มีอยู่ไปยัง SVN


384

ฉันทำงานทั้งหมดของฉันใน Git และผลักดันให้ GitHub ฉันมีความสุขมากกับทั้งซอฟต์แวร์และเว็บไซต์และฉันไม่ต้องการเปลี่ยนวิธีการทำงานของฉันในตอนนี้

อาจารย์ที่ปรึกษาระดับปริญญาเอกของฉันขอให้นักเรียนทุกคนทำงานในที่เก็บ SVN ที่โฮสต์อยู่ที่มหาวิทยาลัย ฉันได้พบเอกสารและแบบฝึกหัดมากมายเกี่ยวกับการดึงที่เก็บ SVN ที่มีอยู่ลงใน Git แต่ไม่มีอะไรเกี่ยวกับการผลักดันที่เก็บ Git ไปยังที่เก็บ SVN ใหม่ ฉันคาดหวังว่าจะต้องมีวิธีในการทำเช่นนี้ด้วยการผสมผสานของ git-svn และสาขาที่สดใหม่และการลดราคาและเงื่อนไขที่ยอดเยี่ยมทั้งหมด แต่ฉันเป็นมือใหม่ Git และไม่รู้สึกมั่นใจกับพวกเขาเลย

จากนั้นฉันต้องการเรียกใช้คำสั่งสองสามคำสั่งเพื่อส่งไปยังที่เก็บ SVN เมื่อฉันเลือก ฉันต้องการใช้ Git ต่อไปและเพียงแค่มีที่เก็บ SVN ใน Git

ฉันจะเป็นคนเดียวที่เคยยอมรับกับ SVN หากสิ่งนี้สร้างความแตกต่าง


1
โปรดทราบ: คุณอาจสูญเสียการประทับวันที่เดิมเมื่อคุณทำเช่นนี้ วันที่ใหม่จะขึ้นอยู่กับเวลาของการนำเข้าสู่การโค่นล้ม
สูงศักดิ์

สำหรับผู้ที่มองหาข้อมูลที่เป็นปัจจุบันมากขึ้นบางคนอาจพบว่าโพสต์ต่อไปนี้มีประโยชน์ในระหว่างการค้นหาไปยังระบบอัตโนมัติ: Deliciousbrains.com/deploying-wordpress-plugins-travis
Josh Habdas

คำตอบ:


402

ฉันต้องการสิ่งนี้เช่นกันและด้วยความช่วยเหลือจากคำตอบของ Bombe + ที่เล่นซอไปรอบ ๆ ฉันทำให้มันทำงานได้ นี่คือสูตรของ:

นำเข้า Git -> การโค่นล้ม

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 คุณจะได้รับข้อความที่เป็นความลับดังนี้:

ใช้ระดับที่สูงขึ้นของ URL: protocol:///path/to/repo/PROJECT => protocol:///path/to/repo

เพียงแค่เพิกเฉย

เมื่อคุณรัน # 5 คุณอาจได้รับข้อขัดแย้ง แก้ไขไฟล์เหล่านี้ด้วยการเพิ่มไฟล์ที่มีสถานะ "unmerged" และดำเนินการ rebase ต่อ ในที่สุดคุณจะทำ; แล้วซิงค์กลับไปยังพื้นที่เก็บข้อมูล SVN dcommitโดยใช้ นั่นคือทั้งหมดที่

การทำให้ที่เก็บข้อมูลตรงกัน

ตอนนี้คุณสามารถซิงโครไนซ์จาก SVN ถึง Git โดยใช้คำสั่งต่อไปนี้:

git svn fetch
git rebase trunk

และในการซิงโครไนซ์จาก Git ไปยัง SVN ให้ใช้:

git svn dcommit

หมายเหตุสุดท้าย

คุณอาจต้องการลองใช้กับสำเนาโลคัลก่อนใช้กับที่เก็บแบบสด คุณสามารถทำสำเนาของที่เก็บ Git ของคุณไปยังสถานที่ชั่วคราว ใช้เพียงcp -rเพราะข้อมูลทั้งหมดอยู่ในพื้นที่เก็บข้อมูลของตัวเอง จากนั้นคุณสามารถตั้งค่าที่เก็บไฟล์ทดสอบโดยใช้:

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

และตรวจสอบสำเนาทำงานโดยใช้:

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

ที่จะช่วยให้คุณสามารถเล่นกับสิ่งต่าง ๆ ก่อนที่จะทำการเปลี่ยนแปลงที่ยั่งยืน

ภาคผนวก: ถ้าคุณทำผิดพลาด git svn init

หากคุณเรียกใช้git svn initURL ผิดโดยไม่ตั้งใจและคุณไม่ฉลาดพอที่จะสำรองข้อมูลงานของคุณ (ไม่ต้องถาม ... ) คุณจะไม่สามารถเรียกใช้คำสั่งเดิมอีกครั้งได้ อย่างไรก็ตามคุณสามารถยกเลิกการเปลี่ยนแปลงได้โดยการออก:

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

และลบส่วนใน[svn-remote "svn"]ส่วน

จากนั้นคุณสามารถเรียกใช้git svn initใหม่ได้


2
คำตอบที่ดี สิ่งนี้จะทำให้วันที่ที่มอบหมายนั้นยุ่งเหยิงหรือไม่?
Drew Noakes

4
คำถามที่ดี - น่าเสียดายที่ฉันไม่รู้คำตอบเช่นกัน นี่เป็นคำแนะนำที่ใช้งานได้จริงของสิ่งที่ฉันพบว่าทำงาน ฉันไม่เข้าใจรายละเอียดทั้งหมดอย่างสมบูรณ์ ฉันเดาว่าคุณสามารถทำการทดสอบและหาคำตอบได้ จำไว้ว่าคุณสามารถเริ่มต้น repo svn repo ในท้องถิ่นเพื่อทดสอบสิ่งต่างๆ
troelskn

10
ฉันได้ทำตามขั้นตอนเหล่านี้เหมือนกันโดยใช้ "คอมไพล์ rebase --onto ลำต้น --root" ในสถานที่ของขั้นตอนที่ 5 และมีมากความสำเร็จมากขึ้น เพียงผสานความขัดแย้งจำนวนหนึ่งเพื่อแก้ไขแทนที่จะเป็นตัน
kubi

5
ในกรณีของฉันลำดับนี้ไม่ทำงาน จะมีข้อความ "ไม่สามารถระบุข้อมูล SVN ต้นน้ำจากประวัติ HEAD" ได้เสมอ ดังนั้นไม่เป็นไปได้ dcommit
Fedir RYKHTIK

2
ไม่เป็นไรฉันพยายามทำให้ฉลาดและไม่ใช้ -s เนื่องจากฉันไม่ต้องการทำตามการตั้งค่ามาตรฐาน SVN (งวง / กิ่ง / แท็ก /) ไม่สามารถทำให้มันทำงานได้เลยหากปราศจากสิ่งนั้น
James McMahon

33

นี่คือวิธีที่เราทำให้มันทำงาน:

โคลนที่เก็บ Git ของคุณที่ใดที่หนึ่งบนเครื่องของคุณ

เปิด. git / config และเพิ่มรายการต่อไปนี้ (จากการดูแลมิรเรอร์ SVN แบบอ่านอย่างเดียวของที่เก็บ Git ):

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

ตอนนี้จากหน้าต่างคอนโซลพิมพ์เหล่านี้:

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

ทีนี้ถ้ามันหยุดตรงนี้ด้วยเหตุผลใดก็ตามให้พิมพ์สามบรรทัดนี้:

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

และในที่สุดคุณสามารถมอบให้กับ SVN:

git svn dcommit

หมายเหตุ: ฉันมักจะทำให้เสียโฟลเดอร์นั้นในภายหลัง


6
+1 นี้ใช้งานได้จริงสำหรับฉัน (ไม่มีลำตัว / ฐานอะไรเลย) ตรงกันข้ามกับคำตอบอื่น ๆ ที่ยังคงให้อยู่Unable to determine upstream SVN information from HEAD history.
stijn

2
ข้อสรุปที่ดีอีกประการหนึ่งคือcodeography.com/2010/03/17/howto-mirror-git-to-subversion.html
Tommy

2
ฉันลองใช้เทคนิคนี้ แต่ไม่ได้นำเข้าประวัติ Btw, "git merge master" ได้กลายเป็น "git merge - ไม่ได้เป็นมาสเตอร์ - ประวัติที่ไม่เกี่ยวข้อง"
Berend de Boer

1
ถ้าคุณอย่างต้องการจะเขียนทับสิ่งที่อยู่ใน SVN git merge -s recursive -Xtheirs --allow-unrelated-histories masterกับสิ่งที่อยู่ในคอมไพล์ใช้
user1475814

28

การใช้git rebaseโดยตรงจะเสียการกระทำครั้งแรก Git ปฏิบัติต่อมันแตกต่างกันและไม่สามารถรีบูตได้

มีขั้นตอนที่จะรักษาประวัติแบบเต็ม: http://kerneltrap.org/mailarchive/git/2008/10/26/3815034

ฉันจะคัดลอกโซลูชันที่นี่ แต่เครดิตสำหรับBjörn

เริ่มต้น git-svn:

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

- คำนำหน้าช่วยให้คุณสามารถติดตามสาขาระยะไกลเช่น "svn / trunk" ซึ่งเป็นสิ่งที่ดีเพราะคุณไม่ได้ชื่อที่ไม่ชัดเจนถ้าคุณเรียกสาขาในท้องถิ่นของคุณเพียงแค่ "ลำต้น" จากนั้น และ-sเป็นทางลัดสำหรับเค้าโครง / แท็ก / กิ่งสาขามาตรฐาน

ดึงข้อมูลเริ่มต้นจาก SVN:

git svn fetch

ตอนนี้ค้นหาแฮชของการคอมมิท (ควรแสดงการคอมมิชชันเดียว):

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

จากนั้นรับค่าแฮชของ trunk trunk ที่ว่างเปล่า:

git rev-parse svn/trunk

สร้างการรับสินบน:

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

ตอนนี้ "gitk" ควรจะแสดงsvn/trunkเป็นรายการแรกที่อิงกับสาขาหลักของคุณ

ทำให้การรับสินบนถาวร:

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

วางกราฟต์:

rm .git/info/grafts

gitk ยังควรแสดงsvn/trunkในบรรพบุรุษของเจ้านาย

ทำให้ประวัติของคุณเป็นเชิงเส้นที่ด้านบนของลำตัว:

git svn rebase

และตอนนี้ "git svn dcommit -n" ควรบอกคุณว่ากำลังจะส่งไปยังลำตัว

git svn dcommit

คุณช่วยอธิบายได้ไหมว่าเทคนิคนี้แตกต่างจากด้านบนอย่างไร
cmcginty

3
เมื่อฉันลอง "git rev-parse svn / trunk" มันรายงานการแก้ไขที่ไม่รู้จักหรือเส้นทางที่ไม่ได้อยู่ในแผนผังการทำงาน
อดัมเนส

นี่เป็นคำตอบเดียวที่เหมาะกับฉันยกเว้นขั้นตอน git filter-branch และ drop graft ไม่จำเป็น: ฉันทำการ rebase หลังจากสร้างกราฟแล้วทำการ git svn dcommit
fc7

8

สร้างไดเรกทอรีใหม่ในพื้นที่เก็บข้อมูลการโค่นล้มสำหรับโครงการของคุณ

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

เปลี่ยนเป็นโครงการที่จัดการโดย Git ของคุณและเริ่มต้น git-svn

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

สิ่งนี้จะสร้างการคอมมิชชันเดียวเนื่องจากไดเรกทอรีโครงการ SVN ของคุณยังว่างเปล่า ตอนนี้ลดทุกอย่างในการกระทำที่git svn dcommitและคุณควรจะทำ แม้ว่ามันจะทำให้วันที่คุณมุ่งมั่นยุ่งเหยิงอย่างจริงจัง


ฉันใช้คำตอบนี้พร้อมกับคำแนะนำที่hassox.blogspot.com/2007/12/using-git-with-svn.html ฉันทำตามคำสั่งเหล่านี้แล้ว "#git branch -a" เพื่อดูชื่อลำตัว จากนั้น: # git checkout -b local-svn trunk # git ผสาน master # git svn dcommit อย่าลืมว่า. gitignore ไดเรกทอรี. svn!
cflewis

ขณะที่ฉันเพิ่งดำเนินการแบบเดียวกันฉันต้องการทำให้ชัดเจนว่าในขณะนี้ (มกราคม '09) บางครั้ง git สามารถทำการดำเนินการ rebase บน root ที่กระทำ นี่ทำให้กระบวนการง่ายกว่าบทความเก่า ๆ หลายฉบับที่ระบุให้ดูความคิดเห็นในarubything.com/2009/1/4/…
Louis Jacomet

ตัวเลือก "-s" git svn init ทำอะไรได้บ้าง ฉันไม่เห็นสิ่งนี้ใน man pages สำหรับ git svn
นาธาน

อ่านหน้าคนอีกครั้งอาจค้นหาคำว่า "-s" เพราะมันอยู่ในนั้น มันเป็นชื่อแทนสำหรับ“ --stdlayout”
Bombe

7

Git -> SVN พร้อมประวัติการส่งมอบที่สมบูรณ์

ฉันมีโครงการ Git และต้องย้ายไปที่ SVN นี่คือวิธีที่ฉันทำมันรักษาประวัติศาสตร์การกระทำทั้งหมด สิ่งเดียวที่ได้รับหายไปเป็นต้นฉบับกระทำเวลาตั้งแต่ libSVN git svn dcommitจะตั้งเวลาท้องถิ่นเมื่อเราทำ

ทำอย่างไร:

  1. มีพื้นที่เก็บข้อมูล SVN ที่เราต้องการนำเข้าข้อมูลของเราไปและโคลนด้วย git-svn:

    git svn clone https://path.to/svn/repository repo.git-svn`
    
  2. ไปที่นั่น:

    cd repo.git-svn
    
  3. เพิ่มรีโมตของที่เก็บ Git (ในตัวอย่างนี้ฉันใช้C: /Projects/repo.git ) คุณต้องการที่จะผลักดันไปยัง SVN และตั้งชื่อเก่า:

    git remote add old-git file:///C/Projects/repo.git/
    
  4. ดึงข้อมูลจากสาขาหลักจากที่เก็บ old-git ไปยังที่เก็บปัจจุบัน:

    git fetch old-git master
    
  5. ชำระเงินที่สาขาหลักของ remote-git ระยะไกลลงในสาขาใหม่ที่เรียกว่าเก่าในที่เก็บปัจจุบัน:

    git checkout -b old old-git/master`
    
  6. รีบูตเพื่อวาง HEAD ไว้ด้านบนของ old-git / master สิ่งนี้จะรักษาความมุ่งมั่นทั้งหมดของคุณ สิ่งนี้ก็คือการทำงานทั้งหมดของคุณให้เสร็จใน Git และวางไว้บนงานที่คุณเข้าถึงจาก SVN

    git rebase master
    
  7. ตอนนี้กลับไปที่สาขาหลักของคุณ:

    git checkout master
    

    และคุณจะเห็นว่าคุณมีประวัติการกระทำที่ชัดเจน นี่คือสิ่งที่คุณต้องการผลักดันไปยัง SVN

  8. ผลักดันงานของคุณไปที่ SVN:

    git svn dcommit
    

นั่นคือทั้งหมดที่ มันสะอาดมากไม่มีการแฮ็คและทุกอย่างทำงานได้อย่างสมบูรณ์แบบนอกกรอบ สนุก.


กระบวนการที่คล้ายกันมีรายละเอียดที่chani.wordpress.com/2012/01/25/…
TWiStErRob

ดูเหมือนกับ. อย่างไรก็ตามฉันพบว่าเธอค่อนข้างสับสนและฉันสั้นกว่ามาก (8 ขั้นตอนกว่า 19/23) บางทีฉันไม่ได้รับเธออย่างถูกต้อง แต่ฉันคิดว่าเธอผสมคำสั่ง svn และ git ที่กระสุนนัดที่สองของเธอ
codingdave

อาใช่ความแตกต่างก็คือกระบวนการของคุณนำเข้าคอมไพล์ไปยังรูทของ SVN repo เธอนำเข้าสู่โฟลเดอร์ย่อยนั่นเป็นเหตุผลว่าทำไมจึงgit svnจำเป็นต้องเตรียม preps
TWiStErRob

ในขั้นตอนที่ 7 ไม่ควรมีคอมไพล์เก่าหรือไม่ สำหรับฉันดูเหมือนว่าคุณกำลังทำพิธีปรมาจารย์ที่คุณไม่ได้เปลี่ยน!
อเล็กซานเดอร์

@ อเล็กซานเดอร์ที่ใช้ 'git rebase master' เราให้การผสานอย่างรวดเร็วไปข้างหน้านั่นคือการผสานแบบเส้นตรงโดยไม่มีการผสานที่มีผู้ปกครองสองคน เราต้องการประวัติเชิงเส้นตรงนี้
codingdave


3

ฉันต้องการคอมมิตพื้นที่เก็บข้อมูล Git ที่มีอยู่ของฉันไปยังพื้นที่เก็บข้อมูล SVN ที่ว่างเปล่า

นี่คือวิธีที่ฉันจัดการเพื่อทำสิ่งนี้:

$ 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

มันทำงานได้โดยไม่มีปัญหา ฉันหวังว่านี่จะช่วยให้ใครบางคน

เนื่องจากฉันต้องอนุญาตตัวเองด้วยชื่อผู้ใช้ที่แตกต่างไปยังที่เก็บ SVN (ฉันoriginใช้การรับรองความถูกต้องส่วนตัว / สาธารณะคีย์) ฉันต้องใช้--usernameคุณสมบัติ


คุณอาจต้องติดตั้งgit-svnก่อนที่จะสามารถทำได้โปรดดูstackoverflow.com/questions/527037/git-svn-not-a-git-command
flexponsive

2

หากคุณต้องการทำงานกับ Git เป็นที่เก็บหลักของคุณและเพียงแค่ต้อง "ส่งออก" การแก้ไขไปยัง SVN เป็นครั้งคราวคุณสามารถใช้เทเลอร์เพื่อซิงค์ที่เก็บ SVN สามารถคัดลอกการแก้ไขระหว่างระบบควบคุมแหล่งต่าง ๆ และจะอัปเดต SVN ด้วยการเปลี่ยนแปลงที่คุณทำใน Git

ฉันไม่ได้ลองใช้การแปลงแบบ Git-to-SVN แต่สำหรับตัวอย่าง SVN -> SVN ดูคำตอบนี้


2

อีกชุดหนึ่งที่ใช้งานได้ (มีความคิดเห็นบางส่วนในแต่ละขั้นตอน)

  1. ติดตั้งgit-svnและsubversionชุดเครื่องมือ:

    sudo apt-get install git-svn subversion
    
  2. สลับข้างใน PROJECT_FOLDER

    cd PROJECT_FOLDER
    
  3. สร้างเส้นทางโครงการบนเซิร์ฟเวอร์การโค่นล้ม (น่าเสียดายที่git-svnปลั๊กอินปัจจุบันมีข้อบกพร่องเมื่อเปรียบเทียบกับ TortoiseSVN) PROJECT_FOLDERมันไม่สามารถที่จะเก็บรหัสที่มาโดยตรงใน PROJECT_FOLDER/trunkแต่โดยปกติก็จะอัปโหลดรหัสทั้งหมดลง

    svn mkdir --parents protocol: /// path / to / repo / PROJECT_FOLDER / trunk -m "creating git repo placeholder"

นี่คือสถานที่trunkที่ส่วนท้ายของเส้นทางมีผลบังคับใช้

  1. เริ่มต้นgit-svnบริบทปลั๊กอินภายใน.gitโฟลเดอร์

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

    นี่คือสถานที่trunkที่ไม่จำเป็นที่จุดสิ้นสุดของเส้นทาง

  2. ดึงSubversionข้อมูลที่เก็บว่าง

    git svn fetch
    

    ขั้นตอนนี้ช่วยในการซิงโครไนซ์เซิร์ฟเวอร์การโค่นล้มกับgit-svnปลั๊กอิน นี่คือช่วงเวลาที่git-svnปลั๊กอินสร้างremotes/originเส้นทางและเชื่อมโยงกับtrunkโฟลเดอร์ย่อยในฝั่งเซิร์ฟเวอร์

  3. รีคอมมิต Git เก่าที่เกิดขึ้นก่อนที่git-svnปลั๊กอินจะเกี่ยวข้องในกระบวนการ (ขั้นตอนนี้เป็นทางเลือก )

    git rebase origin/trunk
    
  4. เพิ่มไฟล์ใหม่ / แก้ไขเพื่อคอมมิท (ขั้นตอนนี้เป็นเรื่องปกติสำหรับกิจกรรม Git และเป็นทางเลือก )

    git add .
    
  5. ยอมรับไฟล์ที่เพิ่งเพิ่มเข้าไปในที่เก็บ Git ท้องถิ่น (ขั้นตอนนี้เป็นทางเลือกและจะใช้ได้เฉพาะเมื่อมีการใช้ขั้นตอนที่ 7):

    git commit -m "Importing Git repository"
    
  6. การผลักดันโครงการทั้งหมดเปลี่ยนแปลงประวัติลงในเซิร์ฟเวอร์โค่นล้ม:

    git svn dcommit
    

1

คุณสามารถสร้างที่เก็บ SVN ใหม่ ส่งออกโครงการ Git ของคุณ (ดึงไฟล์. git ออก) เพิ่มไปยังที่เก็บ SVN (การเริ่มต้นพื้นที่เก็บข้อมูลด้วยสิ่งที่คุณมีใน Git) จากนั้นใช้คำแนะนำสำหรับการนำเข้าที่เก็บ SVN ในโครงการ Git ใหม่

แต่นี่จะสูญเสียประวัติ Git ก่อนหน้าของคุณ


1

หากคุณไม่ต้องใช้ SVN เฉพาะและคุณใช้ GitHub คุณสามารถใช้ตัวเชื่อมต่อ SVN ได้

ข้อมูลเพิ่มเติมอยู่ที่นี่: การทำงานร่วมกันบน GitHub ด้วยการโค่นล้ม


SVN คืออะไร ใน ( "... SVN ใด ๆ ที่เฉพาะเจาะจงและ ... " ) รุ่น SVN ลูกค้า SVN เหรอ? หรืออย่างอื่น?
Peter Mortensen

1

ฉันต้องการแบ่งปันเครื่องมือที่ยอดเยี่ยมที่ใช้ในชุมชน WordPress ชื่อ Scatter

Git ปลั๊กอิน WordPress และกระจายสติเล็กน้อย

สิ่งนี้ช่วยให้ผู้ใช้สามารถส่งที่เก็บ Git ไปยัง wordpress.org SVN ได้โดยอัตโนมัติ ในทางทฤษฎีรหัสนี้สามารถนำไปใช้กับพื้นที่เก็บข้อมูล SVN ใด ๆ


ดูเหมือนว่าลิงก์จะเสียอย่างมีประสิทธิภาพ ( "เซิร์ฟเวอร์ที่ evansolomon.me ใช้เวลานานเกินไปในการตอบสนอง" )
ปีเตอร์มอร์เทนเซ่น

1

เมื่อเร็ว ๆ นี้ฉันต้องย้ายที่เก็บ Git หลายแห่งไปยัง SVN และหลังจากลองใช้วิธีแก้ปัญหาทั้งหมดที่ฉันสามารถหาได้สิ่งที่ได้ผลสำหรับฉันคือMercurial (ใช่โดยใช้VCS ตัวที่สาม ) ด้วยการใช้คู่มือนี้ฉันได้มาพร้อมกับกระบวนการต่อไปนี้ (บน Linux แต่ความคิดพื้นฐานควรจะใช้ได้กับ Windows ด้วย)

  1. แพ็คเกจที่จำเป็น:

    $ sudo apt-get install git subversion mercurial python-subversion
    
  2. Mercurial ต้องได้รับการกำหนดค่าโดยการเพิ่มรายการต่อไปนี้ลงใน~/.hgrc:

    [extensions]
    hgext.convert=
    
  3. สร้างไดเรกทอรีการทำงานชั่วคราว (ฉันมีที่เก็บหลายแห่งที่จะย้ายข้อมูลดังนั้นฉันจึงสร้างไดเรกทอรีสำหรับรุ่น SVN และ Git เพื่อแยกพวกเขาออก):

    $ mkdir svn
    $ mkdir git
    
  4. สร้างพื้นที่เก็บข้อมูล SVN ท้องถิ่นว่างเปล่า:

    $ svnadmin create svn/project
    
  5. โคลนที่เก็บ Git ที่มีอยู่:

    $ git clone server/path/project.git git/project
    
  6. ให้ Mercurial ทำสิ่งนี้:

    $ hg convert --dest-type svn git/project svn/project
    
  7. ตอนนี้พื้นที่เก็บข้อมูล SVN ควรมีประวัติการกระทำเต็ม แต่ไม่ได้มีการประทับเวลาเดิม หากนี่ไม่ใช่ปัญหาให้ข้ามส่วนถัดไปไปยังขั้นตอนที่ 11

  8. ด้วยการทำงานเพียงเล็กน้อยวันที่และเวลาของแต่ละการกระทำสามารถเปลี่ยนแปลงได้ เนื่องจากที่เก็บของฉันมีขนาดค่อนข้างเล็กฉันจึงสามารถทำได้ด้วยตนเอง ขั้นแรกให้สร้างpre-revprop-changeเบ็ดในที่เก็บ SVN ด้วยเนื้อหาต่อไปนี้เพื่ออนุญาตให้แก้ไขคุณสมบัติที่จำเป็น:

    #!/bin/bash
    exit 0;
    

    สคริปต์นี้ต้องทำให้สามารถเรียกใช้งานได้:

    $ chmod +x svn/project/hooks/pre-revprop-change
    
  9. Mercurial สร้างสำเนาการทำงานของที่เก็บ SVN ชื่อproject -wc ดังนั้นให้สลับไปที่มันและแก้ไขเวลาที่มอบหมาย:

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

    ป้อนวันที่และเวลาที่ถูกต้อง (ให้ความสนใจกับเขตเวลา!) และบันทึก คุณควรได้รับข้อความแจ้งว่า "กำหนดค่าใหม่สำหรับคุณสมบัติ svn: date ในการแก้ไข 1"
    ตอนนี้ล้างและทำซ้ำสำหรับการแก้ไขอื่น ๆ

  10. เลือกที่จะตรวจสอบประวัติการกระทำเพื่อให้แน่ใจว่าทุกอย่างดูเรียบร้อย

    $ svn log -r 1:HEAD
    

    จากนั้นย้อนกลับไปหนึ่งระดับ:

    $ cd ..
    
  11. ดัมพ์ที่เก็บ:

    $ svnadmin dump svn/project > project.dump
    
  12. และโหลดการถ่ายโอนข้อมูลบนเซิร์ฟเวอร์การโค่นล้มของคุณ ทำ!

กระบวนการนี้อาจทำงานระหว่างที่เก็บข้อมูลระยะไกลโดยตรง แต่ฉันพบว่าการทำงานกับที่เก็บข้อมูลในเครื่องทำได้ง่ายกว่า การแก้ไขเวลาที่มอบหมายเป็นงานจำนวนมาก แต่โดยรวมแล้วกระบวนการนั้นตรงไปตรงมามากกว่าวิธีอื่น ๆ ที่ฉันพบ


1

มีสามวิธี:

  1. rebase: ตามคำตอบอื่น ๆ

  2. กระทำ id: ค้นหา svn ก่อนกระทำ ID และ git แรกกระทำ id, echo ของพวกเขาเป็น. git / ข้อมูล / grafts: echo "git_id svn_id}" > .git/info/graftsแล้วgit svn dcommit

  3. ชำระเงินทุก Git กระทำ, คัดลอกไฟล์ลงใน svn_repo, svn กระทำ

bash demo: github demo

v1.x: ใช้ rebase และกระทำ ID

v2.x: ใช้ไฟล์คัดลอกจากนั้น svn กระทำ


0

ในกรณีของฉันฉันต้องเริ่มต้นโครงการที่สะอาดจาก SVN

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

เพิ่มแหล่งที่มาโครงการของคุณทั้งหมด ...

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

0

ฉันแค่ต้องการแบ่งปันประสบการณ์ของฉันกับคำตอบที่ยอมรับได้ ฉันทำทุกขั้นตอนและทุกอย่างเรียบร้อยก่อนที่ฉันจะวิ่งในขั้นตอนสุดท้าย:

git svn dcommit

$ git svn dcommit

ใช้ค่า uninitialized $ u ในการทดแทน (s ///) ที่ /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm บรรทัด 101

การใช้ค่าเริ่มต้น $ u ในการต่อข้อมูล (.) หรือสตริงที่ /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm บรรทัด 101 refs / remotes / origin / HEAD: ' https://192.168.2.101/ svn / PROJECT_NAME 'ไม่พบใน' '

ฉันพบเธรดhttps://github.com/nirvdrum/svn2git/issues/50และในที่สุดก็แก้ปัญหาซึ่งฉันใช้ในไฟล์ต่อไปนี้ในบรรทัด 101 / usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm

ฉันแทนที่

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

กับ

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

นี่เป็นการแก้ไขปัญหาของฉัน


-1

ถ้าคุณไม่ต้องการทำทุกสิ่งสิ่งที่คุณทำใน Git ไปยังที่เก็บ SVN ถ้าคุณเพียงแค่ต้องการส่งความมุ่งมั่นที่เลือกขึ้นไปที่ท่อ? ฉันมีทางออกที่ดีกว่า

ฉันเก็บที่เก็บ Git หนึ่งแห่งในที่ซึ่งสิ่งที่ฉันทำคือดึงและผสานจาก SVN ด้วยวิธีนี้ฉันสามารถแน่ใจได้ว่าฉันรวมการเปลี่ยนแปลงทั้งหมดเหมือนกับ SVN แต่ฉันเก็บประวัติการกระทำของฉันแยกจาก SVN โดยสิ้นเชิง

จากนั้นฉันก็เก็บสำเนาทำงาน SVN ในเครื่องที่อยู่ในโฟลเดอร์แยกต่างหาก นั่นคือสิ่งที่ฉันทำกลับไปที่แผนกบริการและฉันก็ใช้โปรแกรมอรรถประโยชน์บรรทัดคำสั่ง SVN สำหรับสิ่งนั้น

เมื่อฉันพร้อมที่จะส่งมอบสถานะของที่เก็บ Git ในพื้นที่ของฉันไปยัง SVN ฉันก็เพียงแค่คัดลอกไฟล์ทั้งหมดไปยังสำเนาทำงาน SVN ในท้องถิ่นและส่งจากที่นั่นโดยใช้ SVN แทนที่จะเป็น Git

วิธีนี้ฉันไม่จำเป็นต้องทำการรีบูตใด ๆ เพราะการรีบูทเป็นเหมือนการให้บริการฟรี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.