ข้อผิดพลาด“ แท็กมีอยู่แล้วในรีโมท "หลังจากสร้างแท็ก 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. โคลน repo บนเครื่องโลคอล
  3. แก้ไขไฟล์ README กระทำการเปลี่ยนแปลงและส่งการกระทำ
  4. แท็กที่สร้างdev:git 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
ความมุ่งมั่นไม่ได้ทำ "ในแท็ก" หรือ "ในสาขา" (แม้ว่าจะแน่ใจว่ารู้สึกเหมือนเป็นกรณี) ในความเป็นจริงชื่อแท็กและสาขาเพียงชี้ไปที่ (หนึ่งเดียว) กระทำ ดูคำตอบด้านล่าง
torek

8
สิ่งนี้ใช้ได้กับฉันgit pull --tagsแล้วgit push origin --tags
เลื่อย

คำตอบ:


175

แก้ไข, 24 พ.ย. 2559: คำตอบนี้เห็นได้ชัดว่าเป็นที่นิยมดังนั้นฉันจึงเพิ่มบันทึกย่อที่นี่ หากคุณเปลี่ยนแท็กบนเซิร์ฟเวอร์กลางทุกคนที่มีเก่าแท็กใด ๆ โคลนของที่เก็บข้อมูลกลางเซิร์ฟเวอร์ที่มีอยู่แล้วมีแท็กสามารถรักษาแท็กเก่า ดังนั้นในขณะนี้จะบอกวิธีการทำมันให้แน่ใจว่าคุณต้องการที่จะทำ คุณจะต้องได้รับทุกคนที่แล้วมีแท็ก "ผิด" เพื่อลบของพวกเขา "ผิดแท็ก" และแทนที่ด้วยใหม่ "แท็กขวา"

การทดสอบใน Git 2.10 / 2.11 แสดงให้เห็นว่าการรักษาแท็กเก่าเป็นพฤติกรรมปกติสำหรับลูกค้าที่ทำงานและปรับปรุงเป็นพฤติกรรมปกติสำหรับลูกค้าที่ทำงานgit fetchgit fetch --tags

(คำตอบดั้งเดิมมีดังนี้)


เมื่อคุณขอแท็กดันgit push --tagsส่ง (พร้อมกับกระทำใด ๆ และวัตถุอื่น ๆ ที่จำเป็นและการปรับปรุงเตะอื่น ๆ จากการตั้งค่าการผลักดัน) เพื่อระยะไกลร้องขอการปรับปรุงรูปแบบ (มันส่งได้มาก: หนึ่งอันสำหรับแต่ละแท็ก)new-sha1 refs/tags/name

รีโมตคำร้องขอถูกแก้ไขโดยรีโมตเพื่อเพิ่ม old-sha1 (หรืออีกครั้งหนึ่งสำหรับแต่ละแท็ก) จากนั้นส่งไปยังการรับล่วงหน้าและ / หรือการอัพเดตฮุค hooks เหล่านั้นสามารถตัดสินใจว่าจะอนุญาตหรือปฏิเสธแท็กสร้าง / ลบ / อัปเดต

old-sha1ค่าเป็นทุกศูนย์ "null" SHA-1 หากแท็กจะถูกสร้างขึ้น new-sha1เป็นโมฆะ SHA-1 หากแท็กจะถูกลบ มิฉะนั้นค่า SHA-1 ทั้งคู่จะเป็นค่าจริงและถูกต้อง

แม้ว่าจะไม่มี hooks แต่ก็มี "hook ในตัว" ที่เรียกใช้เช่นกัน: รีโมตจะปฏิเสธที่จะย้ายแท็กจนกว่าคุณจะใช้สถานะ "บังคับ" (แม้ว่า "hook ในตัว" จะใช้ได้เสมอกับทั้งคู่ "เพิ่ม" และ "ลบ") ข้อความปฏิเสธที่คุณเห็นมาจากเบ็ดในตัวนี้ (บังเอิญตะขอในตัวเดียวกันนี้ยังปฏิเสธการอัปเดตสาขาที่ไม่ใช่การส่งต่อที่รวดเร็ว) 1

แต่ - นี่คือกุญแจหนึ่งในการทำความเข้าใจว่าเกิดอะไรขึ้น - git pushขั้นตอนนี้ไม่ทราบว่ารีโมตมีแท็กนั้นหรือไม่และถ้าเป็นเช่นนั้น SHA-1 จะมีมูลค่าเท่าใด มีเพียงบอกว่า "นี่คือรายการแท็กที่สมบูรณ์ของฉันพร้อมกับค่า SHA-1" รีโมตจะเปรียบเทียบค่าและหากมีส่วนเพิ่มเติมและ / หรือการเปลี่ยนแปลงให้รัน hooks ที่ค่าเหล่านั้น (สำหรับแท็กที่เหมือนกันมันไม่ได้ทำอะไรเลยสำหรับแท็กที่คุณไม่มีพวกมันก็ไม่ทำอะไรเลย!)

หากคุณลบแท็กในเครื่องแล้วการpushกดของคุณจะไม่ถ่ายโอนแท็ก รีโมตถือว่าไม่มีการเปลี่ยนแปลง

หากคุณลบแท็กในเครื่องจากนั้นสร้างแท็กที่ชี้ไปยังสถานที่ใหม่จากนั้นการpushพุชของคุณจะโอนแท็กและรีโมตจะเห็นสิ่งนี้ว่าเป็นการเปลี่ยนแท็กและปฏิเสธการเปลี่ยนแปลงเว้นแต่เป็นแรงผลักดัน

ดังนั้นคุณมีสองตัวเลือก:

  • ทำแรงกดหรือ
  • ลบแท็กบนรีโมท

หลังสามารถทำได้ผ่านgit push2แม้ว่าการลบแท็กในเครื่องและpushไม่มีผล สมมติว่าชื่อของรีโมทคือoriginและแท็กที่คุณต้องการลบคือdev:

git push origin :refs/tags/dev

สิ่งนี้ขอให้รีโมตลบแท็ก การมีหรือไม่มีแท็กdevในที่เก็บโลคัลของคุณไม่เกี่ยวข้อง ประเภทนี้ที่pushมีการอ้างอิงเป็นการกดลบอย่างแท้จริง:remoteref

ระยะไกลอาจหรือไม่อนุญาตให้ลบแท็ก (ขึ้นอยู่กับ hooks พิเศษใด ๆ ที่เพิ่ม) หากอนุญาตให้ลบได้แท็กจะหายไปและอีกหนึ่งวินาทีgit push --tagsเมื่อคุณมีdevแท็กโลคัลที่ชี้ไปยังวัตถุ repo แท็กการคอมมิตหรือหมายเหตุประกอบให้ส่งdevแท็กใหม่ของคุณ บนรีโมตในdevตอนนี้จะเป็นแท็กที่สร้างขึ้นใหม่ดังนั้นรีโมตอาจยอมให้กดได้ (อีกครั้งจะขึ้นอยู่กับการเพิ่ม hooks พิเศษใด ๆ )

แรงกดง่ายกว่า หากคุณต้องการให้แน่ใจว่าจะไม่อัปเดตสิ่งอื่นใดนอกเหนือจากแท็กเพียงบอกgit pushให้ผลักดันเพียงหนึ่งที่อ้างอิง:

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

(หมายเหตุ: คุณไม่จำเป็นต้องใช้--tagsถ้าหากคุณต้องการระบุเพียงหนึ่งแท็ก)


1แน่นอนเหตุผลของเบ็ดในตัวนี้คือการช่วยบังคับใช้พฤติกรรมที่ผู้ใช้รายอื่นของรีโมต repo เดียวกันนั้นคาดหวัง: สาขานั้นจะไม่กรอทและแท็กจะไม่เคลื่อนที่ หากคุณบังคับให้คุณควรแจ้งให้ผู้ใช้รายอื่นทราบว่าคุณกำลังทำสิ่งนี้อยู่เพื่อให้พวกเขาสามารถแก้ไขได้ โปรดทราบว่า "Git 1.8.2" ไม่ได้ย้ายแท็กเลย " เวอร์ชันก่อนหน้าจะอนุญาตให้แท็ก "ก้าวไปข้างหน้า" ในกราฟการกระทำเหมือนกับชื่อสาขา ดูบันทึกประจำรุ่น 1.8.2 คอมไพล์

2มันไม่สำคัญถ้าคุณสามารถลงชื่อเข้าใช้ทางไกลได้ เพียงไปที่ที่เก็บ Git และเรียกใช้git tag -d devและมีการวิ่ง โปรดทราบว่าวิธีใดวิธีหนึ่ง - การลบแท็กบนรีโมตหรือใช้git pushเพื่อลบแท็ก- มีช่วงเวลาที่ทุกคนที่เข้าถึงรีโมตจะพบว่าdevแท็กนั้นหายไป (พวกเขาจะยังคงมีของตัวเองแท็กเก่าถ้าพวกเขามีอยู่แล้วมันและพวกเขาก็อาจจะผลักดันให้พวกเขากลับมาแท็กเก่าขึ้นก่อนที่คุณจะสามารถผลักดันหนึ่งใหม่.)


สิ่งนี้เกิดขึ้นเฉพาะใน git รุ่นใหม่หรือไม่ ฉันมี1.7.9.5และฉันไม่มีปัญหานี้ ...
IonicăBizău

2
Probalby-I มีหน่วยความจำที่คลุมเครือของเพียงแค่เปลี่ยนแท็กโดยอัตโนมัติในรุ่นเก่าของคอมไพล์โดยไม่ต้องgit push --tags --forceฉันทดสอบสิ่งนี้ภายใต้ 1.8.4 และคุณจำเป็นต้องใช้--forceหรือสองเทคนิคการอัพเดตสเตจ
torek

2
@ Johnツ: การปรับปรุง: มันเป็นพฤติกรรมใหม่เป็นของ 1.8.2 ตามบันทึกประจำรุ่น ฉันจะแก้ไขเป็นเชิงอรรถ 1 ด้วย
torek

ไม่ทราบว่าฉันเข้ามาในสถานการณ์นี้ได้อย่างไร แต่มันถูกลบแท็กและสร้างขึ้นใหม่ในเวลาอันสั้น
RiggsFolly

4
คุณจะบังคับให้ทำอย่างไรถ้าคุณไม่ได้เป็นเจได
Fonix

54

ใน Mac SourceTree ยกเลิกการเลือกช่องทำเครื่องหมายPush all tags :

ป้อนคำอธิบายรูปภาพที่นี่


3
hahahah คนที่เรียบง่ายมากฉันอ่านคำตอบที่ยอมรับแล้วและฉันคิดว่าฉันจะได้รับสิ่งนี้มากขึ้น
MegaManX

10
นี่เป็นเพียงการเอาชนะโดยไม่แก้ไขปัญหาจริง สิ่งนี้ไม่ได้แก้ไขชื่อแท็กที่ตรงกับที่อยู่ห่างไกลและในพื้นที่
amalBit

1
ใช้งานได้กับรุ่น windows เช่นกัน! ขอบคุณสำหรับการบันทึกเราจากการอ่านคำตอบที่ได้รับการยอมรับมานานแล้วว่าละเว้น sourcetree ผู้ใช้ที่ไม่สนใจสิ่งที่เกิดขึ้นในคำสั่งพร้อมรับคำ :)
schlingel

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

DONE


12

ดูเหมือนว่าฉันจะสายในเรื่องนี้และ / หรือได้รับคำตอบแล้ว แต่สิ่งที่สามารถทำได้คือ: (ในกรณีของฉันฉันมีเพียงหนึ่งแท็กในพื้นที่ดังนั้น .. ฉันลบแท็กเก่าและ retagged ด้วย :

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

แล้ว:

git push --tags -f

ที่จะอัปเดตแท็กทั้งหมดในระยะไกล

อาจเป็นอันตรายได้! ใช้ที่มีความเสี่ยงของตัวเอง


1
มันทำเพื่อฉัน! แท็กเพียงทั้งในประเทศและไม่ได้อยู่ในระยะไกล :)
pgarciacamou

4

สาเหตุที่คุณถูกปฏิเสธคือแท็กของคุณขาดการซิงค์กับรุ่นระยะไกล นี่คือพฤติกรรมเดียวกันกับสาขา

ซิงค์กับแท็กจากระยะไกลผ่านทางgit pull --rebase <repo_url> +refs/tags/<TAG>และหลังจากที่คุณซิงค์คุณจะต้องจัดการความขัดแย้ง หากคุณติดตั้ง diftool (เช่น meld) ให้git mergetool meldใช้มันเพื่อซิงค์ข้อมูลระยะไกลและรักษาการเปลี่ยนแปลงของคุณ

เหตุผลที่คุณดึงด้วย--rebase flag คือคุณต้องการให้งานของคุณอยู่เหนือรีโมตเพื่อให้คุณสามารถหลีกเลี่ยงความขัดแย้งอื่น ๆ

นอกจากนี้สิ่งที่ฉันไม่เข้าใจคือเหตุผลที่คุณจะลบdevแท็กและสร้างใหม่อีกครั้ง ??? แท็กใช้สำหรับระบุรุ่นซอฟต์แวร์หรือเหตุการณ์สำคัญ ตัวอย่างของแท็กคอมไพล์v0.1dev, v0.0.1alpha, v2.3-cr(CR - ปล่อยผู้สมัคร) และอื่น ๆ ..


อีกวิธีหนึ่งที่คุณสามารถแก้ปัญหานี้คือปัญหา a git reflogและไปยังช่วงเวลาที่คุณผลักdevแท็กบนรีโมต คัดลอกรหัสประจำตัวและgit reset --mixed <commmit_id_from_reflog>วิธีนี้คุณจะรู้ว่าแท็กของคุณซิงค์กับรีโมทในขณะที่คุณผลักมันและจะไม่มีความขัดแย้งเกิดขึ้น


ตัวอย่างเช่นถ้าคุณต้องการติดแท็กการคอมมิชชันที่กำลังใช้งานอยู่ คุณจะต้องลบแท็กการผลิตเก่าออกจากการคอมมิทเฉพาะหรือไม่และสร้างและผลักดันแท็กใหม่สำหรับการคอมมิชชันหลังจากรีลีสการผลิตใหม่
Ville Miekk-oja


0

คำตอบที่ดีที่นี่ โดยเฉพาะอย่างยิ่งหนึ่งโดย @torek ฉันคิดว่าฉันจะเพิ่มงานนี้ด้วยคำอธิบายเล็กน้อยสำหรับผู้ที่รีบเร่ง

เพื่อสรุปสิ่งที่เกิดขึ้นคือเมื่อคุณย้ายแท็กภายในเครื่องมันจะเปลี่ยนแท็กจากค่าการส่งที่ไม่ใช่ค่า Null เป็นค่าอื่น อย่างไรก็ตามเนื่องจาก git (เป็นพฤติกรรมเริ่มต้น) ไม่อนุญาตให้เปลี่ยนแท็กระยะไกลที่ไม่ใช่ค่าว่างคุณจึงไม่สามารถผลักดันการเปลี่ยนแปลงได้

วิธีแก้ไขคือการลบแท็ก (และทำเครื่องหมายลบรีโมททั้งหมด) จากนั้นสร้างแท็กเดียวกันและกด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.