ใช้การนำเข้าแพ็คเกจแบบแยกใน Go


105

สมมติว่าคุณมีพื้นที่เก็บข้อมูลที่และคุณแยกมันgithub.com/someone/repo github.com/you/repoคุณต้องการใช้ทางแยกของคุณแทน repo หลักดังนั้นคุณจึงทำไฟล์

go get github.com/you/repo

ตอนนี้เส้นทางการนำเข้าทั้งหมดใน repo นี้จะ "เสีย" ซึ่งหมายความว่าหากมีหลายแพ็กเกจในที่เก็บที่อ้างอิงถึงกันผ่าน URL ที่สมบูรณ์พวกเขาจะอ้างอิงแหล่งที่มาไม่ใช่ทางแยก

มีวิธีที่ดีกว่าในการโคลนด้วยตนเองในเส้นทางที่ถูกต้องหรือไม่?

git clone git@github.com:you/repo.git $GOPATH/src/github.com/someone/repo

1
ไม่มีเส้นทางนำเข้าในส้อมใหม่จะเสียซึ่งไม่ได้เสียแล้วก่อนที่ฟอร์ก
zzzz

11
ขอโทษที่ทำให้คุณผิดหวัง แต่นั่นไม่เป็นความจริง หากมีการอ้างอิงแพ็กเกจย่อยในการนำเข้าผ่านทาง URL ที่สมบูรณ์การนำเข้านี้จะเสียในทางแยก (หรืออย่างน้อยก็อ้างอิงแพ็กเกจที่ไม่ถูกต้อง)
Erik Aigner

2
เช่นgoamz . มีการอ้างอิงภายในทั่วทุกที่
Erik Aigner

1
ดูที่ec2แพคเกจ - มีlaunchpad.net/goamz/awsการนำเข้า ทั้งสองแพ็กเกจawsและec2แพ็กเกจอยู่ในที่เก็บ SAME ดังนั้นเมื่อถูกแยกจะไม่อ้างอิงแพ็กเกจที่ถูกต้อง (แพ็กเกจในส้อม)
Erik Aigner

1
ส้อมจะอ้างอิงแพ็คเกจเดียวกันกับแหล่งที่มาของส้อม มีอะไรไม่ถูกต้อง ส้อมจะรวบรวมมันจะสร้างมันจะทำสิ่งเดียวกันกับก่อนหน้านี้ คำจำกัดความของ 'แพ็คเกจที่ไม่ถูกต้อง' คืออะไร? โปรดทราบว่าภาษา Go เช่นเดียวกับระบบสร้างไม่มีการรับรู้ถึงที่เก็บมีเพียงแพ็กเกจ
zzzz

คำตอบ:


85

เพื่อจัดการคำขอดึง

  • แยกที่เก็บgithub.com/someone/repoไปที่github.com/you/repo
  • ดาวน์โหลดรหัสเดิม: go get github.com/someone/repo
  • อยู่ที่นั่น: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • เปิดใช้งานการอัปโหลดไปยังส้อมของคุณ: git remote add myfork https://github.com/you/repo.git
  • อัปโหลดการเปลี่ยนแปลงของคุณไปยัง repo ของคุณ: git push myfork

http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html

เพื่อใช้แพ็คเกจในโครงการของคุณ

https://github.com/golang/go/wiki/PackageManagementTools


จากโฟลเดอร์ที่ฉันควรทำอย่างไรgit remote add? โคลนจากส้อม? โคลนจากต้นฉบับ? จากภายในไป?
รอบ

1
@lapots รันคำสั่งใน repo ดั้งเดิม (เช่น $ GOPATH / src / github.com / somone / repo)
will7200

จะเกิดอะไรขึ้นถ้าฉันต้องการเพิ่มการเปลี่ยนแปลงใน repo ที่แยกมานานแล้ว?
NA

65

หากคุณกำลังใช้โมดูลไป คุณสามารถใช้replaceคำสั่ง

replaceสั่งช่วยให้คุณสามารถที่จะจัดหาเส้นทางนำเข้าอื่น ๆ ที่อาจจะมีโมดูลอื่นอยู่ใน VCS (GitHub หรือที่อื่น ๆ ) หรือในระบบแฟ้มในท้องถิ่นของคุณกับเส้นทางของไฟล์ญาติหรือแน่นอน เส้นทางการนำเข้าใหม่จากreplaceคำสั่งถูกใช้โดยไม่จำเป็นต้องอัปเดตเส้นทางการนำเข้าในซอร์สโค้ดจริง

คุณสามารถทำได้ด้านล่างในไฟล์ go.mod ของคุณ

module github.com/yogeshlonkar/openapi-to-postman

go 1.12

require (
    github.com/someone/repo v1.20.0
)

replace github.com/someone/repo => github.com/you/repo v3.2.1

ที่v3.2.1เป็นแท็กใน repo ของคุณ สามารถทำได้ผ่าน CLI

go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1"

4
ทำงานได้ดี ฉันคิดว่าเหตุผลเดียวที่ไม่มีการโหวตเพิ่มขึ้นเป็นเพราะผู้คนยังไม่ได้ใช้โมดูล go ฉันยังใช้เคล็ดลับนี้เพื่อชี้ไปที่ตำแหน่งไฟล์ไปยังไดเร็กทอรีอื่นบนเวิร์กสเตชันของฉันซึ่งฉันมีการแก้ไขในเครื่องที่ฉันกำลังดำเนินการอยู่ ฉันจะลบบรรทัด "แทนที่" ของฉันเมื่อฉันพุชการแก้ไขในเครื่องของฉันใน github
lazieburd

^ 100% เห็นด้วย คนโหวต.
Andrew Arrow

2
โอ้ แต่ "ต้นแบบ" ไม่ได้ผลสำหรับฉัน ฉันต้องเขียน v0.0.1 หรือเวอร์ชันเฉพาะที่นั่น
Andrew Arrow

1
คุณยังสามารถโดยตรงในบรรทัดคำสั่ง:go mod edit -replace go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1"ทั้งสองแบบ@v...เป็นทางเลือก
Joel Purra

จะไม่เป็นการดีที่จะมีgo.mod.localหรือgo.mod.devมีบทบาทในการแทนที่เส้นทางการนำเข้าสำหรับการพัฒนาท้องถิ่นจริง ๆ หรือไม่? ฉันหมายความว่าคุณจะไม่ลืมที่จะลบ "แทนที่" ที่น่าเกลียดเพราะคุณจะไม่ต้องทำ
Manuel

21

วิธีหนึ่งในการแก้ปัญหาคือแนะนำโดย Ivan Rave และhttp://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.htmlซึ่งเป็นวิธีการส้อม

อีกวิธีหนึ่งคือการแก้ปัญหาพฤติกรรมโกลัง เมื่อคุณgo get, golangออกวางไดเรกทอรีของคุณภายใต้ชื่อเช่นเดียวกับในพื้นที่เก็บข้อมูล URI และนี่คือที่ปัญหาเริ่มต้น

ถ้าคุณออกของคุณเองgit cloneคุณสามารถโคลนที่เก็บของคุณไปยังระบบไฟล์ของคุณบนเส้นทางที่ตั้งชื่อตามที่เก็บเดิม

สมมติว่าที่เก็บต้นฉบับอยู่ใน github.com/awsome-org/toolและคุณแยกเข้าgithub.com/awesome-you/toolคุณสามารถ:

cd $GOPATH
mkdir -p {src,bin,pkg}
mkdir -p src/github.com/awesome-org/
cd src/github.com/awesome-org/
git clone git@github.com:awesome-you/tool.git # OR: git clone https://github.com/awesome-you/tool.git
cd tool/
go get ./...

golangเป็นอย่างดีมีความสุขที่จะต่อกับแหล่งเก็บข้อมูลนี้และไม่ได้ดูแลจริงบางไดเรกทอรีบนมีชื่อในขณะที่คอมไพล์ระยะไกลawesome-org awesome-youการนำเข้าทั้งหมดได้awesome-orgรับการแก้ไขผ่านไดเร็กทอรีที่คุณเพิ่งสร้างขึ้นซึ่งเป็นชุดการทำงานในเครื่องของคุณ

ในความยาวมากขึ้นโปรดดูบล็อกโพสต์ของฉัน: Forking Golang repositories บน GitHub และการจัดการเส้นทางการนำเข้า

แก้ไข : พา ธ ไดเร็กทอรีคงที่


3
ฉันยอมรับว่านี่เป็นทางออกที่ "ดีที่สุด" สำหรับเรื่องนี้ แต่มันจะดีมากที่ได้เห็นว่าผู้คนจัดการเวิร์กโฟลว์นี้อย่างไรเมื่อเรียกใช้แอป Go ในคอนเทนเนอร์ Docker ฉันกำลังเรียนรู้ golang และต้องการเพิ่มคุณสมบัติเล็ก ๆ ให้กับไลบรารีที่ฉันใช้เมื่อฉันพบอาการปวดหัวนี้ด้วยการทดสอบก่อนสร้าง Pull Request
Joakim

6

หากส้อมของคุณเป็นเพียงชั่วคราว (เช่นคุณตั้งใจว่าจะรวมเข้าด้วยกัน) ให้ทำการพัฒนาในแหล่งกำเนิดเช่นใน $GOPATH/src/launchpad.net/goamz .

จากนั้นคุณใช้คุณสมบัติของระบบควบคุมเวอร์ชัน (เช่น git remote ) เพื่อสร้างที่เก็บอัพสตรีมที่เก็บของคุณแทนที่จะเป็นที่เก็บดั้งเดิม

ทำให้คนอื่นใช้ที่เก็บของคุณด้วยได้ยากขึ้น go getแต่ง่ายกว่ามากสำหรับการรวมต้นน้ำ

อันที่จริงฉันมีที่เก็บสำหรับ goamz ที่lp:~nick-craig-wood/goamz/goamzฉันพัฒนาด้วยวิธีนั้น บางทีผู้เขียนอาจจะรวมเข้าด้วยกันในวันหนึ่ง!


1
เพียงเพื่อให้ฉันเข้าใจถึงผลกระทบของการทำเช่นนี้ถ้าฉันไปเส้นทางนี้เมื่อมีคนทำgo getจาก repo ของฉันข้อความนำเข้าทั้งหมดของฉันและสิ่งเหล่านี้จะยังคงสะท้อนgithub.com/original_authorและถูกทำลาย ... ถูกต้องหรือไม่?
parker.sikand

@ parker.sikand ใช่ถูกต้อง เทคนิคนี้ดีที่สุดสำหรับสิ่งที่คุณตั้งใจจะผสานต้นน้ำไม่ใช่เพื่อใช้งาน หากคุณต้องการแยกหีบห่ออย่างถาวรให้ใช้เทคนิคของคำตอบอื่น
Nick Craig-Wood

4

นี่เป็นวิธีที่เหมาะสำหรับทุกคน:

ใช้ github เพื่อแยกไปที่ "my / repo" (เป็นเพียงตัวอย่าง):

go get github.com/my/repo
cd ~/go/src/github.com/my/repo
git branch enhancement
rm -rf .
go get github.com/golang/tools/cmd/gomvpkg/…
gomvpkg <<oldrepo>> ~/go/src/github.com/my/repo
git commit

ทำซ้ำทุกครั้งเมื่อคุณปรับปรุงโค้ดให้ดีขึ้น:

git commit
git checkout enhancement
git cherry-pick <<commit_id>>
git checkout master

ทำไม? สิ่งนี้ช่วยให้คุณมี repo ของคุณที่ทุกคนใช้go getงานได้ นอกจากนี้ยังช่วยให้คุณรักษาและปรับปรุงสาขาที่ดีสำหรับคำขอดึง มันไม่ได้ขยายคอมไพล์ด้วย "ผู้ขาย" แต่จะรักษาประวัติศาสตร์และสร้างเครื่องมือที่สมเหตุสมผล


การแก้ไขเล็กน้อย: ไปที่ github.com/golang/tools/cmd/gomvpkg/main.go และคำสั่งนี้จะย้าย. git ดังนั้นให้บันทึกไว้ที่อื่นและกู้คืนในภายหลัง
user1212212

นอกจากนี้ยังเป็นไปได้เพียงใช้ปลั๊กอิน mvn-golang ซึ่งทำให้ระบบอัตโนมัติบางอย่างในการประมวลผลการอ้างอิงเช่นในตัวอย่างgithub.com/raydac/mvn-golang/tree/master/mvn-golang-examples/…
Igor Maznitsa

3

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


3
ฉันเสียเวลามากกว่าที่จะยอมรับการวินิจฉัยสิ่งนี้ในการมีส่วนร่วมครั้งแรกในโครงการ Go "การทดสอบทั้งหมดผ่านรวมถึงการทดสอบที่ฉันเขียนเพื่อทดสอบฟังก์ชันการทำงานใหม่อย่างละเอียดมีอะไรผิดพลาด!" คุณตระหนักถึงเครื่องมือที่มีอยู่เพื่อบรรเทาจุดสะดุดสำหรับผู้เริ่มต้นหรือไม่?
Sage Mitchell

3
เมื่อฉันคิดว่ามันออกมามันเป็นเรื่องง่ายที่จะแก้ปัญหาโดยใช้find, xargsและsedแต่มันจะช่วยให้มีขั้นตอนการทำงานที่ปราศจากความเจ็บปวดที่เราทำงานอย่างสม่ำเสมอสำหรับทุกคน
Sage Mitchell

@JakeMitchell gomvpkgสามารถเปลี่ยนชื่อได้ง่ายขึ้น / ดีขึ้น go get golang.org/x/tools/cmd/gomvpkgแล้วgomvpkg -help.
Dave C

3
คำตอบนี้ทำให้ฉันไม่สามารถปฏิบัติได้อย่างสมบูรณ์ ดึงไฟล์โครงการออกจากโครงการที่แยกออกมานั่นเป็นบ้า? คุณจะทำอย่างไรเมื่อสร้างคำขอดึง คำตอบของ Ivan Rave ดูเหมือนจะเป็นทางออกที่ดีกว่าสำหรับฉันมาก
Ivan P

8
นี่ยังเป็นวิธีการทำงานของ Go-lang? นี่เป็นเรื่องบ้ามากจนไม่ตลก ... อาจเป็นมิตรกับต้นน้ำหรือเป็นมิตรกับปลายน้ำ แต่ไม่ใช่ทั้งสองอย่าง มันเป็นข้อบกพร่องในการออกแบบที่ยิ่งใหญ่ในความคิดเห็นที่ไม่ถ่อมตัวของฉันอาจทำโดยคนที่ไม่ร่วมมือกันข้ามโครงการมากเกินไป #FAIL #GOLANG
Niclas Hedhman

1

เพื่อทำให้กระบวนการนี้เป็นไปโดยอัตโนมัติฉันเขียนสคริปต์เล็ก ๆ คุณสามารถดูรายละเอียดเพิ่มเติมในบล็อกของฉันเพื่อเพิ่มคำสั่งเช่น "gofork" ลงใน bash ของคุณ

function gofork() {
  if [ $# -ne 2 ] || [ -z "$1" ] || [ -z "$2" ]; then
    echo 'Usage: gofork yourFork originalModule'
    echo 'Example: gofork github.com/YourName/go-contrib github.com/heirko/go-contrib'
    return
  fi
   echo "Go get fork $1 and replace $2 in GOPATH: $GOPATH"
   go get $1
   go get $2
   currentDir=$PWD
   cd $GOPATH/src/$1
   remote1=$(git config --get remote.origin.url)
   cd $GOPATH/src/$2
   remote2=$(git config --get remote.origin.url)
   cd $currentDir
   rm -rf $GOPATH/src/$2
   mv $GOPATH/src/$1 $GOPATH/src/$2
   cd $GOPATH/src/$2
   git remote add their $remote2
   echo Now in $GOPATH/src/$2 origin remote is $remote1
   echo And in $GOPATH/src/$2 their remote is $remote2
   cd $currentDir
}

export -f gofork

ควรgolangเปลี่ยนเป็นgoforkสาย 4 หรือไม่?
Dan Tenenbaum

เห็นดี! แก้ไข!
heralight

1

ใช้การจัดจำหน่ายและโมดูลย่อยร่วมกัน

  1. แยก lib บน github (go-mssqldb ในกรณีนี้)
  2. เพิ่มโมดูลย่อยที่โคลนส้อมของคุณลงในโฟลเดอร์ผู้ขายของคุณแต่มีเส้นทางของ repo ต้นน้ำ
  3. อัปเดตimportคำสั่งของคุณในซอร์สโค้ดของคุณให้ชี้ไปที่โฟลเดอร์ผู้ขาย (ไม่รวมvendor/คำนำหน้า) เช่นvendor/bob/lib=>import "bob/lib"

เช่น

cd ~/go/src/github.com/myproj

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

git submodule add "git@github.com:$mygithubuser/$librepo" "vendor/$upstreamgithubuser/$librepo"

ทำไม

สิ่งนี้แก้ได้ ทั้งหมดที่ฉันเคยได้ยินและพบมาในขณะที่พยายามคิดออกด้วยตัวเอง

  • การอ้างอิงแพ็กเกจภายในใน lib ใช้งานได้แล้วเนื่องจากเส้นทางไม่เปลี่ยนแปลงจากต้นน้ำ
  • การชำระเงินใหม่ของโปรเจ็กต์ของคุณใช้งานได้เนื่องจากระบบโมดูลย่อยได้รับจากทางแยกของคุณที่คอมมิตที่ถูกต้อง แต่อยู่ในเส้นทางโฟลเดอร์ต้นน้ำ
  • คุณไม่จำเป็นต้องรู้วิธีแฮ็คเส้นทางด้วยตนเองหรือยุ่งกับเครื่องมือไป

ข้อมูลเพิ่มเติม


0

ในGopkg.tomlไฟล์ของคุณเพิ่มบล็อกเหล่านี้ด้านล่าง

[[constraint]]
  name = "github.com/globalsign/mgo"
  branch = "master"
  source = "github.com/myfork/project2"

ดังนั้นมันจะใช้ส้อมproject2แทนgithub.com/globalsign/mgo


Gopkg.tomlไฟล์เป็นเพียงการใช้โดยdepซึ่งคำถามนี้ไม่ได้พูดถึงที่ทั้งหมด โครงการ Go ใหม่ควรใช้โมดูล Go แทน (และโครงการที่อิงตามที่มีอยู่ IMO ควรย้ายข้อมูลด้วย)
Dave C

ฉันไม่รู้เกี่ยวกับคุณลักษณะนี้และคำตอบของคุณช่วยฉันได้อย่างแน่นอน :)
Veger

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