git-svn: อะไรเทียบเท่ากับ "svn switch --relocate`?


89

ที่เก็บ svn ที่ฉันมิเรอร์ผ่าน git-svn ได้เปลี่ยน URL

ในวานิลลา SVN svn switch --relocate old_url_base new_url_baseคุณเพียงแค่ต้องการทำ

ฉันจะทำสิ่งนี้โดยใช้ git-svn ได้อย่างไร

เพียงแค่เปลี่ยน svn url ในไฟล์ config ก็ล้มเหลว


คุณควรลองและยอมรับคำตอบนี้: stackoverflow.com/a/4061493/1221661
Fritz

มากที่สุดถึงคำตอบวันที่: stackoverflow.com/a/40523789/537554 คำถามเดียวกัน แต่ถามจากมุมมองของผู้ใช้ Git
ryenus

คำตอบ:


61

สิ่งนี้จัดการกับสถานการณ์ของฉันได้ดี:

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

ฉันโคลนโดยใช้file://โปรโตคอลและต้องการเปลี่ยนไปใช้http://โปรโตคอล

การแก้ไขการurlตั้งค่าใน[svn-remote "svn"]ส่วนของมันเป็นเรื่องที่น่าดึงดูดใจ.git/configแต่ด้วยตัวมันเองสิ่งนี้ไม่ได้ผล โดยทั่วไปคุณต้องปฏิบัติตามขั้นตอนต่อไปนี้:

  1. เปลี่ยนการurlตั้งค่าsvn-remote เป็นชื่อใหม่
  2. git svn fetchวิ่ง สิ่งนี้ต้องดึงการแก้ไขใหม่อย่างน้อยหนึ่งครั้งจาก svn!
  3. เปลี่ยนการurlตั้งค่าsvn-remote กลับเป็น URL เดิม
  4. เรียกใช้git svn rebase -lเพื่อทำการ rebase ภายในเครื่อง (ด้วยการเปลี่ยนแปลงที่มาพร้อมกับการดำเนินการดึงข้อมูลล่าสุด)
  5. เปลี่ยนการurlตั้งค่าsvn-remote กลับเป็น URL ใหม่
  6. ตอนนี้ git svn rebaseจะทำงานอีกครั้ง

--rewrite-rootจิตวิญญาณของการผจญภัยที่อาจต้องการที่จะลอง


2
เพื่อความเป็นธรรมนี่ล้มเหลวสำหรับฉันจริงๆและฉันก็โคลน repo อีกครั้ง ยากที่จะรับคอมไพล์เพื่อจัดการเมื่อไดเร็กทอรี svn ถูกเปลี่ยนชื่อ
Gregg Lind

ฉันต้องการยอมรับข้อเขียนที่มีรายละเอียดมากกว่านี้ แต่ก็พอใช้ฉันจะยอมรับจนกว่าจะมีคำตอบใหม่
kch

2
นี่คือคำอธิบายอื่นของขั้นตอนนั้น: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray

ลิงก์ที่ให้ไว้ในคำตอบที่ได้รับการยอมรับนั้นล้าสมัยและลิงก์ใหม่ ณ ตอนนี้คือgit.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.htmlฉันติดตาม "General Case" และมันง่ายและจริง ทำงานได้ดี
TcMaster

2
@TcMaster: ได้ผลสำหรับฉันเช่นกัน ... แต่นั่นเป็นเหตุผลที่คำตอบไม่ควรมีเพียงลิงก์เท่านั้นพวกเขาล้าสมัยและไร้ประโยชน์ ... ฉันจะเพิ่มคำตอบวิกิชุมชน
UncleZeiv

38

คุณสามารถดูว่าสิ่งต่อไปนี้ใช้ได้หรือไม่:

  1. หากsvn-remote.svn.rewriteRootไม่มีอยู่ในไฟล์ config ( .git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. หากsvn-remote.svn.rewriteUUIDไม่มีอยู่ในไฟล์ config:

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

    สามารถหาได้จากcurrentRepositoryUUID.git/svn/.metadata

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


ยอดเยี่ยม - ขอบคุณมันใช้งานได้ดีสำหรับฉัน (โคลนผ่านfile://เปลี่ยนเป็นsvn+ssh); เพียงสังเกตว่า: ขั้นตอนนี้ไม่จำเป็นต้อง "ดึงข้อมูลการแก้ไขใหม่อย่างน้อยหนึ่งรายการจาก svn"; นอกจากนี้ยัง./.git/svn/.metadataเป็นครั้งแรกหลังจากsvn rebaseที่มี<newRepository>เป็นreposRoot- แต่นี้ไม่เพียงพอที่จะเอาrewrite*กุญแจจาก.git/config; ดังนั้นควรเก็บกุญแจเหล่านั้นไว้อย่างถาวรเท่าที่ฉันเข้าใจ
sdaau

1
มันใช้ได้ผลกับฉันเช่นกันเหมือนเสน่ห์ OP ควรลองอันนี้และรับเป็นคำตอบที่ถูกต้อง
Rafareino

สมบูรณ์แบบ. ฉันมีโปรเจ็กต์ใหญ่ที่มีการกระทำหลายพันครั้งในประวัติศาสตร์ดังนั้นการโคลนใหม่จะทำลายประวัติศาสตร์ (หรือใช้เวลานานมากในการชำระเงิน) ฉันใช้svn+ssh://และ svn-server ของเราเพิ่งเปลี่ยนโดเมนจาก.seเป็น.comเพื่อล้างการตั้งชื่อภายในของเรา
UlfR

ทำงานให้ฉัน มี repo อายุ 2 ปีที่มีการกระทำ 1,000 ครั้ง repo ถูกย้ายไปยังโฮสต์ใหม่ดังนั้นสิ่งนี้จึงหลีกเลี่ยงการโคลน svn แบบเต็ม (หวั่น)
David Victor

21

น่าเสียดายที่ลิงก์ส่วนใหญ่ในคำตอบเหล่านี้ใช้งานไม่ได้ดังนั้นฉันจะทำซ้ำข้อมูลเล็กน้อยจาก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ควรใช้งานได้อีกครั้ง!

ข้อมูลเดิมที่ถูกพบที่นี่


3

Git svn อาศัย svn URL เป็นอย่างมาก ทุกคอมมิตที่อิมพอร์ตจาก svn มีgit-svn-idที่รวม svn URL

กลยุทธ์การย้ายตำแหน่งที่ถูกต้องคือการเรียกgit-svn cloneใช้ที่เก็บใหม่และรวมการเปลี่ยนแปลงเข้ากับการปิดใหม่นั้น สำหรับขั้นตอนโดยละเอียดเพิ่มเติมโปรดดูบทความนี้:

http://www.sanityinc.com/articles/relocating-git-svn-repositories


2

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

1

git_fast_filter

แต่เร็วกว่าgit-filter-branch(เช่นนาทีแทนชั่วโมง) git_fast_filterแต่ที่คล้ายกันในจิตวิญญาณคือการใช้งาน อย่างไรก็ตามสิ่งนี้ต้องใช้การเข้ารหัสอีกเล็กน้อยและไม่มีโซลูชันสำเร็จรูปที่เป็นระเบียบ ในทางตรงกันข้ามกับgit-filter-branchนี้จะสร้างใหม่ repo จากเก่าหนึ่ง สันนิษฐานว่าmasterชี้ไปที่การคอมมิต SVN ล่าสุด

  1. โคลนgit_fast_filterจาก repo Gitorious
  2. สร้างสคริปต์ Python ในไดเรกทอรีเดียวกันที่คุณโคลนgit_fast_filterขึ้นอยู่กับการสรุปสาระสำคัญนี้chmod +xตั้งบิตปฏิบัติการใช้ ปรับเส้นทางที่เก็บเก่าและใหม่ (เนื้อหาของสคริปต์ถูกวางไว้ด้านล่างด้วย)
  3. เริ่มต้นที่เก็บเป้าหมายใหม่โดยใช้git initเปลี่ยนไดเร็กทอรีการทำงานเป็น repo ใหม่นี้
  4. ดำเนินการท่อต่อไปนี้:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. คัดลอก.git/configและไฟล์อื่น ๆ ที่เกี่ยวข้องในรูปแบบ.git/infoจาก repo เก่าไปยัง repo ใหม่

  6. .git/svnลบ
  7. ให้git-svnตระหนักถึงการทำแผนที่จำนวนการแก้ไขใหม่

    1. ดำเนินการ git branch refs/remotes/git-svn master

      • รีโมทคอมไพล์-SVN ของคุณอาจจะเรียกได้ว่าแตกต่างจากการrefs/remotes/git-svnปรึกษา.git/config, svn-remoteส่วน
    2. git svn infoปฏิบัติ หากคำสั่งนี้หยุดทำงานแสดงว่ามีบางอย่างผิดปกติ ควรสร้างการแมปหมายเลขการแก้ไขใหม่

    3. ลบสาขาปลอมrefs/remotes/git-svnมันจะถูกสร้างขึ้นใหม่โดยgit-svn

  8. 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()

0

git svn rebase -lวิธีแก้ปัญหาข้างต้นไม่ได้ผลสำหรับฉัน ฉันตัดสินใจที่จะเลือกวิธีอื่น:

  1. โคลน SVN repo เก่าลงใน git repo oldและ SVN ใหม่เป็น git reponew
  2. ดึงoldเข้ามาnew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newด้านบนของold(ควรประสบความสำเร็จเนื่องจากต้นไม้ในรากnewและปลายoldเหมือนกัน)
    • git checkout master(สมมติว่าmasterสาขานั้นชี้ไปที่หัว SVN ซึ่งจะเป็นกรณีที่มีการโคลนแบบสะอาดหรือไม่ก็ให้คำสั่งก่อนที่คุณจะเริ่ม)
    • git rebase --root --onto old
  4. สร้างข้อมูลเมตา git-svn ของ newเพื่อบัญชีสำหรับ rebase
    • git update-ref --no-deref refs/remotes/git-svn master(ปรับการอ้างอิงระยะไกลขึ้นอยู่กับว่าคุณโคลนอย่างไรเช่นอาจเป็นได้refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info

1. คุณเริ่มต้นด้วยการโคลนใหม่ของสถานที่ตั้งใหม่หรือไม่? ถ้าใช่ทำไมคุณถึงไม่ทำในจุดนั้น? 2. หากคุณสร้างฐานข้อมูลใหม่ในรายการเก่าการกระทำเก่าของคุณทั้งหมดกล่าวถึง URL เก่าในรายการบันทึกการกระทำ svn-id หรือไม่ 3. มีเอกสารใดบ้างที่บันทึกเพื่อลบ. git / svn? (3b: คำสั่งใดที่กำลังสร้างข้อมูลเมตา git-svn ใหม่ข้อมูล git svn)
Micha Wiedenmann

0

จากคำตอบอื่น ๆ บางส่วนของคำถามนี้ฉันได้สร้างสคริปต์ 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 แม้ว่า

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