uvで依存パッケージを更新する方法:個別更新、バージョン制約、uv.lock、ロールバック

uv syncでパッケージが更新されない理由を解説。uv lock --upgrade-package、uv addのバージョン制約、--lockedと--frozenの違い、更新後の検証とロールバックを具体例で紹介します。

uvプロジェクトの依存パッケージを1つ更新するには、まず uv lock --upgrade-package 包名 でロックファイルを更新し、次に uv sync --locked でインストールして検証します。宣言されたバージョン範囲に更新先が含まれない場合は、先に pyproject.toml の制約を変更する必要があります。

よくある誤解は「環境を同期する」と「最新版を探す」を同じ操作だと考えることです。uv sync を実行してもパッケージが変わらない場合、uvは既存のロックファイルに従っていることが多いです。

この記事は、すでに pyproject.toml があるPythonプロジェクトを対象としています。例はPowerShellですが、主要なuvコマンドはLinuxとmacOSでも使えます。 requestsとpytestを使うため、モデルAPIに接続せず、独立した練習用ディレクトリで検証できます。 ドキュメントの確認日は2026年10月11日です。特定のAIプロジェクトについて、更新後の互換性を検証した記事ではありません。

何を更新したいのかを区別する

「uvを更新する」という言葉は、3種類の異なる対象を指すことがあります。 最初に対象を確認すれば、ツールを更新したのにプロジェクトの依存関係が変わらない、といった混乱を避けられます。

対象 よく使う操作 主な影響
uv本体 元のインストール方法に従ってuvを更新 パッケージ管理ツールのバージョン
プロジェクトの依存パッケージ1つ uv lock --upgrade-package requests ロックファイルの依存関係の解決結果
許可する依存バージョン範囲 uv add "requests>=2.32,<3" プロジェクトの宣言、ロックファイル、環境
プロジェクトの全依存パッケージ uv lock --upgrade 更新可能なロック済み依存パッケージ全体
uv toolでインストールしたツール uv tool upgrade 工具名 そのツール専用の分離環境

プロジェクト内のrequestsを更新するために uv tool upgrade を使わないでください。 uv本体だけを更新しても、.venv 内のパッケージが自動で新しくなるわけではありません。 ツールのインストールとプロジェクトの依存関係は管理範囲が異なります。詳しくは uvのツールガイドを参照してください。

pyproject.toml、uv.lock、.venvの役割

依存関係の変更には、プロジェクトが許可するバージョン、解決処理が選ぶバージョン、現在のマシンに実際に入っているバージョン、という3つの観点があります。

ファイルまたはディレクトリ 役割 Gitにコミットするか
pyproject.toml 直接依存と許可する範囲を宣言 はい
uv.lock 正確な解決結果を保存 はい
.python-version プロジェクトで選択したPythonバージョンを記録 通常はする
.venv 現在のマシンに構築された環境 いいえ

たとえば、次のように宣言されているとします。

1
2
3
4
5
6
7
[project]
name = "dependency-demo"
version = "0.1.0"
requires-python = ">=3.12,<3.13"
dependencies = [
    "requests>=2.31,<3",
]

この設定は、requestsに一定のバージョン範囲を許可しています。 実行のたびに、その範囲内の最新版をインストールするよう求めているわけではありません。

uv.lock が条件を満たすバージョンをすでに固定していれば、通常の同期ではそのバージョンを使い続けます。 これにより「昨日は動いたのに、今日インストールし直したら壊れた」という事態を減らせます。 仕組みは ロックと同期のドキュメントに説明されています。

独立したディレクトリで個別更新を試す

まず、ツールが使えることを確認します。

1
2
uv --version
git --version

作業中のリポジトリに練習用ファイルを書き込まないよう、まだ存在しないディレクトリ名を選んでください。 以下ではスクリプト用のプロジェクトを使い、Pythonパッケージのビルドバックエンドは設定しません。

1
2
3
4
5
6
uv init --bare --python 3.12 uv-update-demo
Set-Location uv-update-demo
uv python pin 3.12
uv add "requests>=2.31,<3"
uv add --dev pytest
uv sync --locked

必要なPythonがローカルにない場合、uvがインタープリターをダウンロードすることがあります。 ネットワークが制限されている環境では、依存関係の競合を疑う前に、ダウンロードやインタープリター検出の問題を解決してください。 Pythonの選択規則は 公式のインタープリタードキュメントを参照してください。

main.py を作成します。

1
2
3
4
5
6
7
from importlib.metadata import version
import requests

request = requests.Request("GET", "https://example.com/").prepare()
print("requests:", version("requests"))
print("method:", request.method)
print("url:", request.url)

このコードはリクエストを組み立てるだけで、ネットワークへ送信しません。 パッケージをインポートできるかを確認し、現在の環境に実際にインストールされたバージョンを表示します。

1
2
uv run --locked python main.py
uv tree --locked

続いて、練習用の基準状態を記録します。

1
2
3
4
git init
git status --short
git add pyproject.toml uv.lock .python-version main.py
git commit -m "Record dependency baseline"

コミット前に .venv がステージされていないことを確認してください。 Gitのユーザー情報をまだ設定していない場合は、ひとまずファイルのコピーを保存できます。後述のGitによるロールバックには、既存のコミットが必要です。

1つのパッケージを更新し、差分を確認する

先ほどのプロジェクトディレクトリで実行します。

1
2
3
4
uv lock --upgrade-package requests
git diff -- uv.lock
uv sync --locked
uv run --locked python main.py

解決処理とインストールを分けることで、作業環境を変更する前にロックファイルの差分を確認できます。 一度に実行したい場合は uv sync --upgrade-package requests も使えます。

「個別更新」は、そのパッケージを更新対象にするという意味です。ロックファイルの変更が1項目だけになる保証はありません。 新しいバージョンが異なる間接依存を必要とする場合、リゾルバーはプロジェクト全体の条件を満たす組み合わせを探す必要があります。

差分では、次の点を確認します。

  • requests自体が変わったか。
  • 間接依存が追加または削除されたか。
  • ダウンロード元がプロジェクトの想定どおりか。
  • 別の制約によって対象パッケージが元のバージョンに留まっていないか。

作成したばかりの練習用プロジェクトでは、すでに現在利用可能なバージョンが選ばれていることが多いです。 そのため、再度更新しても差分がないことは正常であり、コマンドの失敗とは限りません。

インストール結果の確認には、プロジェクトのインタープリターを使います。

1
2
uv run --locked python -c "import sys; print(sys.executable)"
uv run --locked python -c "from importlib.metadata import version; print(version('requests'))"

最初の出力はプロジェクト環境内のパスを指しているはずです。 エディターが別のバージョンを表示する場合、まず選択中のPythonパスを確認してください。

更新しても古いバージョンのままになる理由

プロジェクトに次の宣言があるとします。

1
2
3
dependencies = [
    "requests==2.31.0",
]

完全一致の制約では、このバージョンだけが許可されます。 --upgrade-package がプロジェクトの宣言を無視することはありません。

互換性を評価したうえで後続バージョンを許可すると決めた場合は、範囲を明示的に変更します。

1
2
3
uv add "requests>=2.32,<3"
git diff -- pyproject.toml uv.lock
uv run --locked python main.py

uv add は既定で宣言、ロックファイル、環境を更新するため、この時点で新しいパッケージがインストールされる可能性があります。 読み取り専用の問い合わせだと考えず、独立したブランチで実行してください。

特定のバージョンだけを評価する場合は、そのバージョンを完全一致で宣言してからテストします。 解決を成功させるためだけに上限をすべて削除しないでください。既存の上限は、既知の互換性の境界を表している可能性があります。

依存バージョンの範囲は、ほかのパッケージ、Pythonバージョン、プラットフォーム条件にも制限されます。 競合が発生したら、解決エラーから矛盾する要件を特定してください。 宣言の変更方法や依存グループは 依存関係管理のドキュメントを参照してください。

全体更新は独立した保守作業として行う

プロジェクト全体を更新するコマンドは次のとおりです。

1
2
3
4
uv lock --upgrade
git diff --stat
git diff -- uv.lock
uv sync --locked

全体更新は依存関係の保守には適していますが、ページの文章だけを変更するコミットに混ぜるのは避けましょう。 変更が大きいほど、問題が発生したときに原因のパッケージを特定しにくくなります。

まずアプリケーションの依存パッケージを1つ更新して受け入れ確認を行い、開発ツールは別に更新することを勧めます。 ネイティブ拡張、GPUランタイム、モデル推論バックエンドを持つプロジェクトでは、システムライブラリやドライバーの要件も確認してください。 ロックファイルはパッケージの解決結果を記録しますが、実機での動作確認を代替するものではありません。

–lockedと–frozenの使い分け

どちらもデプロイコマンドでよく使われますが、確認内容が異なります。

コマンド 動作 用途
uv lock --check ロックファイルが宣言と一致するか確認 コミット前の確認
uv sync --locked ロックファイルが最新の宣言と一致することを要求して同期 デプロイと環境の再現
uv run --locked python main.py ロックファイルが最新の宣言と一致することを要求して実行 日常の検証
uv sync --frozen 最新状態かの確認を省き、既存のロックファイルを使用 別の手順でロックファイルを検証済みのフロー

依存宣言を変更してロックファイルの更新を忘れた場合、--locked が不一致の発見に役立ちます。 --frozen で確認を省いても、今回の宣言が反映されたことにはなりません。

環境のクリーンアップにも注意が必要です。uv sync は既定で厳密に同期し、ロックファイルにないパッケージを削除します。 そのため、.venv に手動で一時インストールしたデバッグ用パッケージは、次回の同期で消えることがあります。 残すべき開発ツールは uv add --dev で宣言してください。

更新後は小さなテストで重要な動作を確認する

test_main.py を作成します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import requests


def test_prepare_request_keeps_query_parameter():
    prepared = requests.Request(
        "GET",
        "https://example.com/search",
        params={"q": "hello world"},
    ).prepare()
    assert prepared.method == "GET"
    assert prepared.url == "https://example.com/search?q=hello+world"

実行します。

1
2
3
4
uv lock --check
uv run --locked pytest -q
uv run --locked python main.py
git diff --check

このテストが確認するのは、リクエストパラメーターのエンコードという具体的な動作です。 ネットワーク接続、プロキシ、TLS、アプリケーションのAPIが正常であることまでは証明できません。 実際のプロジェクトでは、文書解析結果、データベースの読み書き、APIレスポンス構造など、独自の重要な処理も検証してください。

プロジェクトで MinerUによる文書解析を使っている場合、固定のPDFを選び、更新前後のページ数、表、画像参照を比較できます。 小さなサンプルを回帰テストの入力として残すほうが、import の成功だけを確認するより判断材料になります。

更新に失敗した場合の復旧

最初にエラーログと差分を保存し、今回の更新とは無関係な作業がないか確認します。 以下のコマンドは、この2つのファイルの未コミット変更を破棄します。変更がすべて今回の更新に属する場合だけ使ってください。

1
2
3
4
git diff -- pyproject.toml uv.lock
git restore --source=HEAD -- pyproject.toml uv.lock
uv sync --locked
uv run --locked pytest -q

宣言とロックファイルを同時に戻すことで、両者の不一致を防げます。 同期後はテストを再実行し、ファイルが同じに見えるだけでなく、動作する状態に戻ったことを確認してください。

更新をすでにコミットしている場合は、動作が確認できているコミットを特定し、対応するファイルを復元するか、更新コミットを取り消します。 同僚の .venv をそのままコピーしないでください。環境パス、プラットフォーム用バイナリ、インタープリターのバージョンが異なる可能性があります。

依存関係のロールバックでは、データベースのマイグレーションやプログラム実行後のデータ変更は自動で元に戻りません。 データ形式に関わる更新では、アプリケーション固有のバックアップと復旧手順が必要です。

requirements.txtしかない場合

requirementsベースの運用を続けるのか、uvプロジェクトへ正式に移行するのかを先に決めてください。 この2つの目的を、1つの更新コマンドで同時に達成しようとしないことが大切です。

既存の運用を維持する場合は、別の仮想環境にインストールできます。

1
2
uv venv
uv pip install -r requirements.txt

requirementsでバージョンが完全に固定されている場合、このインストールコマンドは制約を解除しません。 プロジェクト方式へ移行する場合は、移行用ブランチでプロジェクトを初期化し、依存関係を取り込みます。

1
2
3
uv init --bare
uv add -r requirements.txt
uv lock --check

pip freeze で生成したファイルを取り込むと、間接依存まで直接依存の宣言になることがあります。 移行後は、アプリケーションが実際に使うパッケージと、ほかのパッケージに付随する依存関係を区別してください。 プライベートインデックス、編集可能インストール、プラットフォーム条件は別途確認が必要です。公式移行ガイドを参照してください。

pipを使うデプロイフロー向けに依存関係を出力する

プロジェクト全体をすぐにuvへ切り替えられない場合は、ロックファイルからエクスポートできます。

1
uv export --locked --format requirements.txt --no-dev --output-file requirements.txt

このファイルは、ロックファイルから生成される成果物として扱ってください。 依存関係を変更したら、プロジェクトとロックファイルを更新してから再出力し、2つのバージョン一覧を手作業で管理しないようにします。

このサンプルプロジェクトは自身をパッケージ化していません。インストール可能なアプリケーションでは、出力にプロジェクト自体やローカルパス参照が含まれていないかも確認してください。 デプロイ先には対応するソースコードが必要です。requirementsだけコピーすれば十分とは限りません。 オプションは 公式エクスポートドキュメントを参照してください。

よくある問題の切り分け

症状 最初に確認する点 対処
sync後もバージョンが変わらない ロックファイルに使用可能なバージョンがあるか 個別更新を明示的に実行
upgrade後も古いまま 完全一致の制約や他パッケージの制限 解決結果を読み、評価後に宣言を変更
ターミナルでは成功し、エディターではインポート失敗 Pythonインタープリターのパス プロジェクトの .venv を選択
ロックファイルは正しいがインストール失敗 ネットワーク、証明書、ディスク、プラットフォーム用wheel エラーを保存し、ダウンロードとビルドのどちらで失敗したか確認
デプロイでロックファイルが古いと表示 宣言とロックファイルを一緒にコミットしたか 開発ブランチで更新して検証
同期後に一時ツールが消える dev依存として宣言されているか uv add --dev で管理

依存関係の更新が完了したと言えるのは、宣言が明確で、ロックファイルが一致し、インストール環境が正しく、重要なアプリケーション動作が検証を通過したときです。 更新対象を決めたら、まず1つのパッケージから始め、差分と復旧手段を残してください。