Golang Go语言中依赖模块 fork 修改使用的问题

发布于 1周前 作者 ionicwang 来自 Go语言

假设我的项目中 require 了一个第三方 github.com/old/dep 模块,依赖的版本是 v1.2.3 。

现在我对该依赖 fork 出来做了修改,放到 github.com/new/dep 上,然后我想依赖于新的模块。

不知道推荐的方法是什么?

方法 1:仍然 require github.com/old/dep v1.2.3 ,用 replace 将其替换到新的地址?那版本号怎么处理呢?毕竟我有了新的提交,打 tag 肯定不能是 v1.2.3 了,重新 tag 为 v1.2.4 ,这该如何写 replace 呢?以后不会混乱么?

方法 2:干脆和 github.com/old/dep 模块分离,直接在项目中 require github.com/new/dep 。但是这个项目中有很多源代码是直接 import 的 github.com/old/dep/xxx 。使用 gohack ?


Golang Go语言中依赖模块 fork 修改使用的问题

更多关于Golang Go语言中依赖模块 fork 修改使用的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

12 回复

用你方法一的思路,replace 是支持版本号映射的,比如

require github.com/old/dep v1.2.3 => github.com/new/dep v1.2.4

另外也可以 github.com/new/dep@dev 指定分支。

你说的方法二有个问题:就像你说的,如果它包含子模块,这些子模块还是会引用 /old/dep ,那 fork 出来需要修改的地方就非常多。

具体怎么做取决于 /new/dep 这个 fork 的定位。仅仅打个补丁,需要定期合并上游 /old/dep 那就用方法一。如果是要大刀阔斧另起炉灶,那就方法二吧。

关于版本号,我的建议是保持一致。就是你在 v1.2.3 上的改版,就用 v1.2.3 发布,特别是你仅仅要做个小改动的时候。不过这个事情不重要,你清楚对应的版本就可以了,而且几乎做不到一一对应。

另外这里要注意 go sum 机制,改版 /new/dep 发布之后 github.com/new/dep v1.2.3 校验信息会被 google 缓存。这个时候如果对 /new/dep 做了多次修改,就只能升版本或者换分支了。

更多关于Golang Go语言中依赖模块 fork 修改使用的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果你的 fork 打算 merge 到上游,用 replace ,如果你的改动比较私人,不希望或者不太可能合并到上游,就用/new/dep

如果可以的话,最好是合并回上游。

谢谢大家的帮助。
衷心感谢,另外我还想问一下,如果我保持版本号不变,那么 tag 不是会冲突么?谢谢

#4

可能之前没表达清楚,这里应该不存在冲突的。


比如说你一开始用的 /old/dep 依赖,那么在 go.mod 里面就会有

require github.com/old/dep v1.2.3

只要你不升级依赖,那么整个项目一直会用 /old/dep v1.2.3

然后你 fork 了 /new/dep 出来,并且给 /new/dep 打了版本 v1.2.3
这个时候增加一句

replace github.com/old/dep v1.2.3 => github.com/new/dep v1.2.3

就可以了。

假如 /old/dep 更新过后,你发现没有必要用 /new/dep 了,那就把上面的删掉,然后更新依赖到比如说 /new/dep v1.2.4 ,不管是 go get -u 还是手动修改 go.mod ,最终 go.mod 都会是

require github.com/old/dep v1.2.4

假如你还是要用 /new/dep ,不管你是继续在 /new/dep 上修改,还是合并了 /old/dep 的上游更新,然后打了 v1.2.4 的版本,只需要修改 replace 这一句变成

replace github.com/old/dep v1.2.3 => github.com/new/dep v1.2.4

但是 require 那一句还保持

require github.com/old/dep v1.2.3



也就是说,只要你不主动升级 /old/dep 的版本,那就只需要修改 replace 的目标版本。至于 /new/dep 怎么打版本 tag 是随意的。

之前说保持版本号一致只是应对两种场景,一种是 /new/dep 作为临时开发测试分支,有可能被 /old/dep 合并,当 /old/dep 更新之后又会回到 /old/dep 上面去。另一种是 /new/dep 是因为某些原因不可能被 /old/dep 合并,但是修改可以通过 patch 的方式自动化,上游 /old/dep 发布一个版本,下游 /new/dep 就发布一个对应的修改版。



默认情况下,github 的 fork 功能,是不带 tag 的,所以你可以在 fork 里面重新任意标记版本。假如你不想处理 tag 相关的事情,也可以完全不理会。这种情况下,replace 后面改成 /new/dep 就行了,go.sum 会用 v0.0.0-timestamp-commit_hash 的方式来唯一确定。

明白了,非常感谢热心解答。

关于 tag 的问题还想请教一下,比如上游 git 的版本是 1.2.3 ,我现在将其 tag 为 1.2.4 ,那下次上游 tag 升级为 1.2.4 的时候,我的 tag 不是和它冲突了么?所以是不是本身不建议 tag ?

我如果不管 tag ,总是用最新的:

replace github.com/old/dep v1.2.3 => github.com/new/dep

这样好像是提示错误的。

#8

git tag 是与 repo 相关的,/old/dep 和 /new/dep 是相互独立的,我不确定你说的冲突,只要同一个 repo 里面 tag 唯一就可以。

一般不建议 => 左边带版本,除非你的项目永远不升级依赖。如果左边带版本 v1.2.3 ,就代表只有这个特定版本会被替换,但是上游更新 v1.2.4 然后你 go get -u 升级了依赖,那 v1.2.3 的替换就失效了。不带版本就是所有版本都会替换。

右边只有替换成本地 repo 的时候才可以不带版本。

要指定 hast 或版本的

hash 打错了

在Go语言中,当你需要修改某个依赖的模块(通常是通过go get获取的第三方库)时,fork并修改是一个常见的做法。以下是一些步骤和建议,帮助你高效地完成这一过程:

  1. Fork原始仓库:在GitHub等平台上,将你需要修改的依赖库fork到你的个人或组织账户下。

  2. 克隆并修改:克隆你fork的仓库到本地,进行必要的修改。确保你的修改符合项目的编码风格和测试要求。

  3. 替换依赖:在你的Go项目中,使用replace指令在go.mod文件中替换原始依赖为你的fork版本。例如:

    replace example.com/original/module => github.com/yourusername/forked-module vX.Y.Z
    

    这里的vX.Y.Z应该是你fork的模块的版本号,或者可以使用伪版本号如v0.0.0-YYYYMMDDHHMMSS-abcdef123456来表示自定义的修改。

  4. 测试修改:在本地项目中运行测试,确保你的修改没有引入新的问题。

  5. 持续集成:如果你的项目使用CI/CD,确保CI/CD管道能够正确地从你的fork仓库中获取依赖。

  6. 贡献修改(可选):如果你的修改对原始项目有益,可以考虑向原始仓库提交PR,以便这些改进能被更多人使用。

注意,长期依赖fork版本的库可能会导致与上游的同步问题,因此建议定期检查并合并上游的更新。

回到顶部