web-dev-qa-db-ja.com

gitタグを再作成した後の「タグは既にリモートに存在します」エラー

次の手順を実行すると、次のエラーが表示されます。

To [email protected]:username/repo-name.git
 ! [rejected]        dev -> dev (already exists)
error: failed to Push some refs to '[email protected]:username/repo-name.git'
hint: Updates were rejected because the tag already exists in the remote.
  1. リポジトリを作成しました
  2. ローカルマシンにリポジトリをクローンしました。
  3. READMEファイルを変更し、変更をコミットしてコミットをプッシュしました。
  4. 作成されたタグdevgit tag dev
  5. プッシュされたタグ:git Push --tags
  6. READMEファイルを変更し、変更をコミットしてコミットをプッシュしました。
  7. タグdevを削除し、再度作成してタグをプッシュしました。

    git tag -d dev
    git tag dev
    git Push --tags
    

なんでこんなことが起こっているの?

私はMacにいます。 Linux(Ubuntu)を使用している私の友人には、この問題はありません。 git Push --tags -fを使用してタグの更新を強制できることは知っていますが、これは危険です(たとえば、ブランチではなくタグのみで誤ってコミットを書き換えるなど)。

129
Luca Boieru

編集、2016年11月24日:この回答は明らかに人気があるため、ここにメモを追加します。中央サーバー上のタグをreplaceした場合、oldタグ—既にタグを持っている中央サーバーリポジトリのクローンは、古いタグを保持することができます。そのため、これで方法がわかりますが、本当にwantしてください。すでに「間違った」タグを持っている全員を削除してtheir「間違ったタグ」を取得し、新しい「正しいタグ」に置き換える必要があります。 。

Git 2.10/2.11のテストでは、古いタグを保持することがgit fetchを実行するクライアントのデフォルトの動作であり、更新がgit fetch --tagsを実行するクライアントのデフォルトの動作であることが示されています。

(元の答えは次のとおりです。)


タグをプッシュするように要求すると、git Push --tagsは(プッシュ設定からのコミットやその他のオブジェクト、およびその他のref更新とともに)new-sha1 refs/tags/nameの形式の更新要求をリモートに送信します。 (まあ、それは多くを送信します:各タグのためのそれらの1つ。)

更新要求は、リモートによってold-sha1(または、タグごとに1つ)を追加するように変更され、その後、pre-receiveおよび/または更新フック(リモートに存在するフック)。これらのフックは、タグの作成/削除/更新を許可するか拒否するかを決定できます。

old-sha1値は、タグが作成されている場合、すべてゼロの「null」SHA-1です。タグが削除されている場合、new-sha1はnull SHA-1です。それ以外の場合、両方のSHA-1値は実際の有効な値です。

フックがなくても、実行される一種の「ビルトインフック」があります。「force」フラグを使用しない限り、リモートはタグの移動を拒否します(ただし、「ビルトインフック」は両方ともOKです) 「追加」および「削除」)。表示される拒否メッセージは、この組み込みフックから来ています。 (ちなみに、この同じ組み込みフックは、早送りではないブランチの更新も拒否します。)1

しかし、これが何が起こっているのかを理解するための鍵の1つです。git Pushステップは、リモートがそのタグを現在持っているかどうか、もしそうなら、SHA-1の値を知りません。 「ここにタグの完全なリストとそのSHA-1値があります」としか書かれていません。リモートは値を比較し、追加や変更がある場合、それらに対してフックを実行します。 (同じタグについては、何もしません。あなたが持っていないタグについては、何もしません!)

タグをローカルで削除してからPushを削除すると、Pushはタグを転送しません。リモートは、変更を加える必要がないと想定しています。

タグをローカルで削除してから、新しい場所を指すタグを作成し、Pushを押すと、Pushはタグを転送し、リモートはこれをタグ変更と見なし、強制プッシュでない限り変更を拒否します。

したがって、2つのオプションがあります。

  • 強制プッシュを行う、または
  • リモートのタグを削除します。

後者git Pushを介して可能です2 タグをローカルで削除してもPushingは効果がありません。リモートの名前がOriginであり、削除するタグがdevであると仮定します。

git Push Origin :refs/tags/dev

これは、タグを削除するようにリモートに要求します。ローカルリポジトリ内のタグdevの有無は無関係です。 :remoterefをrefspecとして使用するこの種のPushは、純粋な削除プッシュです。

リモートは、タグの削除を許可する場合と許可しない場合があります(追加された追加フックに応じて)。削除が許可されている場合、タグはなくなり、2番目のgit Push --tagsが、コミットまたは注釈付きのタグリポジトリオブジェクトを指すローカルdevタグを持っている場合、新しいdevタグを送信します。リモートでは、devが新しく作成されたタグになるため、リモートはおそらくプッシュを許可します(これも追加のフックに依存します)。

フォースプッシュは簡単です。タグ以外の何かotherを更新しないようにする場合は、git Pushにその1つのrefspecのみをプッシュするように指示します。

git Push --force Origin refs/tags/dev:refs/tags/dev

(注:ref-specのタグを1つだけ明示的にプッシュする場合は、--tagsは不要です)。


1もちろん、このビルトインフックのreasonは、同じリモートリポジトリの他のユーザーが期待する動作を強制するのに役立ちます:ブランチはそうではありません巻き戻され、タグは移動しません。強制的にプッシュする場合は、他のユーザーにこれを実行していることを知らせて、修正できるようにする必要があります。 「タグがまったく動かない」は、Git 1.8.2によって新たに実施されることに注意してください。以前のバージョンでは、ブランチ名のように、タグがコミットグラフ内で「前に進む」ことができました。 git 1.8.2リリースノート を参照してください。

2リモートにログインできれば簡単です。そこのGitリポジトリに移動して、git tag -d devを実行するだけです。いずれかの方法(リモートでタグを削除するか、git Pushを使用して削除する)では、リモートにアクセスするユーザーがdevタグが欠落していることに気付く期間があることに注意してください。 (彼らは既に自分の古いタグを持ち続けており、すでに持っていれば、プッシュ新しいタグをプッシュする前に古いタグをバックアップします。)

160
torek

Mac SourceTreeでは、すべてのタグをプッシュするチェックボックスのみを選択解除します。

enter image description here

48
itzhar

SourceTreeを使用している場合、quite simpleです。

enter image description here 基本的には、競合するタグを削除して再追加するだけです。

  1. タブに移動リポジトリ->タグ->タグの削除
  2. 競合するタグ名を選択してください
  3. チェックすべてのリモートからタグを削除
  4. 押す削除
  5. 適切なコミットと同じ名前の新しいタグを作成します
  6. 変更をリモートにプッシュするときは、必ずすべてのタグをプッシュしてください。
14
choofie

UPDATEタグにしたい場合、それを1.0.0としましょう

  1. git checkout 1.0.0
  2. 変更を加えます
  3. git ci -am 'modify some content'
  4. git tag -f 1.0.0
  5. githubのリモートタグを削除:git Push Origin --delete 1.0.0
  6. git Push Origin 1.0.0

完了

10
Kaiyu Lee

私はこの問題に遅れているか、すでに回答されているようですが、できることは次のとおりです:(私の場合、ローカルにタグが1つしかありませんでした..古いタグを削除し、 :

git tag -d v1.0
git tag -a v1.0 -m "My commit message"

次に:

git Push --tags -f

これにより、リモートでallタグが更新されます。

危険になる可能性があります!ご自身の責任で使用してください。

8
André Tzermias

拒否を取得する理由は、タグがリモートバージョンとの同期を失ったためです。これは、ブランチの場合と同じ動作です。

git pull --rebase <repo_url> +refs/tags/<TAG>を介してリモートからタグと同期し、同期後、競合の管理が必要です。 diftoolがインストールされている場合(例:meld)git mergetool meldを使用してリモートを同期し、変更を保持します。

-rebaseフラグを使用してプルしているのは、他の競合を避けるために、リモートの作業の上に作業を配置するためです。

また、私が理解していないのは、なぜdevタグを削除して再作成するのですか?タグは、ソフトウェアバージョンまたはマイルストーンを指定するために使用されます。 gitタグの例v0.1devv0.0.1alphav2.3-cr(cr-候補リリース)など。


これを解決する別の方法は、git reflogを発行し、リモートでdevタグをプッシュした瞬間に移動することです。 commit idgit reset --mixed <commmit_id_from_reflog>をコピーして、プッシュした時点でタグがリモートと同期しており、競合が発生しないことを確認します。

Windows SourceTreeで、Push all tags to remotesのチェックを外します。

enter image description here

2
Contango