はじめに
この記事は、GoのリポジトリをGitHubでフォークして開発しようとした際に「import文のパスがずれてエラーが出る」「ローカルで動かない」という問題に直面した方を対象としています。
読むことで、fork先のリポジトリで正しくimportパスを解決する方法、特にgo.modのreplaceディレクティブを使ったローカル開発のベストプラクティスがわかります。clone直後で動かない原因と、それを解決するための具体的な手順を解説します。
前提知識
- Goの基本的な文法とプロジェクトのビルド方法
- GitHubでリポジトリをフォーク・クローンする操作
go.modが依存関係を管理していることの理解
forkしてみたらimportが解決できない!
Go製のOSSにプルリクエストを送ろうと、GitHub上でフォークしてcloneしました。ところがgo runやgo buildを実行すると、以下のようなエラーが出てしまいます。
main.go:5:2: github.com/original/repo/pkg/logger: no required module provides package github.com/original/repo/pkg/logger
要するに、「import文が元リポジトリのパスを指したままで、フォーク先のコードを参照できていない」という事象です。GoのmoduleシステムはimportパスとGitHubの物理パスを一致させる前提にあるため、フォーク先ではパスがずれてしまいます。
go.modのreplaceでローカルパスを騙す
この問題を解決する最も確実で簡潔な方法が、go.modにreplaceディレクティブを追加することです。以下、手順を紹介します。
ステップ1:フォーク&clone
- GitHubで対象リポジトリをフォーク
- フォーク先のURLを自分の環境にclone
Bashgit clone https://github.com/YOUR_NAME/repo.git cd repo
ステップ2:go.modにreplaceを追加
プロジェクトルートのgo.modを開き、最終行に以下を追加します。
Gomodule github.com/original/repo go 1.22 require ( github.com/some/dependency v1.2.3 ) replace github.com/original/repo => ./
- 左辺:元リポジトリのimportパス
- 右辺:
./で現在のディレクトリ(フォーク先)を指す
これでgo run/go buildが通るようになります。
ステップ3:replaceを外してCIを通す(オプション)
プルリク作成時にCIが動く場合、go.modにreplaceが残っているとCI側でも同じパス解決が必要です。CIを通したい場合は、プッシュ前に以下のどちらかを選びます。
- 一時的に
replace行をコメントアウト - CI上でも同様のreplace処理を施す(
sedや環境変数で)
Bash# 例:コメントアウトしてプッシュ sed -i 's/^replace/# replace/' go.mod git add go.mod git commit -m "fix: remove replace for CI" git push origin feature-branch
ハマった点:replaceの書き方を間違えると無視される
最初replaceを以下のように書いてしまい、効いているのかどうか分からず困りました。
Go// 間違い例 replace ( github.com/original/repo v0.0.0 => ./ )
replaceは「モジュールパス => ローカルパス」のみでバージョンを書くと無視されます。正しくは:
Go// 正しい例 replace github.com/original/repo => ./
解決策:go listでreplaceが効いているか確認
以下コマンドで、replaceが効いているか即座に検証できます。
Bashgo list -m all | grep repo # => github.com/original/repo => ./ (replace)
=>の右が./になっていれば成功です。
まとめ
本記事では、GitHubでフォークしたGoリポジトリでimportパスが解決できない問題を、go.modのreplaceディレクティブで解決する方法を解説しました。
- フォーク直後はimportパスが元リポジトリを指しているためビルドできない
replace github.com/original/repo => ./を追加すればローカルで解決- CIを通す場合は、replaceを外すかCI側でも同様の処理が必要
この手法を使えば、OSSに貢献する際の最初のハードルが一つ下がります。次回はgo.workを使った複数モジュールの管理方法について掘り下げていきます。
参考資料
