ที่เก็บ svn ที่ฉันมิเรอร์ผ่าน git-svn ได้เปลี่ยน URL
ในวานิลลา SVN svn switch --relocate old_url_base new_url_base
คุณเพียงแค่ต้องการทำ
ฉันจะทำสิ่งนี้โดยใช้ git-svn ได้อย่างไร
เพียงแค่เปลี่ยน svn url ในไฟล์ config ก็ล้มเหลว
ที่เก็บ svn ที่ฉันมิเรอร์ผ่าน git-svn ได้เปลี่ยน URL
ในวานิลลา SVN svn switch --relocate old_url_base new_url_base
คุณเพียงแค่ต้องการทำ
ฉันจะทำสิ่งนี้โดยใช้ git-svn ได้อย่างไร
เพียงแค่เปลี่ยน svn url ในไฟล์ config ก็ล้มเหลว
คำตอบ:
สิ่งนี้จัดการกับสถานการณ์ของฉันได้ดี:
https://git.wiki.kernel.org/index.php/GitSvnSwitch
ฉันโคลนโดยใช้file://
โปรโตคอลและต้องการเปลี่ยนไปใช้http://
โปรโตคอล
การแก้ไขการurl
ตั้งค่าใน[svn-remote "svn"]
ส่วนของมันเป็นเรื่องที่น่าดึงดูดใจ.git/config
แต่ด้วยตัวมันเองสิ่งนี้ไม่ได้ผล โดยทั่วไปคุณต้องปฏิบัติตามขั้นตอนต่อไปนี้:
url
ตั้งค่าsvn-remote เป็นชื่อใหม่git svn fetch
วิ่ง สิ่งนี้ต้องดึงการแก้ไขใหม่อย่างน้อยหนึ่งครั้งจาก svn!url
ตั้งค่าsvn-remote กลับเป็น URL เดิมgit svn rebase -l
เพื่อทำการ rebase ภายในเครื่อง (ด้วยการเปลี่ยนแปลงที่มาพร้อมกับการดำเนินการดึงข้อมูลล่าสุด)url
ตั้งค่าsvn-remote กลับเป็น URL ใหม่git svn rebase
จะทำงานอีกครั้ง--rewrite-root
จิตวิญญาณของการผจญภัยที่อาจต้องการที่จะลอง
คุณสามารถดูว่าสิ่งต่อไปนี้ใช้ได้หรือไม่:
หากsvn-remote.svn.rewriteRoot
ไม่มีอยู่ในไฟล์ config ( .git/config
):
git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
หากsvn-remote.svn.rewriteUUID
ไม่มีอยู่ในไฟล์ config:
git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
สามารถหาได้จากcurrentRepositoryUUID
.git/svn/.metadata
git config svn-remote.svn.url <newRepositoryURL>
file://
เปลี่ยนเป็นsvn+ssh
); เพียงสังเกตว่า: ขั้นตอนนี้ไม่จำเป็นต้อง "ดึงข้อมูลการแก้ไขใหม่อย่างน้อยหนึ่งรายการจาก svn"; นอกจากนี้ยัง./.git/svn/.metadata
เป็นครั้งแรกหลังจากsvn rebase
ที่มี<newRepository>
เป็นreposRoot
- แต่นี้ไม่เพียงพอที่จะเอาrewrite*
กุญแจจาก.git/config
; ดังนั้นควรเก็บกุญแจเหล่านั้นไว้อย่างถาวรเท่าที่ฉันเข้าใจ
svn+ssh://
และ svn-server ของเราเพิ่งเปลี่ยนโดเมนจาก.se
เป็น.com
เพื่อล้างการตั้งชื่อภายในของเรา
น่าเสียดายที่ลิงก์ส่วนใหญ่ในคำตอบเหล่านี้ใช้งานไม่ได้ดังนั้นฉันจะทำซ้ำข้อมูลเล็กน้อยจากgit wikiเพื่อใช้อ้างอิงในอนาคต
วิธีนี้ใช้ได้ผลสำหรับฉัน:
แก้ไขsvn-remote
url
(หรือfetch
เส้นทาง) .git/config
เพื่อชี้ไปยังโดเมน / url / path ใหม่
git svn fetch
เรียกใช้คอมไพล์ สิ่งนี้ต้องดึงการแก้ไขใหม่อย่างน้อยหนึ่งครั้งจาก svn!
หากคุณพยายามgit svn rebase
ตอนนี้คุณจะได้รับข้อความแสดงข้อผิดพลาดดังนี้:
Unable to determine upstream SVN information from working tree history
ผมคิดว่านี่เป็นเพราะgit svn
สับสนโดยข้อเท็จจริงที่ว่าล่าสุดกระทำของคุณก่อนที่จะดึงข้อมูลจะมีการชี้ไปยังเส้นทางเก่าซึ่งไม่ตรงกับที่พบในgit-svn-id
.git/config
ในการแก้ไขปัญหาชั่วคราวให้เปลี่ยนsvn-remote
url
(หรือfetch
เส้นทาง) กลับไปที่โดเมน / url / path เดิม
ตอนนี้ให้รันgit svn rebase -l
อีกครั้งเพื่อทำการ rebase ภายในเครื่องพร้อมกับการเปลี่ยนแปลงที่มาพร้อมกับการดำเนินการดึงข้อมูลล่าสุด เวลานี้มันจะทำงานเพราะเห็นได้ชัดgit svn
จะไม่สับสนโดยความจริงที่ว่าของหัวใหม่ไม่ตรงกับพบว่าในgit-svn-id
.git/config
สุดท้ายเปลี่ยนsvn-remote
url
(หรือfetch
เส้นทาง) กลับไปที่โดเมน / url / path ใหม่
ณ จุดนี้git svn rebase
ควรใช้งานได้อีกครั้ง!
Git svn อาศัย svn URL เป็นอย่างมาก ทุกคอมมิตที่อิมพอร์ตจาก svn มีgit-svn-id
ที่รวม svn URL
กลยุทธ์การย้ายตำแหน่งที่ถูกต้องคือการเรียกgit-svn clone
ใช้ที่เก็บใหม่และรวมการเปลี่ยนแปลงเข้ากับการปิดใหม่นั้น สำหรับขั้นตอนโดยละเอียดเพิ่มเติมโปรดดูบทความนี้:
http://www.sanityinc.com/articles/relocating-git-svn-repositories
git filter-branch
สคริปต์นี้นำมาจากรายการบล็อกได้ผลสำหรับฉัน จัดหา URL repo เก่าและใหม่เป็นพารามิเตอร์เช่นเดียวกับsvn switch --relocate
.
โทรสคริปต์git filter-branch
เพื่อแทนที่ URL ที่โค่นล้มในgit-svn-id
ในกระทำข้อความอัปเดต.git/config
และยังปรับปรุงข้อมูลเมตาด้วยการสร้างโดยใช้git-svn
git svn rebase
แม้ว่าgit svn clone
จะเป็นโซลูชันที่มีประสิทธิภาพมากกว่า แต่filter-branch
วิธีการนี้จะทำงานได้เร็วขึ้นมากสำหรับที่เก็บข้อมูลขนาดใหญ่ (ชั่วโมงเทียบกับวัน)
#!/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
git_fast_filter
แต่เร็วกว่าgit-filter-branch
(เช่นนาทีแทนชั่วโมง) git_fast_filter
แต่ที่คล้ายกันในจิตวิญญาณคือการใช้งาน อย่างไรก็ตามสิ่งนี้ต้องใช้การเข้ารหัสอีกเล็กน้อยและไม่มีโซลูชันสำเร็จรูปที่เป็นระเบียบ ในทางตรงกันข้ามกับgit-filter-branch
นี้จะสร้างใหม่ repo จากเก่าหนึ่ง สันนิษฐานว่าmaster
ชี้ไปที่การคอมมิต SVN ล่าสุด
git_fast_filter
จาก repo Gitoriousgit_fast_filter
ขึ้นอยู่กับการสรุปสาระสำคัญนี้chmod +x
ตั้งบิตปฏิบัติการใช้ ปรับเส้นทางที่เก็บเก่าและใหม่ (เนื้อหาของสคริปต์ถูกวางไว้ด้านล่างด้วย)git init
เปลี่ยนไดเร็กทอรีการทำงานเป็น repo ใหม่นี้ดำเนินการท่อต่อไปนี้:
(cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
path/to/git_fast_filter/commit_filter.py | git-fast-import
คัดลอก.git/config
และไฟล์อื่น ๆ ที่เกี่ยวข้องในรูปแบบ.git/info
จาก repo เก่าไปยัง repo ใหม่
.git/svn
ลบให้git-svn
ตระหนักถึงการทำแผนที่จำนวนการแก้ไขใหม่
ดำเนินการ git branch refs/remotes/git-svn master
refs/remotes/git-svn
ปรึกษา.git/config
, svn-remote
ส่วนgit svn info
ปฏิบัติ หากคำสั่งนี้หยุดทำงานแสดงว่ามีบางอย่างผิดปกติ ควรสร้างการแมปหมายเลขการแก้ไขใหม่
ลบสาขาปลอมrefs/remotes/git-svn
มันจะถูกสร้างขึ้นใหม่โดยgit-svn
git svn rebase
ประสานโดยโทรด้านล่างนี้เป็นเนื้อหาของcommit_filter.py
แทนที่ค่าของIN_REPO
และOUT_REPO
ตามความเหมาะสม:
#!/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()
git svn rebase -l
วิธีแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน ฉันตัดสินใจที่จะเลือกวิธีอื่น:
old
และ SVN ใหม่เป็น git reponew
old
เข้ามาnew
cd new
git fetch ../old
git tag old FETCH_HEAD
new
ด้านบนของold
(ควรประสบความสำเร็จเนื่องจากต้นไม้ในรากnew
และปลายold
เหมือนกัน)
git checkout master
(สมมติว่าmaster
สาขานั้นชี้ไปที่หัว SVN ซึ่งจะเป็นกรณีที่มีการโคลนแบบสะอาดหรือไม่ก็ให้คำสั่งก่อนที่คุณจะเริ่ม)git rebase --root --onto old
new
เพื่อบัญชีสำหรับ rebase
git update-ref --no-deref refs/remotes/git-svn master
(ปรับการอ้างอิงระยะไกลขึ้นอยู่กับว่าคุณโคลนอย่างไรเช่นอาจเป็นได้refs/remotes/svn/trunk
)rm -r .git/svn
git svn info
จากคำตอบอื่น ๆ บางส่วนของคำถามนี้ฉันได้สร้างสคริปต์ Ruby ที่จัดการการย้าย git-svn สามารถค้นหาได้ที่https://gist.github.com/henderea/6e779b66be3580c9a584 https://gist.github.com/henderea/6e779b66be3580c9a584
มันจัดการการย้ายตำแหน่งโดยไม่ต้องตรวจสอบสำเนาอื่นและยังจัดการกรณีที่มีการเปลี่ยนแปลงที่ไม่ได้ผลักดันในหนึ่งสาขาขึ้นไป (เนื่องจากจะทำลายตรรกะปกติ) มันใช้ข้อมูลจากคำตอบ git filter-branch (สำหรับตรรกะหลัก) และคำตอบเกี่ยวกับการคัดลอกสาขาจากอินสแตนซ์ของ repo ไปยังอีกอินสแตนซ์ (สำหรับการคัดลอกสาขาที่มีการเปลี่ยนแปลงที่ไม่ได้ผลักดัน)
ฉันใช้สิ่งนี้เพื่อย้าย repos git-svn จำนวนมากที่ฉันมีสำหรับการทำงานและสคริปต์เวอร์ชันนี้ (ฉันผ่านการทำซ้ำมาแล้วนับไม่ถ้วน) ดูเหมือนจะใช้ได้กับฉัน มันไม่ได้เร็วมาก แต่ดูเหมือนว่าจะจัดการกับทุกกรณีที่ฉันพบเจอและส่งผลให้มีการย้ายที่ตั้งใหม่ทั้งหมด
สคริปต์ให้คุณมีตัวเลือกในการสร้างสำเนาของ repo ก่อนทำการเปลี่ยนแปลงใด ๆ ดังนั้นคุณสามารถใช้ตัวเลือกนี้เพื่อสร้างข้อมูลสำรองได้ จำเป็นต้องสร้างสำเนาหากคุณไม่ได้ผลักดันการเปลี่ยนแปลงในสาขาใด ๆ
สคริปต์ไม่ใช้อัญมณีหรือไลบรารีอื่น ๆ ที่ไม่รวมอยู่ในการติดตั้ง MRI Ruby ปกติ ใช้ไลบรารี readline และ fileutils ที่รวมอยู่ใน MRI
หวังว่าสคริปต์ของฉันจะเป็นประโยชน์กับคนอื่น อย่าลังเลที่จะเปลี่ยนแปลงสคริปต์
หมายเหตุ:ฉันได้ทดสอบสคริปต์นี้ด้วย git 2.3.0 / 2.3.1 และ Ruby 2.2.0 บน OS X 10.10 Yosemite เท่านั้น (เนื่องจากเป็นสภาพแวดล้อมที่ฉันใช้) แต่ฉันคาดหวังว่ามันจะทำงานบนสภาพแวดล้อมอื่น ๆ ด้วย ไม่มีการรับประกันเกี่ยวกับ Windows แม้ว่า