Flutterのpubspeck.yamlにGithubのブランチを指定した場合はVerifiedコミットが取得される
何があったのか
纏めると以下です。
試したこと
Flutterでパッケージを使用する際はpackage.yamlに記述しますが、そこにGitHubのURLとブランチを指定することができます。例えば以下のようにreferenced_libraryというパッケージを参照しているとします。
dependencies:
flutter:
sdk: flutter
referenced_library:
git:
url: git@github.com:XXXXXX/referenced_library.git # URL
ref: main # ブランチ名
referenced_library側は、単純に文字列を返すだけの関数があるとします。
class Calculator {
String getMessage() => 'これは古いです。';
}
メインのアプリ側は、このreferenced_libraryのgetMessage()を呼び出した結果を画面に表示しています。

パッケージ側を更新
パッケージ側を更新し、getMessage()が返す文言が変わりました。
class Calculator {
- String getMessage() => 'これは古いです。';
+ String getMessage() => '変更しました。';
}
この状態で、メインのアプリ側でflutter pub getを実行してパッケージを更新しても、表示される文言は変わりませんでした。
キャッシュを削除してみた
古いキャッシュが残ったままになっているかもしれないと思い、flutter pub cache cleanを実行してキャッシュを削除しました。
❯ flutter pub cache clean
This will remove everything inside /Users/xxx/.pub-cache.
You will have to run `flutter pub get` again in each project.
Are you sure? (y/N)? y
Removing pub cache directory /Users/xxx/.pub-cache.
Deletion failed, path = '/Users/xxx/.pub-cache' (OS Error: Directory not empty, errno = 66)
Failed to update packages.
# エラーが出る場合は、再度実行する
❯ flutter pub cache clean
This will remove everything inside /Users/xxx/.pub-cache.
You will have to run `flutter pub get` again in each project.
Are you sure? (y/N)? y
Removing pub cache directory /Users/xxx/.pub-cache.
再度flutter pub get を実行する
キャッシュが削除されたので、再度flutter pub getでパッケージを取得するも、変わらず古い文言のままでした。
flutter pub get

なぜなのか
原因は、冒頭に書いた話ですが、最新のVerifiedコミットが取得されるからです。最新のVerifiedコミット以降に作られたコミットは無視されています。
Verifiedとは?
署名付きのコミットのことで、詳細は以下をご参照いただきたいのですが、要するにそのコミットって本当にその人がやったのか?というのを検証できるようにする仕組みのことです。
各コミットには誰がコミットしたかが表示されていますが、そもそもこれはローカルのgitconfigで設定できるので、他人の名前やメールアドレスを指定できてしまうからということのようです。

コミット履歴
- 最新の一つ前のコミット(eb05175)は、
getMessage()は'これは古いです。' ← Verified - 最新のコミット(094581e)は、
getMessage()は'変更しました。'
なので、最新ではなく一つ前のコミットが取得されていたため、画面には'これは古いです。'が表示されたままでした。
なんでVerifiedが付いたり付かなかったりするの?
コミットする際、明示的に指定しなければ署名は付きません。
ですが、GitHubのWebインターフェース上で操作した場合は自動的にGitHubが署名するようです。
今回の場合は、
- 最新の一つ前のコミット(eb05175)は、ブランチ切ってコード変更して、PR作ってmainにマージした。→ GitHubのWeb画面上で操作した
- 最新のコミットは、mainブランチから直接pushした。→ GitHubのWeb画面上で操作していない
という違いがあったため、このような事態に陥りました。

Web画面から操作した場合自動で署名される
解決
mainから再度ブランチを切って、PR作成→マージをすれば、最新コミットがVerifiedになりました。その状態でflutter pub getをすれば、ちゃんと変更後の文言が表示されました。
要するに、mainに直接pushせず、ちゃんとブランチ切ろうということですね。。そうしていれば通常問題になることはないはずです。
さらに探求
解決に至るまで、実はもう少し色々調査してまして、分かったことを記載します。
cacheの中身
まずキャッシュの保存場所は、~/.pub-cacheなのですが、その中の~/.pub-cache/git配下に、対象のリポジトリが丸々cloneされており、中のソースコードを開くと確かに変更前の状態でした。

で、よくよく見るとディレクトリ名にコミットID(ハッシュ値)そのものが付いていました。これで気がつきました。
pubspeck.lock
もう一個ハマったことがあって、それがpubspeck.lockです。このファイルは各パッケージの具体的なバージョンなどが記載されているファイルで、flutter pub getした際にpubspeck.lockに記載のバージョンがダウンロードされます。これがあるお陰で人に依って取得されるバージョンが異なるということを防ぐことができます。
で、私は上記で解決した際、結局GitHub上のブランチの操作が原因だったので、パッケージ自体を変更するつもりが無かったのでローカルの変更内容を全て破棄して元に戻してしまったんです。
そうすると、最新のコミットをVerifiedにしたにも関わらず、また古いコミットが取得されてしまいました。
pubspeck.lockにはバージョンだけでなく、以下のようにGitHubの場合はコミットID(ハッシュ値)が記載されていました。
referenced_library:
dependency: "direct main"
description:
path: "."
ref: main
resolved-ref: eb051756c94b51d7fdfdf9389fa2b0216bfc46f6 # コミットID
url: "git@github.com:XXX/referenced_library.git"
source: git
version: "0.0.1"
ローカルの編集内容を破棄して元に戻してしまったことで、コミットID(resolved-refの値)も古いコミットのIDに戻ってしまった、ということです。
flutter pub upgradeを実行するか、このファイル自体を削除してしまうと、(更新があれば)全パッケージが更新されてしまうので、更新したいパッケージの行だけを削除することで、そのパッケージだけを更新することができます。
pubspeck.yaml にコミットIDを指定することもできる
ちなみに、以下のようにpubspeck.yamlにブランチ名ではなくコミットIDを指定することもできます。
dependencies:
flutter:
sdk: flutter
referenced_library:
git:
url: git@github.com:XXXXXX/referenced_library.git # URL
ref: 094581e234a76a2e317df294ed0ce20042eb606d # コミットID
こうすると、Verifiedかどうかに関わらず、指定したコミットが取得されます。
当然、そのコミットに固定されることになりますが。
Discussion