gitタグの再作成後の「タグはすでにリモートに存在しています」エラー


142

以下の手順を実行すると、次のエラーが発生します。

To git@provider.com:username/repo-name.git
 ! [rejected]        dev -> dev (already exists)
error: failed to push some refs to 'git@provider.com: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タグの更新を強制するために使用できることは知っていますが、これは危険です(たとえば、誤って行われたコミットを、ブランチではなくタグでのみ書き換えます)。


1
コミットは「タグ内」または「ブランチ」では行われません(ただし、後者の場合のように感じられます)。実際、タグ名とブランチ名は単に(1つ、単一の)コミットを指します。以下の回答を参照してください。
2013年

8
これは私にとってgit pull --tagsgit push origin --tags
うまくいき

回答:


175

編集、2016年11月24日:この回答は明らかに人気があるため、ここにメモを追加します。中央サーバーのタグを置き換える場合、古いタグを持つすべてのユーザー(中央サーバーリポジトリのクローンで、既にタグが付いているもの)は古いタグを保持できます。これでその方法がわかりますが、本当にやりたいことを確認してください。あなたは既に削除する「間違った」タグ持っている誰も取得する必要があります彼らの「間違ったタグ」と新しい「右タグ」と交換します。

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

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


タグをプッシュするようにgit push --tags依頼すると、フォームの更新リクエストをリモートに送信します(必要なコミットやその他のオブジェクト、およびプッシュ設定からの他のref更新とともに)。(まあ、それはいくつでも送信します:タグごとに1つです。)new-sha1 refs/tags/name

更新要求は、リモートによって変更されてold-sha1(または、タグごとに1つずつ)追加され、事前受信フックまたは更新フック、あるいはその両方(リモートに存在するフック)に配信されます。これらのフックは、タグの作成/削除/更新を許可するか拒否するかを決定できます。

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

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

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

タグをローカルで削除した場合push、プッシュは単にタグを転送しません。リモートは、変更が行われないことを前提としています。

タグをローカルで削除し、新しい場所を指すように作成するとpush、プッシュによってタグが転送され、リモートでこれがタグの変更として認識され、強制プッシュでない限り変更が拒否されます。

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

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

後者、タグをローカルで削除してもingの効果がない場合でも、git push2を介して可能pushです。リモートの名前がで、origin削除するタグがdev次のとおりであるとします。

git push origin :refs/tags/dev

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

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

フォースプッシュはより簡単です。あなたが更新何にもわからないようにしたい場合は、他のタグよりも、ただ伝えるgit pushだけで1 refspecをプッシュします:

git push --force origin refs/tags/dev:refs/tags/dev

(注:--tags1つのタグref-specのみを明示的にプッシュする場合は必要ありません)。


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

2リモコンでログインできる場合は簡単です。そこでGitリポジトリに移動して実行しgit tag -d devます。いずれかの方法(リモートでタグを削除するか、それを使用git pushして削除する)のいずれかに、リモートにアクセスする誰かがdevタグが欠落していることに気付くことがあります。(彼らがすでに持っている場合、彼らは彼ら自身の古いタグを持ち続けます、そして彼らはあなたが新しいものをプッシュすることができる前に彼らの古いタグを元に戻すことさえするかもしれません。)


これはgitの新しいバージョンでのみ発生しますか?私が持っている1.7.9.5...と私は、この問題を持っていない
IonicăBizău

2
Probalby — git push --tags古いバージョンのgitでは、なしでタグを自動的に変更するだけの漠然とした記憶があり--forceます。私はこれを1.8.4の下でテストしましたが--force、あなたは、または2段階の更新テクニックを必要とします。
2013年

2
@Johnツ:更新:リリースノートによると、これは1.8.2以降の新しい動作です。これも脚注1に編集します。
2013年

どのようにしてこの状況に陥ったのかわからないが、これによりタグが削除され、トライスで再作成された。
RiggsFolly 2015年

4
jediを使用しない場合は、どのようにフォースプッシュを実行しますか?
Fonix、2015

54

Mac SourceTreeでは、[ すべてのタグをプッシュ]チェックボックスのみをオフにします。

ここに画像の説明を入力してください


3
ハハハとてもシンプルな男、私は受け入れられた答えを読んでいて、これを
偽造しよ

10
これは実際に問題を解決せずにそれを克服するためです。これは、リモートおよびローカルでのタグ名の不一致を解決しません。
amalBit 2016

1
Windows版でも動作します!コマンドプロンプトで何が行われているのかを気にしないsourcetreeユーザーを省略している長く受け入れられている回答を読んでくれないようにしてくれて
ありがとう

19

それはです非常に簡単、あなたが使用している場合SourceTreeを

ここに画像の説明を入力してください 基本的には、競合するタグを削除して再度追加するだけです。

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

16

タグを更新したい場合は、それを言いましょう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

完了


12

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

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

次に:

git push --tags -f

これにより、リモートのすべてのタグが更新されます。

危険かもしれません!自己責任で使用してください。


1
これで完了です。タグはローカルにのみあり、リモートにはありませんでした:)
pgarciacamou 2018年

4

拒否されるのは、タグがリモートバージョンと同期しなくなったためです。これはブランチの場合と同じ動作です。

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

--rebaseフラグを使用してプルしている理由は、他の競合を回避できるように、リモートのものの上に作業を置きたいためです。

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


これを解決するもう1つの方法は、a git reflogを発行して、devリモートでタグを押した瞬間に移動することです。コミットIDをコピーするgit reset --mixed <commmit_id_from_reflog>と、プッシュした時点でタグがリモートと同期していて、競合が発生しないことがわかります。


たとえば、現在本稼働中のコミットにタグを付ける場合などです。次に、特定のコミットから古い本番タグを削除し、新しい本番リリース後にコミット用の新しいタグを作成してプッシュする必要がありますか。
Ville Miekk-oja


0

ここでいくつかの良い答え。特に@torekによるもの。急いでいる人のための少しの説明でこの回避策を追加すると思いました。

要約すると、ローカルでタグを移動すると、タグが非Nullコミット値から別の値に変更されます。ただし、(デフォルトの動作として)gitではnull以外のリモートタグを変更できないため、変更をプッシュすることはできません。

回避策は、タグを削除することです(そして、すべてのリモートにチェックを入れます)。次に、同じタグを作成してプッシュします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.