在Go中使用forked包导入

在Go中使用forked包导入,go,Go,假设您在github.com/someone/repo上有一个存储库,然后将它转到github.com/you/repo。你想用你的叉子而不是主回购,所以你做了一个 go get github.com/you/repo 现在,此repo中的所有导入路径都将“断开”,这意味着,如果存储库中有多个包通过绝对URL相互引用,它们将引用源,而不是fork 有没有更好的方法手动将其克隆到正确的路径 git clone git@github.com:you/repo.git $GOPATH/src/git

假设您在
github.com/someone/repo
上有一个存储库,然后将它转到
github.com/you/repo
。你想用你的叉子而不是主回购,所以你做了一个

go get github.com/you/repo
现在,此repo中的所有导入路径都将“断开”,这意味着,如果存储库中有多个包通过绝对URL相互引用,它们将引用源,而不是fork

有没有更好的方法手动将其克隆到正确的路径

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

对此的答案是,如果您用多个包分叉回购,则需要重命名所有相关的导入路径。这在很大程度上是一件好事,因为您已经分叉了所有这些包,导入路径应该反映这一点。

如果您的分叉只是临时的(即您打算将其合并),那么只需在原地进行开发,例如在
$GOPATH/src/launchpad.net/goamz中

然后,使用版本控制系统的功能(例如
git remote
)使上游存储库成为您的存储库,而不是原始存储库

这使得其他人使用您的存储库时更难使用
go-get
,但更容易将其集成到上游

事实上,我在
lp:~nick craig wood/goamz/goamz
上有一个goamz的存储库,我就是这样开发的。也许有一天作者会合并它

处理拉取请求
  • 将存储库
    github.com/someone/repo
    转移到
    github.com/you/repo
  • 下载原始代码:
    获取github.com/someone/repo
  • 在那里:
    cd“$(go env GOPATH)/src”/github.com/someone/repo
  • 启用上载到您的fork:
    git remote add myforkhttps://github.com/you/repo.git
  • 将您的更改上载到您的回购:
    git push myfork

在项目中使用包的步骤

解决这个问题的一个方法是伊万·雷夫(Ivan Rave)提出的,还有——分叉法

另一个是绕过golang行为。当您
go-get
时,golang会以与存储库URI中相同的名称列出目录,这就是问题的根源

相反,如果您发布自己的
git clone
,则可以将存储库克隆到文件系统上,路径以原始存储库命名

假设原始存储库位于
github.com/awsome org/tool
中,并将其转移到
github.com/awome you/tool
,您可以:

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非常乐意继续使用这个存储库,实际上并不关心某个上层目录名为
awesome org
,而git remote名为
awesome you
awesome org
的所有导入都通过您刚刚创建的目录解析,该目录是您的本地工作集

更多详细信息,请参阅我的博文:


编辑:固定目录路径

以下是一种适用于所有人的方法:

使用github分叉到“my/repo”(只是一个示例):

获取github.com/my/repo
cd~/go/src/github.com/my/repo
git分支增强
rm-rf。
去github.com/golang/tools/cmd/gomvpkg/…
gomvpkg~/go/src/github.com/my/repo
git提交
每次改进代码时重复以下步骤:

git commit
git checkout enhancement
git cherry-pick <<commit_id>>
git checkout master
git提交
git签出增强
吉特樱桃采摘
切换到主分支

为什么??这可以让您拥有任何
去获得的
都可以使用的回购协议。它还允许您维护和增强一个分支,该分支适合拉取请求。它不会用“供应商”来膨胀git,它保留了历史,构建工具可以理解它

为了自动化这个过程,我编写了一个小脚本。您可以在my上找到更多详细信息,以便在bash中添加类似“gofork”的命令

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
同时使用vendoring和子模块
  • 在github上分叉lib(在本例中,转到mssqldb)
  • 添加一个将您的分支克隆到您的分支中但具有上游回购路径的分支
  • 更新源代码中的
    import
    语句以指向供应商文件夹(不包括
    vendor/
    前缀)。例如,
    供应商/bob/lib
    =>
    导入“bob/lib”
  • 例如。 为什么? 这解决了我自己在尝试解决这个问题时听到和遇到的所有问题

    • 库中的内部包引用现在起作用,因为路径与上游的路径相同
    • 项目的新签出是有效的,因为子模块系统在正确的提交位置(但在上游文件夹路径)从您的fork获取它
    • 您不必知道如何手动破解路径或弄乱go工具
    更多信息
    如果您正在使用。你可以使用指令

    replace
    指令允许您提供另一个可能需要的导入路径 是位于VCS(GitHub或其他地方)或您的计算机上的另一个模块 具有相对或绝对文件路径的本地文件系统。新进口 使用
    replace
    指令的路径,无需更新 在实际源代码中导入路径

    因此,您可以在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
    
    其中,
    v3.2.1
    是回购协议上的标签。也可以通过CLI完成

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

    Gopkg.toml
    文件中,在下面添加这些块

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

    因此,它将使用forked
    project2
    代替github.com/globalsign/mgo

    您可以使用命令
    go get-f
    获得forked repo

    而不是克隆到特定位置,您可以在任何地方进行克隆。 然后,您可以运行这样的命令,以便参考本地版本:

    go mod edit -replace github.com/owner/repo=../repo
    

    新fork中的任何导入路径都不会中断,因为在进行fork之前,这些路径尚未中断。很抱歉,让您失望,但事实并非如此。如果子包通过其绝对url在导入中引用,则此导入将在fork中中断(或至少引用错误的包)。例如。它有内部参考
    [[constraint]]
      name = "github.com/globalsign/mgo"
      branch = "master"
      source = "github.com/myfork/project2"
    
    go mod edit -replace github.com/owner/repo=../repo