Sử dụng nhập gói đã tách trong Go


104

Giả sử bạn có một kho lưu trữ tại github.com/someone/repovà bạn chuyển nó vào github.com/you/repo. Bạn muốn sử dụng fork của mình thay vì repo chính, vì vậy bạn thực hiện

go get github.com/you/repo

Bây giờ tất cả các đường dẫn nhập trong kho này sẽ bị "hỏng", có nghĩa là, nếu có nhiều gói trong kho tham chiếu lẫn nhau thông qua URL tuyệt đối, chúng sẽ tham chiếu đến nguồn chứ không phải fork.

Có cách nào tốt hơn là sao chép nó theo cách thủ công vào đúng đường không?

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

1
Không có đường dẫn nhập nào trong fork mới sẽ bị phá vỡ mà chưa bị phá vỡ trước khi fork.
zzzz

11
Xin lỗi đã làm bạn thất vọng, nhưng điều đó không đúng. Nếu một gói phụ được tham chiếu trong các lần nhập thông qua url tuyệt đối của nó, quá trình nhập này sẽ bị hỏng trong nhánh rẽ (hoặc ít nhất là tham chiếu gói sai).
Erik Aigner

2
Ví dụ: goamz . Nó có tài liệu tham khảo nội bộ ở khắp nơi.
Erik Aigner

1
Nhìn vào ec2gói - nó có một launchpad.net/goamz/awsnhập khẩu. Cả hai, người awsvà các ec2gói nằm trong kho CÙNG, vì vậy khi chia hai, sẽ không tham khảo các gói đúng (một trong những ngã ba).
Erik Aigner

1
Fork sẽ tham chiếu cùng một gói với nguồn của fork. Điều gì không chính xác trong đó? Ngã ba sẽ biên dịch, nó sẽ xây dựng, nó sẽ làm điều tương tự như trước đây. Sau đó, định nghĩa của 'gói không chính xác' là gì? Lưu ý rằng ngôn ngữ Go, cũng như hệ thống xây dựng của nó, không có nhận thức về kho mà chỉ có các gói.
zzzz

Câu trả lời:


84

Để xử lý các yêu cầu kéo

  • chuyển một kho lưu trữ github.com/someone/repođếngithub.com/you/repo
  • tải xuống mã gốc: go get github.com/someone/repo
  • ở đó: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • cho phép tải lên fork của bạn: git remote add myfork https://github.com/you/repo.git
  • tải các thay đổi của bạn lên repo của bạn: git push myfork

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

Để sử dụng một gói trong dự án của bạn

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


từ thư mục nào tôi nên làm gì git remote add? nhân bản từ ngã ba? sao chép từ bản gốc? từ bên trong đi?
lapots

1
@lapots chạy lệnh trong repo gốc (tức là $ GOPATH / src / github.com / somone / repo)
will7200

Điều gì sẽ xảy ra nếu tôi muốn thêm các thay đổi vào repo đã được chia từ lâu?
NA

61

Nếu bạn đang sử dụng mô-đun go . Bạn có thể sử dụng replacechỉ thị

Lệnh replacecho phép bạn cung cấp một đường dẫn nhập khác có thể là một mô-đun khác nằm trong VCS (GitHub hoặc nơi khác) hoặc trên hệ thống tệp cục bộ của bạn với đường dẫn tệp tương đối hoặc tuyệt đối. Đường dẫn nhập mới từ replacechỉ thị được sử dụng mà không cần cập nhật đường dẫn nhập trong mã nguồn thực.

Vì vậy, bạn có thể thực hiện bên dưới trong tệp go.mod của mình

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

nơi v3.2.1là thẻ trên repo của bạn. Cũng có thể được thực hiện thông qua CLI

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

4
hoạt động tốt. Tôi nghĩ rằng lý do duy nhất khiến điều này không có nhiều lượt ủng hộ hơn là vì mọi người chưa sử dụng mô-đun go. Tôi cũng đã sử dụng thủ thuật này để trỏ đến một vị trí tệp đến một thư mục khác trên máy trạm của tôi, nơi tôi đang thực hiện các chỉnh sửa cục bộ. Tôi sẽ chỉ xóa dòng "thay thế" khi tôi đẩy các chỉnh sửa cục bộ của mình trong github.
lazieburd

^ 100% đồng ý. Bình chọn mọi người.
Andrew Arrow,

2
oh, nhưng "chủ nhân" đã không làm việc cho tôi. Tôi đã phải viết v0.0.1 hoặc một số phiên bản cụ thể ở đó.
Andrew Arrow

1
Bạn cũng có thể go mod edit -replace trực tiếp trên dòng lệnh: go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1". Cả hai đều @v...là tùy chọn.
Joel Purra

Sẽ thật tuyệt nếu có một go.mod.localhoặc ai go.mod.devđó thực sự có vai trò thay thế con đường nhập khẩu để phát triển địa phương? Ý tôi là, bạn sẽ không bao giờ quên loại bỏ "thay thế" xấu xí bởi vì bạn sẽ không phải làm vậy.
Manuel

21

Một cách để giải quyết nó được đề xuất bởi Ivan Rave và http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html - cách forking.

Một cách khác là giải quyết hành vi golang . Khi bạn go get, golang đặt các thư mục của bạn dưới cùng tên như trong URI kho lưu trữ, và đây là lúc rắc rối bắt đầu.

Thay vào đó, nếu bạn phát hành riêng git clone, bạn có thể sao chép kho lưu trữ của mình vào hệ thống tệp của bạn trên một đường dẫn được đặt tên theo kho lưu trữ ban đầu.

Giả sử có kho lưu trữ gốc github.com/awsome-org/toolvà bạn phân nhánh nó github.com/awesome-you/tool, bạn có thể:

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 hoàn toàn vui vẻ tiếp tục với kho lưu trữ này và thực sự không quan tâm đến một số thư mục phía trên có tên awesome-orgtrong khi điều khiển từ xa git awesome-you. Tất cả quá trình nhập cho awesome-orgđược cộng hưởng thông qua thư mục bạn vừa tạo, đó là tập hợp làm việc cục bộ của bạn.

Nói chi tiết hơn, vui lòng xem bài đăng trên blog của tôi: Tạo kho lưu trữ Golang trên GitHub và quản lý đường dẫn nhập

chỉnh sửa : đường dẫn thư mục cố định


3
Tôi đồng ý đây là giải pháp "tốt nhất" cho việc này. Nhưng sẽ thực sự tuyệt vời khi thấy cách mọi người quản lý quy trình công việc này khi chạy ứng dụng Go trong vùng chứa Docker. Tôi đang học golang và muốn thêm một tính năng nhỏ vào thư viện mà tôi đang sử dụng khi tôi gặp phải vấn đề đau đầu này với việc thử nghiệm nó trước khi tạo Yêu cầu kéo.
Joakim

6

Nếu fork của bạn chỉ là tạm thời (tức là bạn dự định rằng nó sẽ được hợp nhất) thì chỉ cần thực hiện phát triển tại chỗ, ví dụ: tại chỗ $GOPATH/src/launchpad.net/goamz.

Sau đó, bạn sử dụng các tính năng của hệ thống kiểm soát phiên bản (ví dụ git remote) để làm cho kho lưu trữ ngược dòng là kho lưu trữ của bạn thay vì kho lưu trữ ban đầu.

Nó khiến người khác khó sử dụng kho lưu trữ của bạn go gethơn nhưng lại dễ dàng hơn để tích hợp ngược dòng.

Trên thực tế, tôi có một kho lưu trữ cho goamz lp:~nick-craig-wood/goamz/goamzmà tôi phát triển theo cách đó. Có thể một ngày nào đó tác giả sẽ hợp nhất lại!


1
Để tôi hiểu ý nghĩa của việc làm này, nếu tôi đi theo con đường này, khi ai đó thực hiện một go gettừ kho của tôi, tất cả các câu lệnh nhập của tôi và những điều đó sẽ vẫn phản ánh github.com/original_authorvà do đó bị hỏng ... đúng không?
parker.sikand

@ parker.sikand vâng, đúng vậy. Kỹ thuật này là tốt nhất cho những thứ bạn định trộn ngược dòng, không phải để sử dụng. Nếu bạn có ý định tách gói vĩnh viễn thì hãy sử dụng kỹ thuật của câu trả lời khác.
Nick Craig-Wood

4

Đây là một cách để làm việc đó cho tất cả mọi người:

Sử dụng github để fork thành "my / repo" (chỉ là một ví dụ):

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

Lặp lại mỗi lần khi bạn làm cho mã tốt hơn:

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

Tại sao? Điều này cho phép bạn có repo của bạn mà bất kỳ go gethoạt động nào . Nó cũng cho phép bạn duy trì và cải tiến một nhánh tốt cho một yêu cầu kéo. Nó không cồng kềnh với "nhà cung cấp", nó lưu giữ lịch sử và các công cụ xây dựng có thể hiểu được điều đó.


Chỉnh sửa nhẹ: chạy github.com/golang/tools/cmd/gomvpkg/main.go và lệnh này di chuyển .git, vì vậy hãy lưu nó ở nơi khác và khôi phục nó sau đó.
dùng1212212

cũng có thể chỉ cần sử dụng plugin mvn-golang giúp tự động hóa một số quá trình xử lý phụ thuộc như trong ví dụ github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/…
Igor Maznitsa

3

Câu trả lời cho điều này là nếu bạn fork một repo với nhiều gói, bạn sẽ cần đổi tên tất cả các đường dẫn nhập có liên quan. Đây phần lớn là một điều tốt vì bạn đã chia nhỏ tất cả các gói đó và các đường dẫn nhập sẽ phản ánh điều này.


3
Tôi đã đốt nhiều thời gian hơn những gì tôi quan tâm để thừa nhận việc chẩn đoán điều này trong lần đầu tiên đóng góp cho dự án cờ vây. "Tất cả các bài kiểm tra đều vượt qua, bao gồm cả những bài kiểm tra tôi đã viết để kiểm tra toàn bộ chức năng mới. Có chuyện gì vậy ?!" Bạn có biết về bất kỳ công cụ có sẵn nào để giảm bớt khó khăn này cho người mới bắt đầu không?
Sage Mitchell

3
Khi tôi figured it out đó là dễ dàng để giải quyết vấn sử dụng find, xargssed, nhưng nó sẽ giúp đỡ để có một công việc đau đớn-miễn phí liên tục làm việc cho tất cả mọi người.
Sage Mitchell

@JakeMitchell gomvpkgcó thể đổi tên dễ dàng hơn / tốt hơn. go get golang.org/x/tools/cmd/gomvpkgsau đó gomvpkg -help.
Dave C

3
Câu trả lời này đánh giá tôi là hoàn toàn không thực tế. Đưa các tệp dự án ra khỏi một dự án đã phân nhánh, điều đó thật điên rồ? Bạn làm gì khi tạo một yêu cầu kéo? Câu trả lời của Ivan Rave có vẻ là một giải pháp tốt hơn cho tôi.
Ivan P

8
Đây có còn là cách Go-lang đang hoạt động không? Điều này thật điên rồ, không vui chút nào ... Hoặc là thân thiện với thượng nguồn, hoặc thân thiện với hạ lưu, nhưng không phải cả hai. Đó là một lỗ hổng thiết kế lớn theo quan điểm không khiêm tốn của tôi, có lẽ được thực hiện bởi những người không cộng tác quá nhiều dự án chéo. #FAIL #GOLANG
Niclas Hedhman,

1

Để tự động hóa quá trình này, tôi đã viết một đoạn script nhỏ. Bạn có thể tìm thêm chi tiết trên blog của tôi để thêm một lệnh như "gofork" vào bash của bạn.

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

Nên golangđổi thành goforkdòng 4?
Dan Tenenbaum

cũng thấy! sửa chữa!
heralight

1

Sử dụng mô-đun con và nhà cung cấp cùng nhau

  1. Fork the lib trên github (go-mssqldb trong trường hợp này)
  2. Thêm một mô-đun con sao chép fork của bạn vào thư mục nhà cung cấp nhưng có đường dẫn của repo ngược dòng
  3. Cập nhật các importcâu lệnh trong mã nguồn của bạn để trỏ đến thư mục nhà cung cấp, (không bao gồm vendor/tiền tố). Vd vendor/bob/lib=>import "bob/lib"

Ví dụ

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

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

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

Tại sao

Điều này giải quyết tất cả các vấn đề tôi đã nghe và gặp phải trong khi cố gắng tự tìm ra điều này.

  • Các tham chiếu gói nội bộ trong lib hiện hoạt động vì đường dẫn không thay đổi so với ngược dòng
  • Quá trình kiểm tra mới cho dự án của bạn hoạt động vì hệ thống mô-đun con lấy nó từ fork của bạn theo đúng cam kết nhưng trong đường dẫn thư mục ngược dòng
  • Bạn không cần phải biết tự hack các đường dẫn hoặc gây rối với công cụ go.

Thêm thông tin


0

trong Gopkg.tomltệp của bạn, hãy thêm các khối này bên dưới

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

Vì vậy, nó sẽ sử dụng fork project2thay chogithub.com/globalsign/mgo


Các Gopkg.tomltập tin chỉ được sử dụng bởi depđó câu hỏi này không đề cập đến ở tất cả. Các dự án Go mới nên sử dụng mô-đun Go thay thế (và các dự án dựa trên dep hiện có của IMO cũng nên di chuyển).
Dave C

Tôi không biết về tính năng dep này, và câu trả lời của bạn chắc chắn đã giúp tôi :)
Veger

0

Bạn có thể sử dụng lệnh go get -fđể nhận được một repo đã chia nhỏ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.