Utilizzo dell'importazione di pacchetti biforcuti in Go


104

Supponiamo di avere un repository in github.com/someone/repoe di eseguirne il fork github.com/you/repo. Vuoi usare il tuo fork invece del repository principale, quindi fai un file

go get github.com/you/repo

Ora tutti i percorsi di importazione in questo repository saranno "interrotti", il che significa che se ci sono più pacchetti nel repository che fanno riferimento l'un l'altro tramite URL assoluti, faranno riferimento alla sorgente, non al fork.

C'è un modo migliore per clonarlo manualmente nel percorso giusto?

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

1
Nessun percorso di importazione nel nuovo fork verrà interrotto che non lo fosse già prima del fork.
zzzz

11
Mi dispiace deluderti, ma non è vero. Se si fa riferimento a un sotto-pacchetto nelle importazioni tramite il suo URL assoluto, questa importazione verrà interrotta nel fork (o almeno farà riferimento al pacchetto sbagliato).
Erik Aigner

2
Ad esempio goamz . Ha riferimenti interni dappertutto.
Erik Aigner

1
Guarda il ec2pacchetto: ha launchpad.net/goamz/awsun'importazione. Sia awsil ec2pacchetto che il pacchetto risiedono nello STESSO repository, quindi quando viene eseguito il fork, non farà riferimento al pacchetto corretto (quello nel fork).
Erik Aigner

1
Il fork farà riferimento allo stesso pacchetto dell'origine del fork. Cosa c'è di sbagliato in questo? Il fork verrà compilato, compilato, farà la stessa cosa di prima. Qual è quindi la definizione di "pacchetto errato"? Nota che il linguaggio Go, così come il suo sistema di compilazione, non ha consapevolezza dei repository, solo dei pacchetti.
zzzz

Risposte:


84

Per gestire le richieste pull

  • forkare un repository github.com/someone/repoingithub.com/you/repo
  • scarica il codice originale: go get github.com/someone/repo
  • essere lì: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • abilita il caricamento sul tuo fork: git remote add myfork https://github.com/you/repo.git
  • carica le modifiche nel tuo repository: git push myfork

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

Per utilizzare un pacchetto nel tuo progetto

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


da quale cartella dovrei fare git remote add? clonare dalla forcella? clonare dall'originale? dall'interno andare?
giri

1
@lapots esegue il comando nel repository originale (ad esempio $ GOPATH / src / github.com / somone / repo)
will7200

Cosa succede se voglio aggiungere modifiche a un repo che è stato biforcato molto tempo fa?
NA

61

Se stai usando go modules . Potresti usare la replacedirettiva

La replacedirettiva consente di fornire un altro percorso di importazione che potrebbe essere un altro modulo situato in VCS (GitHub o altrove) o sul file system locale con un percorso di file relativo o assoluto. Il nuovo percorso di importazione dalla replacedirettiva viene utilizzato senza la necessità di aggiornare i percorsi di importazione nel codice sorgente effettivo.

Quindi puoi fare di seguito nel tuo file 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

dov'è il v3.2.1tag sul tuo repository. Inoltre può essere fatto tramite CLI

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

4
ha funzionato alla grande. Penso che l'unica ragione per cui questo non abbia più voti positivi è perché la gente non sta ancora usando i moduli go. Ho anche usato questo trucco per puntare a un percorso di file in un'altra directory sulla mia workstation in cui avevo modifiche locali su cui stavo lavorando. Vorrei semplicemente rimuovere la mia riga "sostituisci" una volta che spingo le mie modifiche locali in GitHub.
lazieburd

^ 100% d'accordo. Vota le persone.
Andrew Arrow

2
oh, ma "master" non ha funzionato per me. Ho dovuto scrivere la v0.0.1 o una versione specifica lì.
Andrew Arrow,

1
È possibile anche go mod edit -replace direttamente sulla riga di comando: go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1". Entrambi @v...sono opzionali.
Joel Purra

Non sarebbe bello avere un go.mod.localo il go.mod.devcui ruolo è quello di sostituire effettivamente il percorso di importazione per lo sviluppo locale? Voglio dire, non dimenticheresti mai di rimuovere il brutto "rimpiazzo" perché non dovresti.
Manuel

21

Un modo per risolverlo è quello suggerito da Ivan Rave e http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html - il modo di biforcarsi.

Un altro è risolvere il comportamento del golang . Quando tu go get, golang disponi le tue directory con lo stesso nome dell'URI del repository, ed è qui che iniziano i problemi.

Se, invece, ne emetti uno tuo git clone, puoi clonare il tuo repository sul tuo filesystem su un percorso che prende il nome dal repository originale.

Supponendo che il repository originale sia presente github.com/awsome-org/toole che tu lo invii github.com/awesome-you/tool, puoi:

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 è perfettamente felice di continuare con questo repository e in realtà non si preoccupa che alcune directory superiori abbiano il nome awesome-orgmentre il telecomando git lo è awesome-you. Tutte le importazioni per awesome-orgvengono risistemate tramite la directory che hai appena creato, che è il tuo working set locale.

Più in dettaglio, vedere il mio post sul blog: Forking di repository Golang su GitHub e gestione del percorso di importazione

modifica : percorso di directory fisso


3
Sono d'accordo che questa sia la soluzione "migliore" per questo. Ma sarebbe davvero bello vedere come le persone gestiscono questo flusso di lavoro quando eseguono l'app Go in un contenitore Docker. Sto imparando il golang e volevo aggiungere una piccola funzionalità a una libreria che sto usando quando mi sono imbattuto in questo mal di testa testandolo prima di creare una richiesta di pull.
Joakim

6

Se il tuo fork è solo temporaneo (cioè intendi che venga unito), allora esegui il tuo sviluppo in situ, ad esempio in $GOPATH/src/launchpad.net/goamz.

Quindi si utilizzano le funzionalità del sistema di controllo della versione (ad esempio git remote) per rendere il repository a monte il proprio repository piuttosto che quello originale.

Rende più difficile per altre persone utilizzare il tuo repository, go getma è molto più facile integrarlo a monte.

In effetti ho un repository per goamz in lp:~nick-craig-wood/goamz/goamzcui sviluppo esattamente in quel modo. Forse l'autore un giorno lo fonderà!


1
Solo così capisco le implicazioni di fare questo, se ho seguito questa strada, quando qualcuno fa un go getdal mio repo, tutte le mie istruzioni di importazione e simili continueranno a riflettere github.com/original_authore quindi saranno interrotte ... corretto?
parker.sikand

@ parker.sikand sì, è corretto. Questa tecnica è la migliore per le cose che intendi unire a monte, non per usarle. Se intendi eseguire il fork del pacchetto in modo permanente, utilizza la tecnica dell'altra risposta.
Nick Craig-Wood

4

Ecco un modo per farlo funzionare per tutti:

Usa github per fare il fork di "my / repo" (solo un esempio):

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

Ripeti ogni volta che migliori il codice:

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

Perché? Questo ti consente di avere il tuo repository con cui go getfunziona. Ti consente inoltre di mantenere e migliorare un ramo adatto a una richiesta pull. Non riempie il git di "vendor", preserva la storia e gli strumenti di costruzione possono dargli un senso.


Leggera correzione: vai a eseguire github.com/golang/tools/cmd/gomvpkg/main.go e questo comando sposta .git, quindi salvalo altrove e ripristinalo in seguito.
user1212212

inoltre è possibile utilizzare semplicemente il plugin mvn-golang che rende un po 'automatizzata nell'elaborazione delle dipendenze come nell'esempio github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/…
Igor Maznitsa

3

La risposta a questa domanda è che se si esegue il fork di un repository con più pacchetti, sarà necessario rinominare tutti i percorsi di importazione pertinenti. Questa è in gran parte una buona cosa poiché hai biforcato tutti quei pacchetti ei percorsi di importazione dovrebbero riflettere questo.


3
Ho bruciato più tempo di quanto mi interessa ammettere di aver diagnosticato questo nel mio primo contributo a un progetto Go. "Tutti i test vengono superati, compresi quelli che ho scritto per testare in modo esaustivo le nuove funzionalità. Cosa c'è che non va ?!" Sei a conoscenza di strumenti disponibili per alleviare questo punto d'inciampo per i principianti?
Sage Mitchell

3
Una volta capito, è stato facile risolverlo usando find, xargse sed, ma sarebbe utile avere un flusso di lavoro indolore che funzioni costantemente per tutti.
Sage Mitchell

@JakeMitchell gomvpkgpuò fare le rinomine più facilmente / meglio. go get golang.org/x/tools/cmd/gomvpkgallora gomvpkg -help.
Dave C

3
Questa risposta mi sembra del tutto impraticabile. Estrarre file di progetto da un progetto biforcuto, è folle? Cosa fai quando crei una richiesta pull? La risposta di Ivan Rave mi sembra una soluzione molto migliore.
Ivan P

8
Funziona ancora così Go-lang? Questo è così folle, che non è divertente ... O essere amichevole a monte, o amichevole a valle, ma non entrambi. È un enorme difetto di progettazione a mio parere non così modesto, probabilmente fatto da persone che non collaborano troppo a progetti incrociati. #FAIL #GOLANG
Niclas Hedhman

1

Per automatizzare questo processo, ho scritto un piccolo script. Puoi trovare maggiori dettagli sul mio blog per aggiungere un comando come "gofork" alla tua 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

Dovrebbe golangessere cambiato goforknella riga 4?
Dan Tenenbaum

ben visto! aggiustare!
heralight

1

Usa vendoring e sottomoduli insieme

  1. Eseguire il fork della libreria su GitHub (go-mssqldb in questo caso)
  2. Aggiungi un sottomodulo che clona il tuo fork nella cartella del fornitore ma ha il percorso del repository a monte
  3. Aggiorna le tue importdichiarazioni nel codice sorgente in modo che puntino alla cartella del fornitore (escluso il vendor/prefisso). Ad esempio vendor/bob/lib=>import "bob/lib"

Per esempio

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

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

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

Perché

Questo risolve tutti i problemi di cui ho sentito parlare e ho incontrato mentre cercavo di capirlo da solo.

  • I ref dei pacchetti interni nella libreria ora funzionano perché il percorso non è cambiato dall'upstream
  • Un nuovo checkout del tuo progetto funziona perché il sistema del sottomodulo lo ottiene dal tuo fork al commit corretto ma nel percorso della cartella a monte
  • Non devi sapere per hackerare manualmente i percorsi o fare confusione con gli strumenti go.

Ulteriori informazioni


0

nel tuo Gopkg.tomlfile aggiungi questi blocchi di seguito

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

Quindi userà il fork project2al posto digithub.com/globalsign/mgo


Il Gopkg.tomlfile viene utilizzato solo da depcui questa domanda non menziona affatto. I nuovi progetti Go dovrebbero invece utilizzare i moduli Go (e dovrebbero migrare anche i progetti IMO esistenti basati su dep).
Dave C

Non sapevo di questa funzione di dep, e la tua risposta mi ha sicuramente aiutato :)
Veger

0

Puoi usare il comando go get -fper ottenere un repo biforcato

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.