こんにちは、教育系エンジニアのひらまつ(@hiramatsuu)です。
書籍「ゼロからわかる Linuxコマンド200本ノック(技術評論社)」の著者。Udemy受講者8万人。
プログラミング教育をメインに活動するエンジニアとして、動画教材の作成・技術書の執筆・学習アプリの開発などを行なっています(詳しくはこちら)。
本記事では、Dart・Flutter開発において、lockfile(pubspec.lock)をGitなどのバージョン管理システムにコミットするべきか?について解説します。
タイトルの「lockfileはコミットすべきか?」という問いに、自信を持って回答できない方に、役に立つ記事になっているかと思います。
まずは結論
パッケージの種類によって、方針は異なる。
- アプリケーションパッケージのlockfileは、コミットするべき。
- 一方で、通常のパッケージのlockfileは、コミットすべきではない。
lockfileとは何か
pubspec.lockという名前のファイルを「lockfile」と呼ぶこともある。
lockfileは、pubspec.yamlに記載された情報を元にして、dart pub getなどを実行した時に生成される、依存パッケージの具体的なバージョンを記載したファイル。つまり「あなたのパッケージが依存しているパッケージの、具体的なバージョンのリスト」になるのが、lockfile。
pubspec.yamlとpubspec.lockについて、より詳しくは「なぜpubspec.yamlとpubspec.lockの2つが必要なのか?【Dart・Flutter】」を参照。
コミットすべきでないファイル
- そもそもなぜ、ファイルやディレクトリをGitリポジトリにコミットする必要があるのかというと、後から、特定のバージョンを完全に再現できるようにするため。1
- ソフトウェア開発には不確実性がつきものであるので、すぐに任意のバージョンに戻れるようにしておくことで、安全にソフトウェアを変更できるようになる。2
- 逆に言えば、コミットせずとも任意のバージョンの状態を復元できるのであれば、コミットする必要はない。むしろ、不要なファイルをコミットすることが、生産性の妨げになったり、マシンの設定に関する詳細を公開することによって、セキュリティ上の問題を引き起こす可能性もある。
- なので、プロジェクトの構成要素から「生成されるファイル」については、その他の構成要素のファイルから再生成できるので、コミットする必要はない。
- つまり、コミットすべきかどうか?の方針としては、「生成されたファイルは、一切コミットしない」が基本になる。
- 注意点として、これはあくまでも、ソースコードリポジトリにおける話であり、デプロイすべきファイルについて論じたものではない。コミットするべきではないが、デプロイした方がよいファイルもある。
コミットしないファイルの指定方法
- プロジェクトに固有の、コミットしないファイルを指定するには、プロジェクトの最上位ディレクトリに、「.gitignore」ファイルを配置して、その中にコミットしないファイルをパターンで記載する。
- 複数のプロジェクトにまたがるような、ワークフロー・セットアップに固有の、コミット不要ファイルの指定には、「.gitignore_global」などのglobal ignore fileを使う。3例えば、macOSで開発しているなら、あらゆるプロジェクトで「.DS_store」はコミット不要なので、.gitignore_globalに記載する。
- DartやFlutterの開発においては、以下のようなファイル・ディレクトリを、.gitignoreなどに記載することになる。
pub package managerによって作成されるファイルやディレクトリ
.dart_tool/
build/
pubspec.lock # Except for application packages
dart docコマンドによって、ドキュメンテーションコメントから作成されたAPIのドキュメント
doc/api/
開発環境によって作成されたファイルやディレクトリ。これらは、global ignore fileに記載する方が望ましい。
# IntelliJ
*.iml
*.ipr
*.iws
.idea/
# Mac
.DS_Store
なぜアプリケーションパッケージのlockfileはコミットすべきなのか?
- ここまでの話を聞くと、pubspec.yamlから生成されるlockfile(pubspec.lock)をコミットする必要は無いように思えるが、アプリケーションパッケージの場合は話が別。
- アプリケーションパッケージ(application package)とは、Flutterアプリのような、他のパッケージから依存されないパッケージのこと。アプリケーションパッケージは、エンドユーザーから直接利用される。
- アプリケーションパッケージでは、特定のバージョンのアプリの状態を、他の環境でも完璧に再現できる必要がある。例えば、開発環境と本番環境の状態を一致させたり、開発者間で利用するバージョンを一致させたりなど。そうしないと、バグが再現できないなど、バージョンの不一致による問題が生じる。なので、lockfileをコミットすることで、具体的なバージョンを共有した方が良い。
- 一方で、通常のパッケージにおいては、単独で使われることは基本的になく、他のパッケージと組み合わせてうまく動作することが必要。つまり、どのパッケージと組み合わせられるかで、どのバージョンに依存するかが決まるので、lockfileによるバージョンの固定は用途に沿わず、コミット不要。
その他の情報
Flutter開発についての、他の記事はこちらを参照。