ฉันจะบอก git-svn เกี่ยวกับสาขาระยะไกลที่สร้างขึ้นหลังจากดึง repo ได้อย่างไร


193

ฉันใช้git-svnเพื่อทำงานกับพื้นที่เก็บข้อมูลส่วนกลางของ บริษัท ของฉัน เราเพิ่งสร้างสาขาฟีเจอร์ใหม่ใน repo ส่วนกลาง

ฉันจะบอก Git เกี่ยวกับมันได้อย่างไร เมื่อฉันวิ่งgit branch -rฉันจะเห็นเฉพาะกิ่งไม้ที่มีอยู่เมื่อฉันวิ่งแข่งfetchกับ Subversion repo เพื่อเริ่มต้น Git repo ของฉัน?


คำตอบจากที่นี่: stackoverflow.com/questions/13376917/…อาจมีประโยชน์เช่นกัน
Tomasz Gandor

คำตอบ:


294

คุณสามารถเพิ่มสาขาระยะไกลด้วยตนเอง

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch

3
เพียงแค่เพิ่มลิงค์นี้ไปยังเอกสารเพื่อเป็นข้อมูลอ้างอิงkernel.org/pub/software/scm/git/docs/git-svn.html
slf

1
จาก. git / config มันค่อนข้างง่ายที่จะเข้าใจว่าสามารถกำหนดค่า remote remote จากที่เก็บเดี่ยว / หลายที่
Mikael Lepistö

6
ถ้าฉันสามารถโหวตได้เช่นนี้แปดครั้งฉันก็จะทำ ในที่สุดวิธีการเพิ่มสาขา svn ที่เพิ่มในตำแหน่งที่ไม่เป็นมาตรฐาน!
Tim Keating

7
ฉันfatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.ไปถึงขั้นตอนการชำระเงินคอมไพล์
phpguru

17
@phpguru ลองลบแฟล็กตัวเลือก -t เพื่อให้กลายเป็น 'เช็คเอาต์ git -b newbranch ท้องถิ่น' อย่าลืมใส่คำนำหน้าของรีโมตไปยัง newbranch (เช่นต้นกำเนิด / newbranch)
mj1531

96

หากคุณต้องการติดตามทุกสาขา svn ระยะไกลวิธีการแก้ปัญหาก็ง่ายเหมือน:

git svn fetch

สิ่งนี้จะดึงกิ่งก้านสาขาทั้งหมดที่ยังไม่ได้ดึงออกมา

เคล็ดลับพิเศษ: หากคุณเช็คเอาต์เฉพาะลำต้นในตอนแรกและหลังจากนั้นคุณต้องการติดตามสาขาทั้งหมดจากนั้นแก้ไข.git/configเพื่อให้มีลักษณะเช่นนี้และเรียกใช้อีกครั้งgit svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

จุดที่สำคัญคือurlควรชี้ไปที่รากพื้นที่เก็บข้อมูลและเส้นทางที่กำหนดไว้ในfetchและควรจะเป็นเมื่อเทียบกับbranchesurl

หากคุณต้องการดึงเฉพาะสาขาที่เฉพาะเจาะจงแทนทั้งหมดมีตัวอย่างที่ดีในgit svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

ด้วยรุ่นที่เก่ากว่าgit-svnเมื่อคุณระบุสาขาเช่นนี้คุณอาจไม่สามารถรับสาขาใหม่git svn fetchได้ วิธีแก้ปัญหาหนึ่งอย่างคือเพิ่มfetchบรรทัดเพิ่มเติมเช่นนี้

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

วิธีแก้ปัญหาอื่นโดย @AndyEstes: แก้ไข.git/svn/.metadataและเปลี่ยนค่าของbranches-maxRevหรือtags-maxRevเป็นการแก้ไขก่อนที่จะสร้างสาขาหรือแท็กที่ระบุใหม่ เมื่อคุณทำสิ่งนี้เสร็จแล้วให้วิ่งgit svn fetchเพื่อติดตาม svn remote branch


1
หากคุณดึงการแก้ไขที่ดำเนินการ svn branching แล้วก่อนที่คุณจะตั้งค่าเหล่านั้นคุณอาจต้องการทำการรีเซ็ต git svn
kcm1700

3
การแก้ไข.git/svn/.metadataมีประโยชน์มาก! ฉันกำลังเพิ่มสาขาพิเศษในของฉัน.git/configซึ่งgit svn fetchไม่ได้รับ - เพราะหมายเลขการแก้ไขข้อมูลเมตาคือ "ไกลไปข้างหน้า" ในกรณีเดียวจะทำการดึงข้อมูลการส่งครั้งล่าสุดจากสาขา ฉันเองได้กำจัดของสาขาความผิดพลาด (เปลี่ยนชื่อ.git/svn/refs/remotes/svn/qa/XYZที่จะ.git/svn/refs/remotes/svn/qa/XYZ~ลดลงในการดำรงอยู่ของ.git/packed-refsฯลฯ ) ... เลือกเป็น "ก่อนหน้านี้" จำนวนการแก้ไขสำหรับข้อมูลเมตา ... วิ่งgit svn fetchจนได้รับประวัติ w / ถูกต้องกราฟที่เกี่ยวโยงกัน
starlocke

8
สิ่งนี้ควรเป็นคำตอบที่ยอมรับ! @janos คุณเพิ่งช่วยฉันชั่วโมงปวดหัว! ถ้าคุณเคยไปอินเดียฉันจะพาคุณออกไปดื่มเบียร์!
Roopesh Shenoy

1
หรือ: git svn fetch --all.
kenorb

1
คำตอบนี้น่าทึ่งเพราะมันตอบคำถามได้ประมาณ 7 คำถามฉันไม่สามารถหาคำตอบได้และมันทำได้โดยไม่ต้องเขียนเรื่อง 6 หน้า
Droj

53

ดูเหมือนว่าฉันเพิ่งจะต้องgit svn fetch; อย่างใดฉันก็มั่นใจว่าจะดึง repo ทั้งหมดแทนที่จะเพียงแค่การเปลี่ยนแปลง


7
@mitjak ทำไมมันไม่ได้คำตอบที่ถูกต้องถ้ามันเป็นทางออก? ฉันไม่เข้าใจความละเอียดอ่อนของคำตอบ
rholmes

'a solution' อาจไม่ใช่ 'the solution'
slf

1
@rholmes: ฉันค่อนข้างแน่ใจว่า mitjak หมายความว่านั่นเป็นวิธีแก้ปัญหาของคุณ แต่ไม่ใช่คำตอบสำหรับคำถามที่คุณถาม (เพราะคุณถามคำถามผิดเมื่อคุณตีความปัญหาผิดในขณะนั้น)
Mike Nelson

สิ่งนี้จะทำงานเมื่อมีสาขาอยู่ในขณะที่คุณทำการโคลน svn repository เป็น git มันจะไม่ทำงานหากสาขาในที่เก็บ svn ถูกสร้างขึ้นในภายหลัง
Petr Gladkikh

3
มันทำงานได้ดีเมื่อสาขาถูกสร้างขึ้นหลังจากโคลนฉันทำมันตลอดเวลา
Tim Gautier

15

บางทีฉันอาจจะสับสนมันขึ้นมา แต่อย่างใดผมทำตามคำแนะนำในคำตอบ vjangus' และมันเกือบจะทำงาน ปัญหาเดียวคือนิวบรันช์ไม่ปรากฏว่าแยกจากลำต้น ใน gitk มันเป็น "ลอย" ทั้งหมดด้วยตัวมันเอง มันไม่มีบรรพบุรุษร่วมกับลำต้น

วิธีแก้ปัญหานี้คือ:

  1. ค้นหา SHA1 ของการกระทำครั้งสุดท้ายที่เกิดขึ้นบนลำตัวก่อนที่จะสร้างสาขา
  2. ค้นหา SHA1 ของการส่งครั้งแรกในสาขาใหม่ (ข้อความน่าจะเป็น "สร้างสาขาใหม่คัดลอกมาจาก trunk @ 12345" หรือบางอย่าง)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- ไม่ควรมีเอาต์พุต หากมีการส่งออกคุณอาจเลือกกระทำผิด
  4. git checkout local-newbranchgit rebase <sha1 from step 1>แล้วก็ สิ่งนี้จะรีบาวน์local-newbranchบนต้นไม้ใหม่ แต่remotes/newbranchจะยังคงถูกตัดการเชื่อมต่อ
  5. ไปที่ไฟล์.git/refs/remotes/newbranchและแก้ไขเพื่อให้มี SHA1 เต็มรูปแบบของการส่งข้อมูลใหม่ (ในการ rebased newbranch) ที่สอดคล้องกับการยอมรับเก่าที่มีอยู่ในปัจจุบัน (หรืออาจจะใช้git-update-ref refs/remotes/newbranch <new-SHA>ขอบคุณ inger)
  6. ครั้งต่อไปที่คุณgit svn dcommitไปnewbranchคุณจะได้รับข้อความมากมายเกี่ยวกับการอัพเดทบันทึก นี่เป็นเรื่องปกติที่ฉันคิดว่า

ฉันแนะนำให้gitk --allเปิดตลอดเวลาและทำให้สดชื่นบ่อยครั้งเพื่อติดตามสิ่งที่คุณทำ ฉันยังใหม่กับ git และ git svn ดังนั้นโปรดแนะนำการปรับปรุงวิธีนี้


2
ขอบคุณเสียงนี้มีประโยชน์ เกี่ยวกับ 5. อาจเป็น 'git-update-ref refs / remotes / newbranch <new-SHA>' เป็นตัวเลือกที่ปลอดภัยกว่า
Inger

ลองใช้วิธีของ vjangus อีกครั้งและมันก็ทำงานได้อย่างสมบูรณ์ ฉันจะออกจากที่นี่อยู่แล้วตั้งแต่มันอาจจะมีคุณค่าให้กับใครสักคน ...
MatrixFrog

1
โซลูชัน vjangus จะสร้างการเชื่อมต่อของสาขาใหม่จากลำต้นเสมอ ฉันคิดว่านี่เป็นเพราะวิธีการที่ SVN ไม่มีเบาะแสเกี่ยวกับวิธีการคัดลอกเนื้อหาจริง
bogdan.mustiata

ประสบการณ์ของฉันกับ repo git-svn ขนาดใหญ่คือสาขา svn ถูกสร้างขึ้นใน git ที่แยกออกจากลำตัวเสมอ ควรจะมีวิธีการเชื่อมต่อพวกเขา แต่ฉันไม่ได้ใช้เวลาในการคิดออก AFAIK คุณไม่สามารถรีบูตสาขา git ที่เชื่อมต่อกับสาขา svn ได้เนื่องจากจะทำให้ตรรกะ dcommit เสียหาย เราเพิ่งเรียนรู้ที่จะอยู่กับมัน
Spencer

7

การทำให้คำตอบของ vjangus ง่ายขึ้น:

หากคุณใช้เลย์เอาต์มาตรฐานใน SVN และทำ svn init ตามปกติแล้ว git-svn จะทำสิ่งต่างๆให้คุณ แค่:

  1. ค้นหาการแก้ไขสำเนาสาขาใน SVN
  2. ดึงข้อมูลการแก้ไขนั้นด้วย git-svn
  3. สร้างการติดตามสาขาในท้องถิ่นระยะไกลใหม่

ตัวอย่าง. SVN URL svn+ssh://gil@svn.myplace.com/repoคือ สาขา SVN newbranchฉันกำลังมองหาคือ สาขาคอมไพล์ท้องถิ่น (ติดตามระยะไกลnewbranch) git-newbranchจะ

ขั้นตอนที่ 1: ค้นหาการแก้ไขสำเนาสาขา

    # svn log - หยุดบนสำเนา svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch | หาง -4
    r7802 | บางคน | 2014-03-21 18:54:58 +0000 (ศุกร์, 21 มีนาคม 2014) | 1 บรรทัด

    การแตกแขนง HEAD สู่ newbranch
    -------------------------------------------------- ----------------------

ดังนั้นจุดที่สาขาใน SVN คือการแก้ไข 7802

ขั้นตอนที่ 2: ดึงข้อมูลการแก้ไข

    # git svn fetch -r 7802
    พบจุดสาขาที่เป็นไปได้: svn + ssh: //gil@svn.myplace.com/repo/trunk => svn + ssh: //gil@svn.myplace.com/repo/branches/newbranch, 7801
    พบสาขาแม่: (อ้างอิง / รีโมท / ลำตัว) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    ติดตามผู้ปกครองด้วย do_switch
    ประสบความสำเร็จในการติดตามผู้ปกครอง
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (อ้างอิง / รีโมท / newbranch)

git-svn ทำงานทั้งหมดและตอนนี้รู้เกี่ยวกับรีโมท:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / รีโมท / newbranch

ขั้นตอนที่ 3: สร้างสาขาท้องถิ่นใหม่ของคุณติดตามรีโมต:

    # git checkout -b git-newbranch -t newbranch
    กำลังตรวจสอบไฟล์: 100% (413/413) เสร็จแล้ว
    สาขา git-newbranch ตั้งค่าเพื่อติดตามอ้างอิง refs / รีโมท / newbranch ท้องถิ่น
    เปลี่ยนเป็นสาขาใหม่ 'git-newbranch'

ในที่สุดการทำตามนี้ทำให้ฉันเข้าใจ ( show-refล้ำค่า)! สำหรับทุกคนที่ติดอยู่กับการอ้างอิงสาขาระยะไกลอย่างไม่ถูกต้องคุณสามารถลบพวกเขา (ฉันต้องทำgit branch -d newbranchแล้วบังคับให้ลบผู้อ้างอิงใน.git/svn/refs/remotes/newbranch) จากนั้นเริ่มใหม่ในขั้นตอนที่ 2 (ด้านบน)
tutuDajuju

5

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

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

กล่าวคือ

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

และคุณเพียงต้องการเลือกสาขาที่จะรวมในที่เก็บ git ของคุณ

คุณสามารถเริ่มต้นพื้นที่เก็บข้อมูลของคุณด้วยลำต้นเท่านั้นโดยไม่มีสาขาเพิ่มเติม:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

หลังจากนั้นคุณจะเห็นการกำหนดค่าต่อไปนี้:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

เมื่อใดก็ตามที่คุณต้องการดึงสาขาใหม่จาก MyRepo คุณสามารถเพิ่มรายการดึงข้อมูลใหม่เพื่อกำหนดค่าโดย:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

หรือคุณอาจแก้ไขการกำหนดค่าเดียวกันใน. git / config

หากต้องการดึงสาขาใหม่หลังจากเพิ่มลงในการกำหนดค่าให้เรียกใช้:

git svn fetch -r 10000:HEAD

[แก้ไข]บางครั้งดูเหมือนว่าจำเป็นต้องเรียกใช้การดึงข้อมูลด้วยพารามิเตอร์ --all เพื่อดึงข้อมูลสาขาที่เพิ่มใหม่:

git svn fetch --all -r 10000:HEAD

4

แทนที่จะจัดการกับนิสัยใจคอ Git-SVN คุณอาจลองSubGit

หนึ่งมีการติดตั้ง SubGit ลงในพื้นที่เก็บข้อมูลการโค่นล้ม หลังจากนั้นสามารถใช้เวิร์กโฟลว์ git มาตรฐานแทนการใช้คำสั่ง git-svn พิเศษ:

  1. ผลักดันพันธะใหม่:

    Git-SVN:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. กำลังเรียกการเปลี่ยนแปลงที่เข้ามา

    Git-SVN:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. การสร้างสาขาใหม่:

    Git-SVN:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

ดูเอกสารประกอบ SubGitสำหรับรายละเอียดเพิ่มเติม


1
SubGit มีข้อเสียที่จะสร้างที่เก็บสองแห่ง - หนึ่ง svn และหนึ่งที่เก็บ "เงา" git ที่เก็บ นี่อาจเป็นปัญหาสำหรับที่เก็บข้อมูล SVN ขนาดใหญ่ ...
Udo

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

1
@Udo - บริษัท ใด ๆ ที่ไม่ต้องการซื้อเซิร์ฟเวอร์พื้นที่เก็บข้อมูลฮาร์ดไดรฟ์มีลำดับความสำคัญเกิดความสับสน แต่สถานที่ส่วนใหญ่ที่มีแหล่งเก็บข้อมูลขนาดใหญ่นั้นให้ความสำคัญกับพื้นที่เก็บข้อมูลอย่างจริงจังและความต้องการพื้นที่เก็บข้อมูลสำหรับพื้นที่เก็บข้อมูลโดยทั่วไปนั้นไม่ได้เป็นปัญหาที่สำคัญแม้แต่กับ บริษัท ที่มีประวัติยาวนานหลายทศวรรษ มันเป็นรูปแบบที่เป็นรูปธรรมที่สุดของ บริษัท ในด้านทรัพย์สินทางปัญญาหลักและพื้นที่ดิสก์มีราคาไม่แพง มันอาจก่อให้เกิดความจำเป็นในการอัพเกรดตัวควบคุม RAID แต่ถึงกระนั้นก็ยังได้รับผลผลิต ...
Bob Kerns

@ Bob Kerns - ประเด็นคือ "ขนาดฉลาด" SVN และ Git และเข้ากันไม่ได้ ไม่ใช่คำถามของการจัดเก็บดิสก์หรือดังนั้น แต่คุณสามารถทำงานกับพื้นที่เก็บข้อมูล SVN ขนาดใหญ่ได้เนื่องจากโดยปกติคุณจะต้องชำระเงินไม่กี่ไฟล์ / โครงการ แต่คุณไม่สามารถโคลนพื้นที่เก็บข้อมูล Git ขนาดใหญ่ - มันไม่ได้สนุกอย่างน้อย ;-) โดย "ใหญ่" ฉันหมายถึงกิ๊กหลาย ๆ
Udo

2

เพื่อเพิ่มคำตอบของ vjangus ซึ่งช่วยฉันฉันก็พบว่ามีประโยชน์ในการเพิ่มการใช้ git grafts เพื่อผูกกิ่งกับลำต้นที่จุดที่เหมาะสม - อนุญาตให้ git ดูประวัติและทำการผสานอย่างถูกต้อง

นี่เป็นกรณีของการเพิ่มบรรทัดลง.git/info/graftsในแฮช:

<initial branch commit> <parent commit in trunk>

เช่น.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

ขอมอบเครดิตให้กับhttp://evan-tech.livejournal.com/255341.html

(ฉันจะเพิ่มนี่เป็นความคิดเห็น แต่ฉันมีชื่อเสียงไม่เพียงพอ)


0

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

นี่คือสิ่งที่ฉันทำ:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

หลังจากนั้นคุณสามารถเปลี่ยนเป็นสาขาระยะไกล:

git checkout --track -b branch_name branch_name

จากนั้นคุณจะเปลี่ยนเป็นสาขาของคุณโดยอัตโนมัติ

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