Fehler "Tag existiert bereits in der Fernbedienung" nach Neuerstellung des Git-Tags

142

Ich erhalte die folgende Fehlermeldung, nachdem ich die folgenden Schritte ausgeführt habe:

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. Erstellt das Repository
  2. Das Repo auf dem lokalen Computer geklont.
  3. Die README-Datei wurde geändert, die Änderungen wurden festgeschrieben und das Commit wurde verschoben.
  4. Tag erstellt dev :git tag dev
  5. Pushed Tags: git push --tags
  6. Die README-Datei wurde geändert, die Änderungen wurden festgeschrieben und das Commit wurde verschoben.
  7. Tag gelöscht dev, erneut erstellt und Tags verschoben:

    git tag -d dev
    git tag dev
    git push --tags
    

Warum passiert dies?

Ich bin auf dem Mac. Meine Freunde, die Linux (Ubuntu) verwenden, haben dieses Problem nicht. Ich weiß, dass ich damit git push --tags -fdie Tag-Aktualisierung erzwingen kann , aber dies ist gefährlich (z. B. das Umschreiben eines versehentlich vorgenommenen Commits nur im Tag, nicht in der Verzweigung).

Luca Boieru
quelle
1
Commits werden nicht "in Tags" oder "in Zweigen" ausgeführt (obwohl es sich sicher so anfühlt, als ob letzteres der Fall ist). Tatsächlich zeigen Tag- und Zweignamen einfach auf (ein, einzelnes) Commit. Siehe Antwort unten.
Torek
8
das für mich arbeitet git pull --tagsdanngit push origin --tags
sawe

Antworten:

175

Bearbeiten, 24. November 2016: Diese Antwort ist anscheinend sehr beliebt, daher füge ich hier eine Notiz hinzu. Wenn Sie ein Tag auf einem zentralen Server ersetzen , kann jeder, der das alte Tag hat - jeder Klon des Repositorys des zentralen Servers, der das Tag bereits hat - sein altes Tag beibehalten . Während dies Ihnen sagt, wie es geht, stellen Sie sicher, dass Sie es tun möchten . Sie müssen alle, die bereits das "falsche" Tag haben, dazu bringen, ihr "falsches Tag" zu löschen und durch das neue "richtige Tag" zu ersetzen.

Das Testen in Git 2.10 / 2.11 zeigt, dass das Beibehalten des alten Tags das Standardverhalten für ausgeführte Clients git fetchist und das Aktualisieren das Standardverhalten für ausgeführte Clients ist git fetch --tags.

(Die ursprüngliche Antwort folgt.)


Wenn Sie nach Push-Tags fragen, wird git push --tags(zusammen mit allen erforderlichen Commits und anderen Objekten sowie anderen Ref-Updates aus den Push-Einstellungen) eine Aktualisierungsanforderung des Formulars an die Fernbedienung gesendet . (Nun, es werden jedoch viele gesendet: eine davon für jedes Tag.)new-sha1 refs/tags/name

Die Aktualisierungsanforderung wird von der Fernbedienung geändert, um eine old-sha1(oder erneut eine für jedes Tag) hinzuzufügen , und dann an die Pre-Receive- und / oder Update-Hooks (je nachdem, welche Hooks auf der Fernbedienung vorhanden sind) gesendet. Diese Hooks können entscheiden, ob das Erstellen / Löschen / Aktualisieren des Tags zugelassen oder abgelehnt werden soll.

Der old-sha1Wert ist die Null-Null "SHA-1", wenn das Tag erstellt wird. Dies new-sha1ist die Null-SHA-1, wenn das Tag gelöscht wird. Ansonsten sind beide SHA-1-Werte echte, gültige Werte.

Selbst ohne Hooks wird eine Art "eingebauter Hook" ausgeführt: Die Fernbedienung weigert sich, ein Tag zu verschieben, es sei denn, Sie verwenden das Flag "force" (obwohl der "eingebaute Hook" bei beiden immer in Ordnung ist "hinzufügen" und "löschen"). Die Ablehnungsnachricht, die Sie sehen, stammt von diesem integrierten Hook. (Im Übrigen lehnt dieser integrierte Hook auch Verzweigungsaktualisierungen ab, die nicht schnell vorgespult werden.) 1

Aber - hier ist einer der Schlüssel zum Verständnis der Vorgänge - der git pushSchritt hat keine Ahnung, ob die Fernbedienung jetzt über dieses Tag verfügt und wenn ja, welchen SHA-1-Wert sie hat. Es heißt nur "hier ist meine vollständige Liste der Tags zusammen mit ihren SHA-1-Werten". Die Fernbedienung vergleicht die Werte und führt bei Hinzufügungen und / oder Änderungen die Hooks für diese aus. (Für Tags, die gleich sind, macht es überhaupt nichts. Für Tags, die Sie nicht haben, macht es auch nichts!)

Wenn Sie das Tag lokal löschen, pushüberträgt Ihr Push das Tag einfach nicht. Die Fernbedienung geht davon aus, dass keine Änderungen vorgenommen werden sollten.

Wenn Sie das Tag lokal löschen und dann auf eine neue Stelle verweisen push, überträgt Ihr Push das Tag, und die Fernbedienung sieht dies als Tag-Änderung an und lehnt die Änderung ab, es sei denn, es handelt sich um einen Force-Push.

Sie haben also zwei Möglichkeiten:

  • einen Kraftstoß machen oder
  • Löschen Sie das Tag auf der Fernbedienung.

Letzteres ist über git push2 möglich , obwohl das Löschen des Tags lokal und pushing keine Auswirkung hat. Angenommen, der Name der Fernbedienung lautet originund das Tag, das gelöscht werden soll, lautet dev:

git push origin :refs/tags/dev

Dadurch wird die Fernbedienung aufgefordert, das Tag zu löschen. Das Vorhandensein oder Fehlen des Tags devin Ihrem lokalen Repository ist irrelevant. Diese Art von push, mit als Referenz, ist ein reiner Lösch-Push.:remoteref

Die Fernbedienung kann das Löschen von Tags zulassen oder nicht (abhängig von zusätzlichen hinzugefügten Hooks). Wenn das Löschen möglich ist, ist das Tag nicht mehr vorhanden. git push --tagsWenn ein lokales devTag auf ein Commit- oder kommentiertes Tag-Repo-Objekt verweist, senden Sie Ihr neues devTag. Auf der Fernbedienung devwird nun ein neu erstelltes Tag angezeigt, sodass die Fernbedienung wahrscheinlich den Push zulässt (dies hängt wiederum von zusätzlichen hinzugefügten Hooks ab).

Der Force-Push ist einfacher. Wenn Sie sicher sein möchten, dass Sie nichts anderes als das Tag aktualisieren , sagen Sie einfach, git pushdass Sie nur diese eine Referenzspezifikation drücken sollen:

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

(Hinweis: Sie brauchen nicht, --tagswenn Sie explizit nur eine Tag-Ref-Spezifikation drücken).


1 Der Grund für diesen integrierten Hook besteht natürlich darin, das Verhalten zu erzwingen, das andere Benutzer desselben Remote-Repos erwarten: Zweige werden nicht zurückgespult und Tags werden nicht verschoben. Wenn Sie einen Force-Push ausführen, sollten Sie die anderen Benutzer darüber informieren, dass Sie dies tun, damit sie dies korrigieren können. Beachten Sie, dass "Tags bewegen sich überhaupt nicht" von Git 1.8.2 neu erzwungen wird. In früheren Versionen konnte das Tag im Festschreibungsdiagramm "vorwärts" verschoben werden, ähnlich wie bei Zweignamen. Siehe die Versionshinweise zu Git 1.8.2 .

2 Es ist trivial, wenn Sie sich auf der Fernbedienung anmelden können. Gehen Sie einfach zum Git-Repository und führen Sie es aus git tag -d dev. Beachten Sie, dass in beiden Fällen - Löschen des Tags auf der Fernbedienung oder Löschen des Tags - git pushjeder, der auf die Fernbedienung zugreift, feststellt, dass das devTag fehlt. (Sie haben weiterhin ihr eigenes altes Tag, falls sie es bereits haben, und sie können sogar ihr altes Tag wieder nach oben verschieben, bevor Sie das neue verschieben können.)

torek
quelle
Geschieht dies nur in den neuen Versionen von git? Ich habe 1.7.9.5und ich habe dieses Problem nicht ...
Ionică Bizău
2
Probalby - Ich habe eine vage Erinnerung daran, wie ich git push --tagsdas Tag in älteren Versionen von git ohne automatisch geändert habe --force. Ich habe dies jedoch unter 1.8.4 getestet, und Sie benötigen --forceoder die zweistufige Aktualisierungstechnik.
Torek
2
@ Johnツ: Update: es ist neues Verhalten wie von 1.8.2 nach der Release Notes . Ich werde dies auch in Fußnote 1 bearbeiten.
Torek
Ich weiß nicht, wie ich in diese Situation gekommen bin, aber dadurch wurde ein Tag gelöscht und im Handumdrehen neu erstellt.
RiggsFolly
4
Wie machst du einen Force-Push, wenn du kein Jedi bist?
Fonix
54

Deaktivieren Sie in Mac SourceTree nur das Kontrollkästchen Alle Tags pushen:

Geben Sie hier die Bildbeschreibung ein

itzhar
quelle
3
hahahah so einfacher Mann, ich habe die akzeptierte Antwort gelesen und dachte, ich werde das
fälschen
10
Dies dient nur dazu, es zu überwinden, ohne das Problem tatsächlich zu lösen. Dies löst nicht die Fehlanpassung des Tag-Namens auf Remote- und lokaler Ebene.
AmalBit
1
funktioniert auch für die Windows-Version! danke, dass du uns davor bewahrt hast, die lange akzeptierte Antwort zu lesen, bei der Sourcetree-Benutzer weggelassen werden, denen es egal ist, was in der Eingabeaufforderung vor sich geht :)
schlingel
19

Es ist ganz einfach, wenn Sie SourceTree verwenden .

Geben Sie hier die Bildbeschreibung ein Grundsätzlich müssen Sie nur das widersprüchliche Tag entfernen und erneut hinzufügen:

  1. Gehen Sie zur Registerkarte Repository -> Tag -> Tag entfernen
  2. Wählen Sie den widersprüchlichen Tag-Namen aus
  3. Aktivieren Sie das Kontrollkästchen Tag von allen Fernbedienungen entfernen
  4. Drücken Sie entfernen
  5. Erstellen Sie ein neues Tag mit demselben Namen für das richtige Commit
  6. Stellen Sie sicher, dass Sie Alle Tags drücken aktivieren, wenn Sie Ihre Änderungen auf die Fernbedienung übertragen
Choofie
quelle
16

Wenn Sie ein Tag AKTUALISIEREN möchten, sagen wir es1.0.0

  1. git checkout 1.0.0
  2. Nehmen Sie Ihre Änderungen vor
  3. git ci -am 'modify some content'
  4. git tag -f 1.0.0
  5. Remote-Tag auf Github löschen: git push origin --delete 1.0.0
  6. git push origin 1.0.0

GETAN

Kaiyu Lee
quelle
12

Es scheint, dass ich mit diesem Problem zu spät komme und / oder es bereits beantwortet wurde, aber was getan werden könnte, ist: (In meinem Fall hatte ich nur ein Tag lokal, also .. Ich habe das alte Tag gelöscht und es erneut markiert ::

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

Dann:

git push --tags -f

Dadurch werden alle Tags auf der Fernbedienung aktualisiert .

Könnte gefährlich sein! Verwendung auf eigene Gefahr.

André Tzermias
quelle
1
Das hat es für mich getan! Die Tags waren nur lokal und nicht in der Fernbedienung :)
Pgarciacamou
4

Der Grund, warum Sie abgelehnt werden, ist, dass Ihr Tag die Synchronisierung mit der Remote-Version verloren hat. Dies ist das gleiche Verhalten bei Zweigen.

Synchronisierung mit dem Tag von der Fernbedienung über git pull --rebase <repo_url> +refs/tags/<TAG>und nach der Synchronisierung müssen Sie Konflikte verwalten . Wenn Sie ein Diftool installiert haben (z. B. meld), git mergetool meldverwenden Sie es, um die Fernbedienung zu synchronisieren und Ihre Änderungen beizubehalten .

Der Grund, warum Sie mit dem Flag --rebase ziehen, ist, dass Sie Ihre Arbeit auf das Remote-Flag legen möchten, um andere Konflikte zu vermeiden.

Ich verstehe auch nicht, warum Sie das devTag löschen und neu erstellen sollten. Tags werden zum Festlegen von Softwareversionen oder Meilensteinen verwendet. Beispiel für git - Tags v0.1dev, v0.0.1alpha, v2.3-cr(cr - Release Candidate) und so weiter ..


Eine andere Möglichkeit, dies zu lösen, ist Problem a git reflogund gehen Sie zu dem Moment, in dem Sie das devTag auf der Fernbedienung gedrückt haben . Kopieren Sie die Commit-ID, und auf git reset --mixed <commmit_id_from_reflog>diese Weise wissen Sie, dass Ihr Tag zum Zeitpunkt des Pushs mit der Fernbedienung synchronisiert war und keine Konflikte auftreten.

Daniel Andrei Mincă
quelle
2

Deaktivieren Sie in Windows SourceTree das Kontrollkästchen Push all tags to remotes.

Geben Sie hier die Bildbeschreibung ein

Contango
quelle
0

Einige gute Antworten hier. Besonders der von @torek . Ich dachte, ich würde diese Problemumgehung mit einer kleinen Erklärung für diejenigen hinzufügen, die es eilig haben.

Zusammenfassend lässt sich sagen, dass beim lokalen Verschieben eines Tags das Tag von einem Nicht-Null-Festschreibungswert in einen anderen Wert geändert wird. Da git (als Standardverhalten) das Ändern von Remote-Tags ungleich Null nicht zulässt, können Sie die Änderung nicht verschieben.

Die Problemumgehung besteht darin, das Tag zu löschen (und alle Fernbedienungen zu entfernen). Erstellen Sie dann das gleiche Tag und drücken Sie.

idnavid
quelle