V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
zhwguest
V2EX  ›  Go 编程语言

请教大神一个 golang 中依赖模块 fork 修改使用的问题

  •  
  •   zhwguest · 331 天前 · 1016 次点击
    这是一个创建于 331 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设我的项目中 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 ?

    11 条回复    2023-12-22 15:19:39 +08:00
    kuanat
        1
    kuanat  
       331 天前   ❤️ 1
    用你方法一的思路,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 做了多次修改,就只能升版本或者换分支了。
    javalaw2010
        2
    javalaw2010  
       331 天前
    如果你的 fork 打算 merge 到上游,用 replace ,如果你的改动比较私人,不希望或者不太可能合并到上游,就用/new/dep
    vultr
        3
    vultr  
       329 天前
    如果可以的话,最好是合并回上游。
    zhwguest
        4
    zhwguest  
    OP
       327 天前
    谢谢大家的帮助。
    @kuanat 衷心感谢,另外我还想问一下,如果我保持版本号不变,那么 tag 不是会冲突么?谢谢
    kuanat
        5
    kuanat  
       327 天前   ❤️ 1
    @zhwguest #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 的方式来唯一确定。
    zhwguest
        6
    zhwguest  
    OP
       323 天前
    @kuanat 明白了,非常感谢热心解答。
    zhwguest
        7
    zhwguest  
    OP
       322 天前
    @kuanat 关于 tag 的问题还想请教一下,比如上游 git 的版本是 1.2.3 ,我现在将其 tag 为 1.2.4 ,那下次上游 tag 升级为 1.2.4 的时候,我的 tag 不是和它冲突了么?所以是不是本身不建议 tag ?
    zhwguest
        8
    zhwguest  
    OP
       322 天前
    我如果不管 tag ,总是用最新的:

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

    这样好像是提示错误的。
    kuanat
        9
    kuanat  
       322 天前   ❤️ 1
    @zhwguest #8

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

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

    右边只有替换成本地 repo 的时候才可以不带版本。
    liaoyuan6666
        10
    liaoyuan6666  
       322 天前
    @zhwguest 要指定 hast 或版本的
    liaoyuan6666
        11
    liaoyuan6666  
       322 天前
    hash 打错了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   942 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:55 · PVG 05:55 · LAX 13:55 · JFK 16:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.