英文:
Update files in vendored library
问题
我需要对一个供应商库中的文件进行一些更改。
最好的方法是什么?
也许:
1. fork 仓库
2. 进行更改
3. 更新依赖以使用 fork
(4.) 向原始仓库提交 pull request
英文:
I need to make some changes to a file in one of the vendored libraries.
What is the best way to go about it?
Maybe:
1. fork repo
2. make changes
3. update dependencies to use fork
(4.) make pr to original repo
答案1
得分: 6
我建议你不要自己修改vendor
目录,除非是为了临时调试。通常情况下,今天的流程可能是以下这样的。
- 为了简单起见,在你工作时先删除现有的
vendor
目录。(稍后你会用你的更改重新构建它。)
$ rm -r ./vendor
- 将上游仓库(或上游仓库的你自己的分支)克隆到本地目录。(确保阅读上游维护者的许可证、
README
和/或贡献指南,以便了解他们的测试、代码审查等流程!)
$ git clone https://github.com/julian59189/somerepo
作为这一步的一部分,如果上游仓库还没有go.mod
文件,你可能需要添加一个。
$ pushd ./somerepo
$ go mod init example.com/somerepo
$ popd
- 在你的
go.mod
文件中添加一个replace
指令,将依赖项指向你的分支。(更多细节,请参阅开发和测试未发布模块代码。)
$ go mod edit -replace example.com/somerepo@someversion=./somerepo
- 在本地克隆中进行更改和测试,并将其推送到你的分支。记录提交哈希以备后用。
…
$ go test ./... example.com/somerepo/...
$ pushd ./somerepo
$ git commit -a
$ COMMIT=$(git rev-parse HEAD)
$ git push
$ popd
- 根据上游作者的说明,向上游提交一个PR(拉取请求)以进行更改。
- (可选)如果你预计PR需要一段时间才能合并,此时你可能希望更新
replace
指令,将其指向已发布的分支而不是本地克隆。
$ go mod edit -replace example.com/somerepo@someversion=github.com/julian59189/somerepo@$COMMIT
$ go mod tidy
现在,任何检出你的仓库并在你的模块内工作的人都将使用修复后的版本,即使他们重新运行go mod vendor
(例如,为了获取不同模块中的一个无关修复)。
- (可选)如果你使用
vendor
目录,请使用替换后的效果重新构建本地的vendor
目录,并提交更改。此时,你自己的模块已经修复,但是使用你的模块的人将看不到修复(因为你不是上游模块的权威所有者)。
$ go mod vendor
$ git add go.mod go.sum vendor
$ git commit
- 一旦上游PR合并,删除你的
replace
指令并更新到最新的上游版本。(如果上游作者尚未打标签发布,你可以使用伪版本,通过将特定的提交哈希传递给go get
而不是latest
来使用;参见使用存储库标识符获取特定提交。)
$ go mod edit -dropreplace=example.com/somerepo@someversion
$ go get -d example.com/somerepo@latest
$ go mod tidy
$ go mod vendor # 如果你想继续使用`vendor`目录。
$ git add go.mod go.sum vendor
$ git commit
英文:
I would advise not modifying the vendor
directory yourself except for temporary debugging. Instead, in general the process today would be something like the following.
- For the sake of simplicity, remove the existing
vendor
directory while you work. (You'll rebuild it later with your changes.)
$ rm -r ./vendor
- Clone the upstream repo (or your own fork of the upstream repo) to a local directory. (Be sure to read the upstream maintainer's license,
README
, and/or contributing guide so that you understand their process for testing, code review, etc.!)
$ git clone https://github.com/julian59189/somerepo
As part of this step, you may need to add a go.mod
file if the upstream repo doesn't already have one.
$ pushd ./somerepo
$ go mod init example.com/somerepo
$ popd
- Add a
replace
directive to yourgo.mod
file to point the dependency to the fork. (For more detail, see Developing and testing against unpublished module code.)
$ go mod edit -replace example.com/somerepo@someversion=./somerepo
- Make and test the change in your local clone, and push it to your fork. Record the commit hash for later use.
…
$ go test ./... example.com/somerepo/...
$ pushd ./somerepo
$ git commit -a
$ COMMIT=$(git rev-parse HEAD)
$ git push
$ popd
- Send an upstream PR for the change, following the upstream author's instructions.
- (optional) If you expect the PR to take a while to be merged, at this point you may want to update the
replace
directive to point to the published fork instead of the local clone.
$ go mod edit -replace example.com/somerepo@someversion=github.com/julian59189/somerepo@$COMMIT
$ go mod tidy
Now anyone who checks out your repo and works within your module will use the fixed version, even if they re-run go mod vendor
(for example, to pick up an unrelated fix in a different module).
- (optional) Rebuild your local
vendor
directory, if you use one, with the replacement in effect, and commit the changes. At this point, your own module itself is fixed, but nobody who uses your module will see the fix (because you are not the authoritative owner of the upstream module).
$ go mod vendor
$ git add go.mod go.sum vendor
$ git commit
- Once the upstream PR is merged, drop your
replace
directive and update to the latest upstream. (If the upstream author hasn't tagged a release yet, you can use a pseudo-version by passing a specific commit hash togo get
instead oflatest
; see Getting a specific commit using a repository identifier.)
$ go mod edit -dropreplace=example.com/somerepo@someversion
$ go get -d example.com/somerepo@latest
$ go mod tidy
$ go mod vendor # If you want to keep a vendor directory going forward.
$ git add go.mod go.sum vendor
$ git commit
答案2
得分: 2
不论许可证如何,从实际角度来看,这在很大程度上取决于具体情况。
- 如果这是一个影响你的生产环境的关键错误 -> 修改供应商可能是最快的方法,但主要缺点是每次更新库时都需要挑选修复补丁。
- 如果这只是一个“好事情”,或者在你的待办事项中没有被妥协 -> 提交PR将有益于你的项目和社区。此外,更新版本只需在
go.mod
文件中进行更改即可。 - 分叉是修改供应商的长路径,它具有所有缺点,还有一个额外的缺点:维护一个额外的代码库。
无论如何,避免与自由软件许可限制相关的问题是非常重要的。
英文:
Regardless of the license, from a pragmatic point of view it depends a lot on the circumstances.
- If it is a critical bug affecting your production -> modifying vendor is probably the fastest way but the main drawback is that the fix should be cherry-picked each time the library is updated.
- If is a nice to have thing or is not compromised in your backlog -> PR will benefit your project and also the community. Moreover, updating a version would be as easy as change it on the
go.mod
file. - Forking is the long path of modifying vendor, it has all drawbacks and one more: maintain an extra repository.
In any case, avoid license restrictions with FREE software LIBRE is quite important.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论