Verwenden des Imports gegabelter Pakete in Go


104

Angenommen, Sie haben ein Repository in github.com/someone/repound geben es an github.com/you/repo. Sie möchten Ihre Gabel anstelle des Haupt-Repos verwenden, also tun Sie a

go get github.com/you/repo

Jetzt werden alle Importpfade in diesem Repo "unterbrochen". Wenn sich also mehrere Pakete im Repository befinden, die über absolute URLs aufeinander verweisen, verweisen sie auf die Quelle und nicht auf die Abzweigung.

Gibt es einen besseren Weg, als es manuell in den richtigen Pfad zu klonen?

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

1
Es wird kein Importpfad in der neuen Gabel unterbrochen, der nicht bereits vor dem Verzweigen unterbrochen wurde.
zzzz

11
Tut mir leid, Sie zu enttäuschen, aber das stimmt nicht. Wenn ein Unterpaket in den Importen über seine absolute URL referenziert wird, wird dieser Import in der Gabel unterbrochen (oder zumindest auf das falsche Paket verweisen).
Erik Aigner

2
ZB goamz . Es hat überall interne Referenzen.
Erik Aigner

1
Schauen Sie sich das ec2Paket an - es hat einen launchpad.net/goamz/awsImport. Sowohl das awsals auch das ec2Paket befinden sich im SAME-Repository. Wenn es also gegabelt wird, verweist es nicht auf das richtige Paket (das in der Gabelung).
Erik Aigner

1
Die Gabel verweist auf dasselbe Paket wie die Quelle der Gabel. Was ist daran falsch? Die Gabel wird kompiliert, sie wird gebaut, sie wird das Gleiche tun wie zuvor. Was ist dann die Definition von "falschem Paket"? Beachten Sie, dass die Go-Sprache als Build-System keine Kenntnis von Repositorys hat, sondern nur von Paketen.
zzzz

Antworten:


83

Pull-Anfragen bearbeiten

  • Fork ein Repository github.com/someone/repozugithub.com/you/repo
  • Originalcode herunterladen: go get github.com/someone/repo
  • da sein: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • Aktivieren Sie das Hochladen auf Ihre Gabel: git remote add myfork https://github.com/you/repo.git
  • Laden Sie Ihre Änderungen in Ihr Repo hoch: git push myfork

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

So verwenden Sie ein Paket in Ihrem Projekt

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


Aus welchem ​​Ordner soll ich machen git remote add? Klon von der Gabel? Klon vom Original? von innen gehen?
Lapots

1
@ Lapots führen den Befehl im ursprünglichen Repo aus (dh $ GOPATH / src / github.com / somone / repo)
will7200

Was ist, wenn ich einem vor langer Zeit gegabelten Repo Änderungen hinzufügen möchte?
NA

61

Wenn Sie go-Module verwenden . Sie könnten die replaceDirektive verwenden

Mit der replaceAnweisung können Sie einen anderen Importpfad angeben, bei dem es sich möglicherweise um ein anderes Modul in VCS (GitHub oder anderswo) oder in Ihrem lokalen Dateisystem mit einem relativen oder absoluten Dateipfad handelt. Der neue Importpfad aus der replaceDirektive wird verwendet, ohne dass die Importpfade im eigentlichen Quellcode aktualisiert werden müssen.

Sie können dies also unten in Ihrer go.mod-Datei tun

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

Wo v3.2.1ist das Tag auf deinem Repo? Kann auch über die CLI erfolgen

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

4
hat super funktioniert. Ich denke, der einzige Grund, warum dies nicht mehr Upvotes hat, ist, dass die Leute noch keine Go-Module verwenden. Ich habe diesen Trick auch verwendet, um auf einen Dateispeicherort in einem anderen Verzeichnis auf meiner Workstation zu verweisen, in dem ich lokale Änderungen vorgenommen habe. Ich würde einfach meine "Ersetzen" -Linie entfernen, sobald ich meine lokalen Änderungen in Github pushe.
Lazieburd

^ 100% stimmen zu. Leute wählen.
Andrew Arrow

2
Oh, aber "Meister" hat bei mir nicht funktioniert. Ich musste dort v0.0.1 oder eine bestimmte Version schreiben.
Andrew Arrow

1
Sie können auch go mod edit -replace direkt über die Befehlszeile : go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1". Beide @v...sind optional.
Joel Purra

Wäre es nicht cool, eine zu haben go.mod.localoder go.mod.devderen Aufgabe es ist, den Importpfad für die lokale Entwicklung tatsächlich zu ersetzen? Ich meine, Sie würden nie vergessen, das hässliche "Ersetzen" zu entfernen, weil Sie es nicht müssten.
Manuel

21

Eine Möglichkeit, dies zu lösen, ist die von Ivan Rave und http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html vorgeschlagene Methode zum Gabeln.

Eine andere Möglichkeit besteht darin, das Golang- Verhalten zu umgehen . Wenn Sie go get, golang Ihre Verzeichnisse unter demselben Namen enthalten, wie es in dem Repository - URI und das ist , wo das Problem beginnt.

Wenn Sie stattdessen Ihr eigenes git cloneRepository ausgeben , können Sie Ihr Repository unter einem Pfad, der nach dem ursprünglichen Repository benannt ist, auf Ihr Dateisystem klonen.

Angenommen, das ursprüngliche Repository befindet sich github.com/awsome-org/toolund Sie teilen es auf github.com/awesome-you/tool, können Sie:

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 ist vollkommen glücklich, mit diesem Repository fortzufahren, und es ist ihm eigentlich egal, ob ein oberes Verzeichnis den Namen hat, awesome-orgwährend sich die Git-Fernbedienung befindet awesome-you. Alle Importe für awesome-orgwerden über das soeben erstellte Verzeichnis, das Ihr lokaler Arbeitssatz ist, erneut erstellt.

Weitere Informationen finden Sie in meinem Blogbeitrag: Forken von Golang-Repositorys auf GitHub und Verwalten des Importpfads

edit : fester Verzeichnispfad


3
Ich bin damit einverstanden, dass dies die "beste" Lösung dafür ist. Aber es wäre wirklich schön zu sehen, wie Leute diesen Workflow verwalten, wenn sie die Go-App in einem Docker-Container ausführen. Ich lerne Golang und wollte einer Bibliothek, die ich verwende, eine winzige Funktion hinzufügen, als ich beim Testen auf diese Kopfschmerzen stieß, bevor ich eine Pull-Anfrage erstellte.
Joakim

6

Wenn Ihre Gabel nur vorübergehend ist (dh Sie beabsichtigen, sie zusammenzuführen), führen Sie Ihre Entwicklung einfach in situ durch, z $GOPATH/src/launchpad.net/goamz.

Anschließend verwenden Sie die Funktionen des Versionskontrollsystems (z. B. git remote), um das Upstream-Repository zu Ihrem Repository und nicht zum ursprünglichen Repository zu machen.

Dies erschwert es anderen Personen, Ihr Repository zu verwenden go get, erleichtert jedoch die Integration in das Upstream.

Tatsächlich habe ich ein Repository für Goamz lp:~nick-craig-wood/goamz/goamz, für das ich genau so entwickle. Vielleicht wird der Autor es eines Tages zusammenführen!


1
Nur damit ich die Auswirkungen davon verstehe, wenn ich diesen Weg gegangen bin, wenn jemand ein go getaus meinem Repo macht, werden alle meine Importanweisungen und dergleichen immer noch reflektiert github.com/original_authorund somit gebrochen ... richtig?
parker.sikand

@ parker.sikand ja das ist richtig. Diese Technik eignet sich am besten für Dinge, die Sie stromaufwärts zusammenführen möchten, und nicht für den Einsatz. Wenn Sie beabsichtigen, das Paket dauerhaft zu teilen, verwenden Sie die Technik der anderen Antwort.
Nick Craig-Wood

4

Hier ist ein Weg, der für alle funktioniert:

Verwenden Sie Github, um zu "my / repo" zu wechseln (nur ein Beispiel):

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

Wiederholen Sie diesen Vorgang jedes Mal, wenn Sie den Code verbessern:

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

Warum? Auf diese Weise können Sie Ihr Repo haben, mit dem jedes go getfunktioniert. Außerdem können Sie einen Zweig pflegen und erweitern, der für eine Pull-Anfrage geeignet ist. Es bläht sich nicht mit "Vendor" auf, es bewahrt die Geschichte und Build-Tools können Sinn machen.


Leichte Korrektur: Führen Sie github.com/golang/tools/cmd/gomvpkg/main.go aus, und dieser Befehl verschiebt .git. Speichern Sie ihn also an einer anderen Stelle und stellen Sie ihn anschließend wieder her.
user1212212

Es ist auch möglich, einfach das mvn-golang-Plugin zu verwenden, das die Verarbeitung von Abhängigkeiten wie im Beispiel github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/…
Igor Maznitsa vom

3

Die Antwort darauf lautet: Wenn Sie ein Repo mit mehreren Paketen teilen, müssen Sie alle relevanten Importpfade umbenennen. Dies ist größtenteils eine gute Sache, da Sie alle diese Pakete gegabelt haben und die Importpfade dies widerspiegeln sollten.


3
Ich habe mehr Zeit verbrannt, als ich zugeben möchte, dass ich dies in meinem ersten Beitrag zu einem Go-Projekt diagnostiziert habe. "Alle Tests bestehen, einschließlich der Tests, die ich geschrieben habe, um neue Funktionen ausführlich zu testen. Was ist los?!" Kennen Sie verfügbare Werkzeuge, um Anfängern diesen Stolperpunkt zu erleichtern?
Sage Mitchell

3
Sobald ich es herausgefunden, es war einfach mit zu lösen find, xargsund sed, aber es würde helfen , einen schmerzfreien Workflow haben , dass konsequent für alle funktioniert.
Sage Mitchell

@JakeMitchell gomvpkgkann die Umbenennung einfacher / besser machen. go get golang.org/x/tools/cmd/gomvpkgdann gomvpkg -help.
Dave C

3
Diese Antwort erscheint mir völlig unpraktisch. Projektdateien aus einem gespaltenen Projekt entfernen, ist das verrückt? Was machen Sie, wenn Sie eine Pull-Anfrage erstellen? Die Antwort von Ivan Rave scheint mir eine viel bessere Lösung zu sein.
Ivan P

8
Funktioniert Go-lang immer noch so? Das ist einfach so verrückt, dass es nicht lustig ist ... Entweder Upstream-freundlich oder Downstream-freundlich, aber nicht beides. Meiner nicht so bescheidenen Meinung nach ist dies ein großer Designfehler, wahrscheinlich von Leuten, die nicht zu viele projektübergreifende Projekte durchführen. #FAIL #GOLANG
Niclas Hedhman

1

Um diesen Prozess zu automatisieren, habe ich ein kleines Skript geschrieben. Weitere Details finden Sie in meinem Blog , um Ihrer Bash einen Befehl wie "gofork" hinzuzufügen.

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

Sollte in Zeile 4 golanggeändert werden gofork?
Dan Tenenbaum

Gut gesehen! Fix!
Heralight

1

Verwenden Sie Vendoring und Submodule zusammen

  1. Fork die lib auf github (in diesem Fall go-mssqldb)
  2. Fügen Sie ein Submodul hinzu, das Ihre Gabel in Ihren Lieferantenordner klont, aber den Pfad des Upstream-Repos enthält
  3. Aktualisieren Sie Ihre importAnweisungen in Ihrem Quellcode so, dass sie auf den Herstellerordner verweisen (ohne vendor/Präfix). ZB vendor/bob/lib=>import "bob/lib"

Z.B

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

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

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

Warum

Dies löst alle Probleme, von denen ich gehört habe und auf die ich gestoßen bin, während ich versucht habe, dies selbst herauszufinden.

  • Interne Paketreferenzen in der Bibliothek funktionieren jetzt, da der Pfad vom Upstream unverändert bleibt
  • Ein neues Auschecken Ihres Projekts funktioniert, da das Submodul-System es beim richtigen Festschreiben, jedoch im Pfad des vorgelagerten Ordners, von Ihrem Fork erhält
  • Sie müssen nicht wissen, wie Sie die Pfade manuell hacken oder mit den Go-Werkzeugen herumspielen.

Mehr Info


0

Fügen Sie in Ihrer Gopkg.tomlDatei diesen Block unten hinzu

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

Also wird es die Gabel project2anstelle von verwendengithub.com/globalsign/mgo


Die Gopkg.tomlDatei wird nur verwendet, wenn depdiese Frage überhaupt nicht erwähnt wird. Neue Go-Projekte sollten stattdessen Go-Module verwenden (und IMO-vorhandene dep-basierte Projekte sollten ebenfalls migriert werden).
Dave C

Ich wusste nichts über diese Dep-Funktion, und Ihre Antwort hat mir sicherlich geholfen :)
Veger

0

Sie können den Befehl verwenden go get -f, um ein gegabeltes Repo zu erhalten

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.