Usando a importação de pacote bifurcada no Go

104

Suponha que você tenha um repositório em github.com/someone/repoe faça um fork dele github.com/you/repo. Você deseja usar seu fork em vez do repo principal, então você faz um

go get github.com/you/repo

Agora, todos os caminhos de importação neste repositório serão "quebrados", o que significa que, se houver vários pacotes no repositório que fazem referência uns aos outros por meio de URLs absolutos, eles farão referência à fonte, não ao fork.

Existe uma maneira melhor do que cloná-lo manualmente no caminho certo?

git clone git@github.com:you/repo.git $GOPATH/src/github.com/someone/repo
Erik Aigner
fonte
1
Nenhum caminho de importação na nova bifurcação será quebrado, o que não foi quebrado antes da bifurcação.
zzzz
11
Desculpe desapontá-lo, mas isso não é verdade. Se um subpacote for referenciado nas importações por meio de seu url absoluto, essa importação será interrompida na bifurcação (ou pelo menos fará referência ao pacote errado).
Erik Aigner
2
Por exemplo, goamz . Possui referências internas por todo o lugar.
Erik Aigner
1
Veja o ec2pacote - ele tem uma launchpad.net/goamz/awsimportação. Ambos, o awse os ec2pacotes residem no SAME repositório, portanto, quando bifurcados, não farão referência ao pacote correto (aquele na bifurcação).
Erik Aigner
1
O fork fará referência ao mesmo pacote que a fonte do fork. O que há de errado nisso? O fork irá compilar, irá construir, fará a mesma coisa de antes. Qual é a definição de 'pacote incorreto' então? Observe que a linguagem Go, assim como seu sistema de construção, não tem conhecimento de repositórios, apenas pacotes.
zzzz

Respostas:

84

Para lidar com solicitações pull

  • bifurcar um repositório github.com/someone/repoparagithub.com/you/repo
  • baixar o código original: go get github.com/someone/repo
  • estar lá: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • habilite o upload para o seu fork: git remote add myfork https://github.com/you/repo.git
  • envie suas alterações para o seu repo: git push myfork

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

Para usar um pacote em seu projeto

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

Ivan Rave
fonte
de qual pasta devo fazer git remote add? clone do garfo? clone do original? de dentro, vá?
lapôs de
1
@lapots executa o comando no repo original (ou seja, $ GOPATH / src / github.com / somone / repo)
will7200
E se eu quiser adicionar alterações a um repositório que foi bifurcado há muito tempo?
NA
61

Se você estiver usando módulos go . Você poderia usar replacediretiva

A replacediretiva permite que você forneça outro caminho de importação que pode ser outro módulo localizado no VCS (GitHub ou outro lugar), ou em seu sistema de arquivos local com um caminho de arquivo absoluto ou relativo. O novo caminho de importação da replacediretiva é usado sem a necessidade de atualizar os caminhos de importação no código-fonte real.

Então, você pode fazer abaixo em seu arquivo 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

onde v3.2.1está a tag no seu repo. Também pode ser feito através do CLI

go mod edit -replace="github.com/someone/[email protected]=github.com/you/[email protected]"
Yogesh
fonte
4
funcionou muito bem. Acho que a única razão pela qual isso não tem mais votos positivos é porque as pessoas ainda não estão usando os módulos go. Também usei esse truque para apontar para um local de arquivo para outro diretório em minha estação de trabalho onde eu tinha edições locais nas quais estava trabalhando. Gostaria apenas de remover minha linha "substituir" assim que enviar minhas edições locais no github.
Lazieburd
^ 100% concordam. Votar pessoas.
Andrew Arrow
2
oh, mas "mestre" não funcionou para mim. Tive que escrever a v0.0.1 ou alguma versão específica lá.
Andrew Arrow
1
Você também pode go mod edit -replace diretamente na linha de comando: go mod edit -replace="github.com/someone/[email protected]=github.com/you/[email protected]". Ambos @v...são opcionais.
Joel Purra
Não seria legal ter um go.mod.localou go.mod.devcujo papel é realmente substituir o caminho de importação para o desenvolvimento local? Quero dizer, você nunca se esqueceria de remover o feio "substituir" porque não seria necessário.
Manuel
21

Uma maneira de resolver isso é aquela sugerida por Ivan Rave e http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html - a forma de bifurcação.

Outra é contornar o comportamento do golang . Quando você go get, golang organiza seus diretórios com o mesmo nome do URI do repositório, e é aí que o problema começa.

Se, em vez disso, você emitir o seu próprio git clone, poderá clonar seu repositório em seu sistema de arquivos em um caminho com o nome do repositório original.

Supondo que o repositório original esteja dentro github.com/awsome-org/toole você o bifurque github.com/awesome-you/tool, você pode:

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á perfeitamente feliz em continuar com este repositório e realmente não se importa se algum diretório superior tem o nome awesome-orgenquanto o remoto git está awesome-you. Todas as importações de awesome-orgsão resolvidas por meio do diretório que você acabou de criar, que é o seu conjunto de trabalho local.

Mais extensamente, por favor, veja minha postagem no blog: Bifurcando repositórios Golang no GitHub e gerenciando o caminho de importação

editar : caminho de diretório fixo

Shlomi Noach
fonte
3
Concordo que essa é a "melhor" solução para isso. Mas seria muito bom ver como as pessoas gerenciam esse fluxo de trabalho ao executar o aplicativo Go em um contêiner do Docker. Estou aprendendo golang e queria adicionar um pequeno recurso a uma biblioteca que estou usando quando tive essa dor de cabeça ao testá-lo antes de criar um Pull Request.
Joakim
6

Se o seu fork for apenas temporário (ou seja, você pretende que ele seja mesclado), faça o seu desenvolvimento in situ, por exemplo, em $GOPATH/src/launchpad.net/goamz.

Em seguida, você usa os recursos do sistema de controle de versão (por exemplo git remote) para tornar o repositório upstream o seu repositório, em vez do original.

Torna mais difícil para outras pessoas usarem seu repositório, go getmas muito mais fácil para ele ser integrado ao upstream.

Na verdade, tenho um repositório para goamz no lp:~nick-craig-wood/goamz/goamzqual desenvolvo exatamente dessa forma. Talvez o autor o mescle um dia!

Nick Craig-Wood
fonte
1
Só para entender as implicações de fazer isso, se eu seguisse esse caminho, quando alguém faz um a go getpartir do meu repo, todas as minhas declarações de importação ainda refletirão github.com/original_authore, portanto, serão quebradas ... correto?
parker.sikand
@ parker.sikand sim, está correto. Essa técnica é melhor para as coisas que você pretende mesclar upstream, não para ir e usá-las. Se você pretende bifurcar o pacote permanentemente, use a técnica da outra resposta.
Nick Craig-Wood,
4

Esta é uma maneira de fazer isso funcionar para todos:

Use o github para fazer um fork de "my / repo" (apenas um exemplo):

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 tornar o código melhor:

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

Por quê? Isso permite que você tenha seu repo com o qual todos possam go gettrabalhar. Também permite manter e aprimorar um branch que é bom para uma solicitação pull. Não incha o git com "fornecedor", preserva a história e as ferramentas de construção podem dar sentido a isso.

user1212212
fonte
Correção leve: execute github.com/golang/tools/cmd/gomvpkg/main.go e este comando move o .git, então salve-o em outro lugar e restaure-o depois.
user1212212
também é possível usar o plugin mvn-golang que faz alguma automação no processamento de dependências como no exemplo github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/…
Igor Maznitsa
3

A resposta para isso é que se você bifurcar um repositório com vários pacotes, precisará renomear todos os caminhos de importação relevantes. Isso é muito bom, já que você fez um fork de todos os pacotes e os caminhos de importação devem refletir isso.

Jeremy Wall
fonte
3
Gastei mais tempo do que gostaria de admitir diagnosticar isso em minha primeira contribuição para um projeto Go. "Todos os testes passam, incluindo os que escrevi para testar exaustivamente novas funcionalidades. O que há de errado ?!" Você está ciente de qualquer ferramenta disponível para facilitar este ponto de tropeço para iniciantes?
Sage Mitchell
3
Depois de descobrir que era fácil de resolver usando find, xargse sed, mas ajudaria a ter um fluxo de trabalho sem problemas que funcione de forma consistente para todos.
Sage Mitchell
@JakeMitchell gomvpkgpode fazer a renomeação mais fácil / melhor. go get golang.org/x/tools/cmd/gomvpkgentão gomvpkg -help.
Dave C de
3
Esta resposta me parece completamente impraticável. Remover arquivos de um projeto bifurcado, isso é loucura? O que você faz quando cria uma solicitação pull? A resposta de Ivan Rave parece uma solução muito melhor para mim.
Ivan P
8
Ainda é assim que Go-lang está funcionando? Isso é tão insano, que não é engraçado ... Seja amigável com o upstream ou com o downstream, mas não ambos. É uma grande falha de design na minha opinião não tão humilde, provavelmente feito por pessoas que não colaboram muito em projetos cruzados. #FAIL #GOLANG
Niclas Hedhman
1

Para automatizar esse processo, escrevi um pequeno script. Você pode encontrar mais detalhes no meu blog para adicionar um comando como "gofork" ao seu 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
heralight
fonte
Deve golangser alterado para a goforklinha 4?
Dan Tenenbaum
bem visto! consertar!
heralight
1

Use venda e submódulos juntos

  1. Bifurque a lib no github (go-mssqldb neste caso)
  2. Adicione um submódulo que clona seu fork em sua pasta vendor, mas tem o caminho do repositório upstream
  3. Atualize suas importinstruções em seu código-fonte para apontar para a pasta do fornecedor (sem incluir o vendor/prefixo). Ex vendor/bob/lib=>import "bob/lib"

Por exemplo

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

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

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

Por quê

Isso resolve todos os problemas que ouvi e deparei ao tentar descobrir sozinho.

  • Refs de pacotes internos na lib agora funcionam porque o caminho não foi alterado do upstream
  • Uma nova verificação do seu projeto funciona porque o sistema de submódulo o obtém de seu fork no commit correto, mas no caminho da pasta upstream
  • Você não precisa saber hackear manualmente os caminhos ou mexer com as ferramentas de trabalho.

Mais informações

Tim Abell
fonte
0

em seu Gopkg.tomlarquivo adicione estes blocos abaixo

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

Portanto, ele usará o bifurcado project2no lugar degithub.com/globalsign/mgo

msonowal
fonte
O Gopkg.tomlarquivo é usado apenas depquando esta questão não menciona nada. Os novos projetos Go devem usar módulos Go (e os projetos baseados em dep existentes da IMO também devem migrar).
Dave C de
Eu não sabia sobre esse recurso de dep, e sua resposta certamente me ajudou :)
Veger
0

Você pode usar o comando go get -fpara obter um repositório bifurcado

kevin
fonte