Korzystanie z rozwidlonego importu pakietów w Go

105

Załóżmy, że masz repozytorium pod adresem github.com/someone/repoi rozwidlasz je do github.com/you/repo. Chcesz użyć forka zamiast głównego repozytorium, więc wykonaj plik

go get github.com/you/repo

Teraz wszystkie ścieżki importu w tym repozytorium będą „zepsute”, co oznacza, że ​​jeśli w repozytorium znajduje się wiele pakietów, które odwołują się do siebie poprzez bezwzględne adresy URL, będą one odnosić się do źródła, a nie do rozwidlenia.

Czy jest lepszy sposób, niż ręczne sklonowanie go do właściwej ścieżki?

git clone git@github.com:you/repo.git $GOPATH/src/github.com/someone/repo
Erik Aigner
źródło
1
Żadna ścieżka importu w nowym rozwidleniu nie zostanie przerwana, jeśli nie została przerwana jeszcze przed rozwidleniem.
zzzz
11
Przepraszam, że cię zawiodłem, ale to nieprawda. Jeśli w imporcie odwołuje się do pakietu podrzędnego za pośrednictwem jego bezwzględnego adresu URL, ten import zostanie przerwany w rozwidleniu (lub przynajmniej odniesie się do niewłaściwego pakietu).
Erik Aigner,
2
Np . Goamz . Wszędzie ma wewnętrzne odniesienia.
Erik Aigner,
1
Spójrz na ec2paczkę - ma launchpad.net/goamz/awsimport. Zarówno pakiety , jak awsi ec2pakiety znajdują się w TYM SAMYM repozytorium, więc po rozwidleniu nie będzie odwoływać się do właściwego pakietu (tego w rozwidleniu).
Erik Aigner,
1
Rozwidlenie będzie odnosić się do tego samego pakietu, co jego źródło. Co w tym złego? Fork skompiluje się, zbuduje, zrobi to samo co poprzednio. Jaka jest zatem definicja „nieprawidłowego pakietu”? Zauważ, że język Go, podobnie jak jego system kompilacji, nie ma świadomości repozytoriów, tylko pakiety.
zzzz

Odpowiedzi:

85

Do obsługi żądań ściągnięcia

  • rozwidlić repozytorium github.com/someone/repodogithub.com/you/repo
  • pobierz oryginalny kod: go get github.com/someone/repo
  • bądź tam: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • włącz przesyłanie do swojego forka: git remote add myfork https://github.com/you/repo.git
  • prześlij zmiany do repozytorium: git push myfork

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

Aby użyć pakietu w swoim projekcie

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

Ivan Rave
źródło
z którego folderu mam zrobić git remote add? klon z widelca? sklonować z oryginału? od wewnątrz iść?
lapots
1
@lapots uruchamia polecenie w oryginalnym repozytorium (tj. $ GOPATH / src / github.com / somone / repo)
will7200
A jeśli chcę dodać zmiany do repozytorium, które zostało rozwidlone dawno temu?
NA
65

Jeśli używasz modułów go . Możesz użyć replacedyrektywy

replaceDyrektywa pozwala dostarczyć inną ścieżkę importu, które mogłyby być inny moduł znajduje się w VCS (GitHub lub gdzie indziej), lub w lokalnym systemie plików z bezwzględną lub względną ścieżkę do pliku. Nowa ścieżka importu z replacedyrektywy jest używana bez konieczności aktualizowania ścieżek importu w rzeczywistym kodzie źródłowym.

Możesz więc zrobić to poniżej w swoim pliku 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

gdzie v3.2.1jest tag w twoim repozytorium. Można to również zrobić przez CLI

go mod edit -replace="github.com/someone/[email protected]=github.com/you/[email protected]"
Yogesh
źródło
4
działał świetnie. Myślę, że jedynym powodem, dla którego nie ma więcej głosów pozytywnych, jest to, że ludzie nie używają jeszcze modułów go. Użyłem również tej sztuczki, aby wskazać lokalizację pliku na inny katalog na mojej stacji roboczej, w którym miałem lokalne edycje, nad którymi pracowałem. Po prostu usunąłbym moją linię „zamień” po wysłaniu lokalnych zmian na github.
lazieburd
^ 100% zgadzam się. Głosuj na ludzi.
Andrew Arrow
2
och, ale „pan” mi nie wyszedł. Musiałem tam napisać v0.0.1 lub jakąś konkretną wersję.
Andrew Arrow
1
Można również go mod edit -replace bezpośrednio w wierszu poleceń: go mod edit -replace="github.com/someone/[email protected]=github.com/you/[email protected]". Obie opcje @v...są opcjonalne.
Joel Purra
Czy nie byłoby fajnie mieć go.mod.locallub go.mod.devktórego rolą jest faktycznie zastąpienie ścieżki importu dla rozwoju lokalnego? Chodzi mi o to, że nigdy nie zapomnisz usunąć brzydkiego „zastąpienia”, ponieważ nie musiałbyś tego robić.
Manuel
21

Jednym ze sposobów rozwiązania tego problemu jest metoda zaproponowana przez Ivana Rave'a i http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html - sposób rozwidlenia.

Innym jest obejście zachowania golang . Kiedy ty go get, golang układa twoje katalogi pod taką samą nazwą jak w identyfikatorze URI repozytorium, i tutaj zaczyna się problem.

Jeśli zamiast tego wydasz własne git clone, możesz sklonować swoje repozytorium do swojego systemu plików na ścieżce nazwanej tak, jak oryginalne repozytorium.

Zakładając, że oryginalne repozytorium jest dostępne github.com/awsome-org/tooli rozwidlasz je github.com/awesome-you/tool, możesz:

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 jest całkowicie zadowolony z kontynuowania tego repozytorium i właściwie nie obchodzi go, że jakiś górny katalog ma taką nazwę, awesome-orgpodczas gdy zdalny git ma taką nazwę awesome-you. Cały import dlaawesome-org pliki są ponownie wyszukiwane za pośrednictwem właśnie utworzonego katalogu, który jest lokalnym zestawem roboczym.

Szerzej , zobacz mój wpis na blogu: Rozwidlenie repozytoriów Golang na GitHub i zarządzanie ścieżką importu

edit : stała ścieżka katalogu

Shlomi Noach
źródło
3
Zgadzam się, że jest to „najlepsze” rozwiązanie. Ale byłoby naprawdę fajnie zobaczyć, jak ludzie zarządzają tym przepływem pracy podczas uruchamiania aplikacji Go w kontenerze Docker. Uczę się golanga i chciałem dodać niewielką funkcję do biblioteki, której używam, kiedy napotkałem ten ból głowy podczas testowania go przed utworzeniem żądania ściągnięcia.
Joakim
6

Jeśli twój fork jest tylko tymczasowy (tj. Zamierzasz go scalić), po prostu zrób swój rozwój in situ, np. In $GOPATH/src/launchpad.net/goamz . .

Następnie używasz funkcji systemu kontroli wersji (np. git remote), Aby uczynić z repozytorium nadrzędnego repozytorium zamiast oryginalnego.

Utrudnia to innym osobom korzystanie z twojego repozytorium, go getale znacznie ułatwia jego integrację z nadrzędnym.

W rzeczywistości mam repozytorium dla goamz, w lp:~nick-craig-wood/goamz/goamzktórym rozwijam się dokładnie w ten sposób. Może autor kiedyś to połączy!

Nick Craig-Wood
źródło
1
Tak więc rozumiem konsekwencje zrobienia tego, gdybym poszedł tą drogą, kiedy ktoś zrobi go getz mojego repozytorium, wszystkie moje instrukcje importu i takie będą nadal odzwierciedlać github.com/original_authori dlatego zostaną złamane ... prawda?
parker.sikand
@ parker.sikand tak, to prawda. Ta technika jest najlepsza w przypadku rzeczy, które zamierzasz scalić w górę, a nie do użytku. Jeśli zamierzasz trwale rozwidlić pakiet, użyj techniki drugiej odpowiedzi.
Nick Craig-Wood
4

Oto sposób, aby to działało dla każdego:

Użyj github, aby rozwidlić do „my / repo” (tylko przykład):

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

Powtarzaj za każdym razem, gdy ulepszysz kod:

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

Czemu? Dzięki temu masz repozytorium, go getz którym współpracuje. Pozwala również utrzymywać i ulepszać gałąź, która jest dobra dla żądania ściągnięcia. Nie nadyma gita „dostawcą”, zachowuje historię, a narzędzia do budowania mogą to nadać sens.

user1212212
źródło
Niewielka korekta: uruchom github.com/golang/tools/cmd/gomvpkg/main.go, a to polecenie przenosi plik .git, więc zapisz go gdzie indziej i przywróć go później.
user1212212
również można po prostu użyć wtyczki mvn-golang, która automatyzuje przetwarzanie zależności jak w przykładzie github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/ ...
Igor Maznitsa
3

Odpowiedź jest taka, że ​​jeśli rozwidlisz repozytorium z wieloma pakietami, będziesz musiał zmienić nazwy wszystkich odpowiednich ścieżek importu. Jest to w dużej mierze dobra rzecz, ponieważ wszystkie te pakiety zostały rozwidlone, a ścieżki importu powinny to odzwierciedlać.

Jeremy Wall
źródło
3
Spaliłem więcej czasu, niż chciałbym przyznać się do zdiagnozowania tego w moim pierwszym wkładzie w projekt Go. „Wszystkie testy przeszły pomyślnie, w tym te, które napisałem w celu wyczerpującego przetestowania nowych funkcji. Co się stało ?!” Czy znasz jakieś dostępne narzędzia, które ułatwiają początkującym użytkownikom ten problem?
Sage Mitchell
3
Kiedy się zorientowałem, było to łatwe do rozwiązania za pomocą find, xargsi sed, ale pomogłoby to mieć bezbolesny przepływ pracy, który konsekwentnie działa dla każdego.
Sage Mitchell
@JakeMitchell gomvpkgmoże łatwiej / lepiej zmieniać nazwy. go get golang.org/x/tools/cmd/gomvpkgwtedy gomvpkg -help.
Dave C
3
Ta odpowiedź wydaje mi się całkowicie niepraktyczna. Wyrywanie plików projektu z rozwidlonego projektu, to szaleństwo? Co robisz, gdy tworzysz żądanie ściągnięcia? Odpowiedź Ivana Rave'a wydaje mi się dużo lepszym rozwiązaniem.
Ivan P
8
Czy nadal tak działa Go-lang? To jest po prostu tak szalone, że nie jest zabawne ... Albo bądź przyjazny dla wyższego szczebla, albo dla downstreamu, ale nie oba. Moim niezbyt skromnym zdaniem jest to ogromna wada projektowa, prawdopodobnie wykonana przez ludzi, którzy nie współpracują zbyt wiele w różnych projektach. #FAIL #GOLANG
Niclas Hedhman
1

Aby zautomatyzować ten proces, napisałem mały skrypt. Możesz znaleźć więcej szczegółów na moim blogu, aby dodać polecenie typu „gofork” do swojego basha.

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
heralight
źródło
Należy golangzmienić na goforkw linii 4?
Dan Tenenbaum
dobrze widoczne! naprawić!
heralight
1

Korzystaj ze sprzedaży i modułów podrzędnych razem

  1. Rozwidlaj bibliotekę na github (w tym przypadku go-mssqldb)
  2. Dodaj podmoduł, który klonuje twój fork do folderu dostawcy, ale ma ścieżkę do repozytorium
  3. Zaktualizuj swoje importinstrukcje w kodzie źródłowym, aby wskazywały folder dostawcy (bez vendor/prefiksu). Np. vendor/bob/lib=>import "bob/lib"

Na przykład

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

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

git submodule add "[email protected]:$mygithubuser/$librepo" "vendor/$upstreamgithubuser/$librepo"

Czemu

To rozwiązuje wszystkie problemy, o których słyszałem i napotkałem, próbując rozwiązać to samodzielnie.

  • Odniesienia do pakietów wewnętrznych w bibliotece działają teraz, ponieważ ścieżka pozostaje niezmieniona w stosunku do nadawcy
  • Nowe pobranie twojego projektu działa, ponieważ system podmodułów pobiera go z twojego rozwidlenia po odpowiednim zatwierdzeniu, ale w ścieżce folderu nadrzędnego
  • Nie musisz wiedzieć, jak ręcznie zhakować ścieżki lub zepsuć narzędzia do uruchamiania.

Więcej informacji

Tim Abell
źródło
0

w swoim Gopkg.tomlpliku dodaj te bloki poniżej

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

Więc użyje rozwidlenia project2zamiastgithub.com/globalsign/mgo

msonowal
źródło
Gopkg.tomlPlik jest używany tylko przez depktóre ta kwestia nie wspomina w ogóle. Nowe projekty Go powinny zamiast tego używać modułów Go (a istniejące projekty IMO oparte na depach powinny również zostać poddane migracji).
Dave C
Nie wiedziałem o tej funkcji dep, a twoja odpowiedź na pewno mi pomogła :)
Veger
0

Możesz użyć polecenia, go get -faby uzyskać rozwidlone repozytorium

kevin
źródło