Uso de la importación de paquetes bifurcados en Go


104

Suponga que tiene un repositorio en github.com/someone/repoy lo bifurca a github.com/you/repo. Quieres usar tu fork en lugar del repositorio principal, entonces haces un

go get github.com/you/repo

Ahora todas las rutas de importación en este repositorio estarán "rotas", lo que significa que si hay varios paquetes en el repositorio que hacen referencia entre sí a través de URL absolutas, harán referencia a la fuente, no a la bifurcación.

¿Existe una mejor manera de clonarlo manualmente en la ruta correcta?

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

1
No se romperá ninguna ruta de importación en la nueva bifurcación que no estuviera rota antes de la bifurcación.
zzzz

11
Siento decepcionarte, pero eso no es cierto. Si se hace referencia a un subpaquete en las importaciones a través de su URL absoluta, esta importación se interrumpirá en la bifurcación (o al menos hará referencia al paquete incorrecto).
Erik Aigner

2
Por ejemplo, goamz . Tiene referencias internas por todo el lugar.
Erik Aigner

1
Mire el ec2paquete, tiene una launchpad.net/goamz/awsimportación. Tanto awslos ec2paquetes como los residen en el MISMO repositorio, por lo que cuando se bifurcan, no harán referencia al paquete correcto (el que está en la bifurcación).
Erik Aigner

1
La bifurcación hará referencia al mismo paquete que la fuente de la bifurcación. ¿Qué hay de incorrecto en eso? La bifurcación se compilará, se construirá, hará lo mismo que antes. Entonces, ¿cuál es la definición de "paquete incorrecto"? Tenga en cuenta que el lenguaje Go, como su sistema de compilación, no tiene conocimiento de repositorios, solo paquetes.
zzzz

Respuestas:


84

Para manejar solicitudes de extracción

  • bifurcar un repositorio github.com/someone/repoparagithub.com/you/repo
  • descargar código original: go get github.com/someone/repo
  • estar ahí: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • habilite la carga en su fork: git remote add myfork https://github.com/you/repo.git
  • cargue sus cambios en su repositorio: git push myfork

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

Para usar un paquete en su proyecto

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


desde que carpeta debo hacer git remote add? clon de fork? clonar del original? desde dentro ir?
lapots

1
@lapots ejecuta el comando en el repositorio original (es decir, $ GOPATH / src / github.com / somone / repo)
will7200

¿Qué sucede si quiero agregar cambios a un repositorio que se bifurcó hace mucho tiempo?
NA

61

Si está utilizando módulos go . Podrías usar replacedirectiva

La replacedirectiva le permite proporcionar otra ruta de importación que podría ser otro módulo ubicado en VCS (GitHub o en otro lugar), o en su sistema de archivos local con una ruta de archivo relativa o absoluta. La nueva ruta de importación de la replacedirectiva se utiliza sin necesidad de actualizar las rutas de importación en el código fuente real.

Entonces podría hacerlo a continuación en su archivo 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

dónde v3.2.1está la etiqueta en su repositorio. También se puede hacer a través de CLI

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

4
funcionó muy bien. Creo que la única razón por la que esto no tiene más votos positivos es porque la gente aún no está usando los módulos go. También utilicé este truco para señalar una ubicación de archivo a otro directorio en mi estación de trabajo donde tenía ediciones locales en las que estaba trabajando. Simplemente eliminaría mi línea "reemplazar" una vez que envíe mis ediciones locales en github.
lazieburd

^ 100% de acuerdo. Vote a la gente.
Andrew Arrow

2
oh, pero "maestro" no funcionó para mí. Tuve que escribir v0.0.1 o alguna versión específica allí.
Andrew Arrow

1
También puede hacer go mod edit -replace directamente en la línea de comandos: go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1". Ambos @v...son opcionales.
Joel Purra

¿No sería genial tener un go.mod.localo go.mod.devcuyo rol es realmente reemplazar el camino de importación para el desarrollo local? Quiero decir, nunca te olvidarías de quitar el feo "reemplazo" porque no tendrías que hacerlo.
Manuel

21

Una forma de resolverlo es la sugerida por Ivan Rave y http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html - la forma de bifurcación.

Otro es solucionar el comportamiento de golang . Cuando usted go get, golang coloca sus directorios con el mismo nombre que en el URI del repositorio, y aquí es donde comienza el problema.

Si, en cambio, emite el suyo propio git clone, puede clonar su repositorio en su sistema de archivos en una ruta con el nombre del repositorio original.

Suponiendo que el repositorio original está dentro github.com/awsome-org/tooly lo bifurca github.com/awesome-you/tool, puedes:

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 está perfectamente feliz de continuar con este repositorio y en realidad no le importa que algún directorio superior tenga el nombre, awesome-orgmientras que el git remote lo es awesome-you. Todas las importaciones awesome-orgse resuelven a través del directorio que acaba de crear, que es su conjunto de trabajo local.

Más detalladamente , consulte la publicación de mi blog: Bifurcación de repositorios de Golang en GitHub y administración de la ruta de importación

editar : ruta de directorio fija


3
Estoy de acuerdo en que esta es la "mejor" solución para esto. Pero sería realmente bueno ver cómo las personas administran este flujo de trabajo cuando ejecutan la aplicación Go en un contenedor Docker. Estoy aprendiendo golang y quería agregar una pequeña función a una biblioteca que estoy usando cuando me encontré con este dolor de cabeza al probarlo antes de crear una solicitud de extracción.
Joakim

6

Si su bifurcación es solo temporal (es decir, tiene la intención de fusionarlo), simplemente haga su desarrollo in situ, por ejemplo, en $GOPATH/src/launchpad.net/goamz .

A continuación, utiliza las funciones del sistema de control de versiones (p. Ej. git remote ) para hacer que el repositorio ascendente sea su repositorio en lugar del original.

Hace que sea más difícil para otras personas usar su repositorio con go get pero es mucho más fácil integrarlo en sentido ascendente.

De hecho, tengo un repositorio de goamz en el lp:~nick-craig-wood/goamz/goamzque desarrollo exactamente de esa manera. ¡Quizás el autor lo combine algún día!


1
Solo para que entienda las implicaciones de hacer esto, si tomé esta ruta, cuando alguien hace una go getdesde mi repositorio, todas mis declaraciones de importación y demás se reflejarán github.com/original_authory, por lo tanto, se romperán ... ¿correcto?
parker.sik y

@ parker.sik y sí, eso es correcto. Esta técnica es mejor para las cosas que desea fusionar en sentido ascendente, no para usarlas. Si tiene la intención de bifurcar el paquete de forma permanente, utilice la técnica de la otra respuesta.
Nick Craig-Wood

4

Aquí hay una forma de que funcione para todos:

Use github para bifurcar a "mi / repositorio" (solo un ejemplo):

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

Repita cada vez que mejore el código:

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

¿Por qué? Esto le permite tener su repositorio con el que cualquiera go getfunciona. También le permite mantener y mejorar una rama que es buena para una solicitud de extracción. No hincha git con "proveedor", conserva el historial y las herramientas de compilación pueden darle sentido.


Ligera corrección: vaya a ejecutar github.com/golang/tools/cmd/gomvpkg/main.go y este comando mueve .git, así que guárdelo en otro lugar y restáurelo después.
user1212212

también es posible usar el complemento mvn-golang que hace cierta automatización en el procesamiento de dependencias como en el ejemplo github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/…
Igor Maznitsa

3

La respuesta a esto es que si bifurca un repositorio con varios paquetes, deberá cambiar el nombre de todas las rutas de importación relevantes. Esto es en gran parte algo bueno ya que ha bifurcado todos esos paquetes y las rutas de importación deberían reflejar esto.


3
He gastado más tiempo del que me gustaría admitir diagnosticar esto en mi primera contribución a un proyecto de Go. "Todas las pruebas pasan, incluidas las que escribí para probar exhaustivamente la nueva funcionalidad. ¡¿Qué pasa ?!" ¿Conoce alguna herramienta disponible para aliviar este obstáculo para los principiantes?
Sage Mitchell

3
Una vez que lo he descubierto que era fácil de resolver usando find, xargsy sed, pero ayudaría a tener un flujo de trabajo sin dolor que trabaja constantemente para todo el mundo.
Sage Mitchell

@JakeMitchell gomvpkgpuede hacer los cambios de nombre más fácil / mejor. go get golang.org/x/tools/cmd/gomvpkgentonces gomvpkg -help.
Dave C

3
Esta respuesta me parece completamente impráctica. Sacar archivos de proyectos de un proyecto bifurcado, ¿es una locura? ¿Qué haces cuando creas una solicitud de extracción? La respuesta de Ivan Rave me parece una solución mucho mejor.
Ivan P

8
¿Sigue funcionando así Go-lang? Esto es tan loco, que no tiene gracia ... Sea amigable con el río arriba o amigable con el río abajo, pero no ambos. En mi no tan humilde opinión, es un gran defecto de diseño, probablemente hecho por personas que no colaboran demasiado en proyectos cruzados. #FAIL #GOLANG
Niclas Hedhman

1

Para automatizar este proceso, escribí un pequeño script. Puedes encontrar más detalles en mi blog para agregar un comando como "gofork" a tu 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

¿Debería golangcambiarse a goforken la línea 4?
Dan Tenenbaum

¡bien visto! ¡reparar!
Heralight

1

Utilice proveedores y submódulos juntos

  1. Bifurque la lib en github (go-mssqldb en este caso)
  2. Agregue un submódulo que clone su bifurcación en la carpeta de su proveedor pero que tenga la ruta del repositorio ascendente
  3. Actualice sus importdeclaraciones en su código fuente para que apunten a la carpeta del proveedor (sin incluir el vendor/prefijo). Por ejemplo vendor/bob/lib=>import "bob/lib"

P.ej

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

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

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

Por qué

Esto resuelve todos los problemas de los que he oído hablar y con los que me he encontrado al tratar de resolverlo yo mismo.

  • Las referencias de paquetes internos en la biblioteca ahora funcionan porque la ruta no ha cambiado desde el origen
  • Una nueva comprobación de su proyecto funciona porque el sistema de submódulos lo obtiene de su bifurcación en la confirmación correcta pero en la ruta de la carpeta ascendente
  • No tiene que saber cortar manualmente los caminos o meterse con las herramientas de Go.

Más información


0

en su Gopkg.tomlarchivo agregue estos bloques a continuación

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

Entonces usará el bifurcado project2en lugar degithub.com/globalsign/mgo


El Gopkg.tomlarchivo solo se usa cuando depesta pregunta no menciona en absoluto. Los nuevos proyectos de Go deberían usar módulos Go en su lugar (y los proyectos existentes basados ​​en dep de la OMI también deberían migrar).
Dave C

No sabía acerca de esta función de depósito, y su respuesta seguramente me ayudó :)
Veger

0

Puede usar el comando go get -fpara obtener un repositorio bifurcado

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.