Git のエラー

Git の「would clobber existing tag」を修正する方法。

FluxGit ·

fetch が既存のローカルタグを別のオブジェクトに置き換えようとすると、Git は「would clobber existing tag」と表示します。両方のタグ参照を比較し、ローカルの参照を保存してください。そのタグだけを更新するのは、リモート側が正しいと確認できた場合です。

安全な対処手順

エラーに表示されたタグを特定します。ローカルとリモートのオブジェクト ID を比較し、ローカルにバックアップを作成します。リモート側が正しい場合に限り、確認したタグだけを強制 fetch してください。すべてのタグを強制更新したり、置き換えたタグをリモートへ push したりしないでください。

注釈付きタグには独自のオブジェクト ID があります。同じコミットを指していても、メッセージや署名が異なればタグオブジェクトは異なります。何が変わったか判断する前に、タグ参照と、そのタグをたどって得られる対象オブジェクトを比較してください。

1. タグを正確に指定して調べる

v1.2.3 をエラーに表示されたタグに、origin を対象のリモート名に置き換えてください。これらのコマンドは参照を変更しません。

git show-ref --verify refs/tags/v1.2.3
git rev-parse 'refs/tags/v1.2.3^{}'
git ls-remote --tags origin 'refs/tags/v1.2.3' 'refs/tags/v1.2.3^{}'

最初のコマンドはローカルのタグオブジェクト ID を表示します。次のコマンドは注釈付きタグをたどり、その対象オブジェクトを解決します。リモートの出力にはタグ参照が表示され、注釈付きタグの場合は対象を示す ^{} で終わる行も表示されます。

ここに示す完全な参照名を使ってください。v1.2.3 を前方一致で検索すると、v1.2.30 も含まれる可能性があります。リモートに該当するタグがない場合は、ここで止めてください。この手順を理由にローカルタグを削除してはいけません。

2. 元のローカル参照を保存する

何かを置き換える前に、復旧用のローカルタグを作成します。最後の空の引数は、バックアップ名がまだ使われていないことを条件にします。

git update-ref refs/tags/backup/v1.2.3 refs/tags/v1.2.3 ""
git rev-parse refs/tags/v1.2.3 refs/tags/backup/v1.2.3

2 つのオブジェクト ID が一致することを確認してください。注釈付きタグのメッセージや署名を含む、元のタグオブジェクトが保存されます。バックアップがすでに存在して作成に失敗した場合は、別の名前を選び、確認してから続けてください。

不一致の原因が解決するまでバックアップを残してください。push しない限りローカルにだけ存在します。この修正のために git push --tags を使わないでください。

3. 確認したタグだけを更新する

リモートのタグが正しく、バックアップが存在することを確認した場合にだけ実行してください。先頭の + は、このローカル参照だけの置き換えを許可します。

git fetch --no-tags --no-prune --no-prune-tags origin '+refs/tags/v1.2.3:refs/tags/v1.2.3'
git show-ref --verify refs/tags/v1.2.3
git rev-parse 'refs/tags/v1.2.3^{}'

--no-tags は他のタグの自動取得を無効にします。--no-prune と --no-prune-tags は、この fetch で設定済みの参照整理を無効にし、修正範囲が広がるのを防ぎます。ブランチやリモートタグを push したり、置き換えたりする操作ではありません。

取得したタグオブジェクトと対象オブジェクトを、先ほど調べたリモートの ID と比較してください。修正の途中でリモートが変わっていた場合は、リリースに使う前に止めて調べてください。バックアップは引き続き元のオブジェクトを指しています。

Git が更新を拒否する理由

Git 2.20 以降、fetch で既存の refs/tags/* 参照を置き換えるには、明示的な強制指定が必要です。2 つの対象コミットに祖先と子孫の関係があっても、この規則は適用されます。タグの更新には、ブランチの fast-forward 規則は使われません。

ローカルタグが正しいリリースを指しているなら、そのまま残してメンテナーと調整してください。公開済みのリモートタグを置き換えると、他の利用者が同じバージョン名で受け取る内容が変わります。

Git の公式リファレンス

リポジトリの状態を把握する

まず確認し、変更する参照を最小限に。

FluxGit は、タグ、リポジトリの状態確認、確認付きの操作を macOS、Windows、Linux 向けのデスクトップ Git クライアントにまとめます。参照を変更する前に、上のコマンドでこの Git エラーを調べてください。

関連資料(英語)