ลบแท็ก git โลคัลที่ไม่อยู่บนที่เก็บรีโมตอีกต่อไป


468

เราใช้แท็กในคอมไพล์เป็นส่วนหนึ่งของกระบวนการปรับใช้ของเรา ในบางครั้งเราต้องการล้างแท็กเหล่านี้โดยลบออกจากที่เก็บระยะไกลของเรา

ตรงไปตรงมานี้ ผู้ใช้รายหนึ่งลบโลคัลแท็กและรีโมตแท็กในคำสั่งชุดเดียว เรามีเชลล์สคริปต์เล็กน้อยที่รวมทั้งสองขั้นตอน

ตอนนี้ผู้ใช้ที่ 2 (ที่ 3, ที่ 4, ... ) มีแท็กท้องถิ่นที่ไม่ปรากฏบนรีโมทอีกต่อไป

ฉันกำลังมองหาคำสั่งที่คล้ายกับgit remote prune originที่ล้างสาขาการติดตามในพื้นที่ซึ่งสาขาระยะไกลถูกลบไปแล้ว

git tag -lอีกวิธีหนึ่งคือคำสั่งง่ายๆที่จะแท็กรายการระยะไกลสามารถนำมาใช้เพื่อเปรียบเทียบกับแท็กท้องถิ่นกลับผ่านทาง


2
ฉันเสนอคุณสมบัติใหม่ในคอมไพล์เพื่อสนับสนุนการตัดแท็กเก่า: thread.gmane.org/gmane.comp.version-control.git/168833
Adam Monsen

1
หมายเหตุ: ด้วย Git 2.17 (Q2 2018) ความเรียบง่ายgit config fetch.pruneTags trueจะทำให้คุณgit fetchทำสิ่งที่คุณต้องการ! ดูคำตอบของฉันสำหรับคำถามอื่นนี้
VonC

2
การโพสต์ความคิดเห็นใหม่จากคำตอบด้านล่าง: อย่างน้อยด้วย git 2.18.0 เราสามารถใช้ไวยากรณ์นี้ได้: git fetch --prune --prune-tags ที่มา
zutnop

คำตอบ:


71

คำถามที่ดี. :) ฉันไม่มีคำตอบที่สมบูรณ์ ...

ที่กล่าวว่าคุณสามารถรับรายการของแท็กระยะไกลgit ls-remoteได้ หากต้องการแสดงแท็กในพื้นที่เก็บข้อมูลที่อ้างอิงโดยoriginคุณต้องเรียกใช้:

git ls-remote --tags origin

ที่ส่งคืนรายการแฮชและชื่อแท็กที่จำง่ายเช่น:

94bf6de8315d9a7b22385e86e1f5add9183bcb3c        refs/tags/v0.1.3
cc047da6604bdd9a0e5ecbba3375ba6f09eed09d        refs/tags/v0.1.4
...
2f2e45bedf67dedb8d1dc0d02612345ee5c893f2        refs/tags/v0.5.4

แน่นอนคุณสามารถรวบรวมสคริปต์ทุบตีเพื่อเปรียบเทียบแท็กที่สร้างโดยรายการนี้กับแท็กที่คุณมีในเครื่อง ดูที่git show-ref --tagsสร้างชื่อแท็กในรูปแบบเดียวกับgit ls-remote)


เช่นกันgit show-refมีตัวเลือกที่จะอยู่ตรงข้ามกับสิ่งที่คุณต้องการได้ คำสั่งต่อไปนี้จะแสดงรายการแท็กทั้งหมดในสาขาระยะไกลที่คุณไม่มีในเครื่อง:

git ls-remote --tags origin | git show-ref --tags --exclude-existing

ขอบคุณไมค์ ฉันจะหมุนสคริปต์ทุบตีของฉันเองโดยใช้แต่ละรายการเพื่อเปรียบเทียบ
kEND

11
คำตอบของ Richard W ทำได้ดีกว่านี้มากในกรณีที่คุณไม่สนใจสคริปต์ที่ซับซ้อน
Kyle Heironimus

1
หมายเหตุด้านข้างเกี่ยวกับแท็กที่ไม่มีอยู่ในเครื่องสามารถขยายได้เพื่อตรวจสอบรีโมตเพิ่มเติม:git remote | xargs -L 1 git ls-remote --tags | git show-ref --tags --exclude-existing
Palec

ดูคำตอบต่อไปสำหรับวิธีแก้ปัญหาที่ง่ายกว่า
sfletche

git รองรับ --prune-tags ไม่แน่ใจว่าเวอร์ชันนี้ถูกนำมาใช้ git-scm.com/docs/git-fetch#git-fetch---prune-tags
John Kloian

1053

นี่เป็นคำถามที่ยอดเยี่ยมฉันสงสัยในสิ่งเดียวกัน

ฉันไม่ต้องการเขียนสคริปต์เพื่อค้นหาวิธีแก้ไขปัญหาอื่น กุญแจสำคัญคือการค้นพบว่าคุณสามารถลบแท็กในเครื่องแล้วใช้ git fetch เพื่อ "รับมันกลับ" จากเซิร์ฟเวอร์ระยะไกล หากไม่มีแท็กบนรีโมตแท็กนั้นจะยังคงอยู่

ดังนั้นคุณต้องพิมพ์สองบรรทัดตามลำดับ:

git tag -l | xargs git tag -d
git fetch --tags

เหล่านี้:

  1. ลบแท็กทั้งหมดออกจาก repo ท้องถิ่น FWIW, xargs วางแต่ละแท็กเอาท์พุทโดย "tag -l" ลงในบรรทัดคำสั่งสำหรับ "tag -d" หากไม่มีสิ่งนี้ git จะไม่ลบอะไรเลยเพราะไม่ได้อ่าน stdin (silly git)

  2. ดึงแท็กที่ใช้งานอยู่ทั้งหมดจาก repo ระยะไกล

สิ่งนี้สามารถใช้งานได้กับ Windows


57
นี่ต้องเป็นคำตอบ git ที่ฉันชอบใน StackOverflow มันรวมความรู้ความเรียบง่ายและการใช้กลอุบายและอธิบายทุกอย่าง ยอดเยี่ยม
tymtam

25
ดังที่ได้กล่าวไว้ในคำตอบที่แยกออกซึ่งจะลบแท็กท้องถิ่นทั้งหมดและแท็กที่ไม่อยู่ใน repo ระยะไกลจะไม่ถูกสร้างขึ้นใหม่อย่างแน่นอน
สอง

13
FWIW สิ่งนี้ไม่จำเป็นอย่างสมบูรณ์ ควรมีgit tag prune originคำสั่ง
void.pointer

9
สิ่งนี้อาจไม่ได้ผลสำหรับทุกคน คุณควรทำ git fetch --tags เพื่อให้ปลอดภัย
Adam Kurkiewicz

5
ฉันต้องไปgit tag -l | %{git tag -d $_}ทำงานใน PowerShell นี้ ไม่แน่ใจเกี่ยวกับคนอื่น
Alain

244

จาก Git v1.7.8 ถึง v1.8.5.6 คุณสามารถใช้สิ่งนี้:

git fetch <remote> --prune --tags

ปรับปรุง

สิ่งนี้ใช้ไม่ได้กับ git เวอร์ชันใหม่ (เริ่มต้นด้วย v1.9.0) เนื่องจากการคอมมิท e66ef7ae6f31f2 ฉันไม่ต้องการที่จะลบมันเพราะมันใช้ได้ผลกับบางคน

ตามที่แนะนำโดย "Chad Juliano" กับ Git ทุกรุ่นตั้งแต่ v1.7.8 คุณสามารถใช้คำสั่งต่อไปนี้:

git fetch --prune <remote> +refs/tags/*:refs/tags/*

คุณอาจต้องใส่ส่วนแท็กด้วยเครื่องหมายคำพูด (บน Windows เป็นต้น) เพื่อหลีกเลี่ยงการขยายสัญลักษณ์แทน:

git fetch --prune <remote> "+refs/tags/*:refs/tags/*"

2
ฉันอ้างถึงเอกสารที่มาพร้อมกับ Git สำหรับ Windows 1.9.4-preview20140611 (และฉันสงสัยว่ารุ่นก่อนหน้านี้ทั้งหมด) ฉันเข้าถึงเอกสารดังกล่าวด้วย "git fetch --help" [quote] แท็กไม่ได้ถูกตัดหากมีการดึงข้อมูลเท่านั้นเนื่องจากแท็กเริ่มต้นที่ติดตามอัตโนมัติหรือเนื่องจากตัวเลือก - แท็ก [/ quote]
Félix Cantournet

2
git fetch --prune <remote> +refs/tags/*:refs/tags/*ไม่ทำงานใน ZSH แต่ใช้งานได้ใน BASH
อเล็กซ์

3
@Alex นั่นเป็นเพียงเพราะ zsh ขยาย*แต่ถ้าคุณอ้างว่ามันควรจะดี
NSF

3
@ v01pe - ขณะนี้มีทางลัด git --prune-tags พร้อมใช้งานตั้งแต่ git 2.17.0 ที่อธิบายไว้ในเอกสารภายใต้หัวข้อการตัด: git-scm.com/docs/git-fetch/2.17.0 จากเอกสาร: The - ตัวเลือก -prune-tags เทียบเท่ากับการอ้างอิง / tags / *: refs / tags / * ที่ประกาศใน refspecs ของรีโมท Equivalents: git fetch origin --prune --prune-tagsOR git fetch origin --prune 'refs/tags/*:refs/tags/*'หรือgit fetch <url of origin> --prune --prune-tagsORgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*'
mkisaacs

3
git fetch origin --prune --prune-tagsตัดทั้งกิ่งไม้และแท็กติดตามระยะไกล ตรวจสอบในเวอร์ชั่น 2.18 git
หมายเลข 945

158

หากคุณต้องการแท็กเหล่านั้นที่มีอยู่บนรีโมตเพียงแค่ลบแท็กท้องถิ่นทั้งหมดของคุณ:

$ git tag -d $(git tag)

จากนั้นดึงแท็กระยะไกลทั้งหมด:

$ git fetch --tags

1
ไร้ที่ติผมมีปัญหากับ xargs หนึ่งไม่พบแท็กบาง
Marcio โทชิโอะ

3
@ocroquette ผมไม่แน่ใจว่ามัน nicer xargsกว่า หากคุณมีแท็กมากกว่าARG_MAXหรือมีข้อ จำกัด คล้ายกันสิ่งนี้จะไม่ทำงาน ไม่น่าเป็นไปได้ แต่เป็นไปได้และนั่นเป็นสาเหตุxargsที่ยอดเยี่ยม
พอลเดรเปอร์

2
"ดี" เป็นเรื่องส่วนตัวทุกคนจะแสดงความคิดเห็นด้วยตนเอง เกี่ยวกับ ARG_MAX นั่นเป็นเรื่องจริง อย่างไรก็ตามในระบบที่ฉันใช้ ARG_MAX นั้นสูงกว่าจำนวนแท็กที่ฉันมีในที่เก็บใด ๆ ดังนั้นฉันจึงไม่คำนึงถึงข้อ จำกัด เช่นเดียวกับที่ฉันไม่สนใจเมื่อเขียน "ls * .jpg" .
ocroquette

2
วิธีแก้ปัญหาที่สะอาดที่สุด
mitsest

2
git config --global alias.prune-tags '!git tag -d $(git tag) && git fetch --tags'คำสั่งนามแฝงบังคับ สนุก. :-)
Karl Wilbur

87

ดูเหมือนว่า Git เวอร์ชันล่าสุด (ฉันใช้ git v2.20) อนุญาตให้พูดง่าย ๆ

git fetch --prune --prune-tags

ทำความสะอาดมาก!

https://git-scm.com/docs/git-fetch#_pruning

คุณสามารถกำหนดค่าให้คอมไพล์ตัดแท็กได้เสมอเมื่อดึงข้อมูล:

git config fetch.pruneTags true

หากคุณต้องการตัดแท็กเมื่อดึงข้อมูลจากระยะไกลเฉพาะคุณสามารถใช้remote.<remote>.pruneTagsตัวเลือก ตัวอย่างเช่นเพื่อตัดแท็กเสมอเมื่อดึงข้อมูลจากแหล่งกำเนิด แต่ไม่ใช่รีโมตอื่น

git config remote.origin.pruneTags true

เยี่ยมมาก ฉันได้ดัดแปลงมันเพื่อโพสต์บน SOes -> ¿Cómo puedo Elimar las etiquetas de Git que solo tengo en local? .
fedorqui 'ดังนั้นหยุดการทำร้าย'

ยอดเยี่ยม ฉันพบความล้มเหลวในการผลัก git ด้วย "git-shell ที่เสียชีวิตของสัญญาณ 13" ไม่มีผลแม้แต่กับ http.postbuffer ที่เพิ่มขึ้น หลังจากเปิดใช้งาน GIT_TRACE_PACKET และ GIT_TRACE ฉันเห็นว่าการผลักดันไปยังการอ้างอิง / แท็กที่ไม่ถูกต้องดังนั้นการใช้ "--prune-tags" จะแก้ไขได้ ขอบคุณมาก!
Ivellios

78

Git ทุกรุ่นตั้งแต่ v1.7.8 เข้าใจgit fetchด้วย refspec ในขณะที่ตั้งแต่ v1.9.0 --tagsตัวเลือกจะแทนที่--pruneตัวเลือก สำหรับวิธีแก้ปัญหาทั่วไปลองสิ่งนี้:

$ git --version
git version 2.1.3

$ git fetch --prune origin "+refs/tags/*:refs/tags/*"
From ssh://xxx
 x [deleted]         (none)     -> rel_test

สำหรับการอ่านเพิ่มเติมเกี่ยวกับการเปลี่ยนแปลงพฤติกรรม "--tags" กับ "--prune" ใน Git v1.9.0 โปรดดูที่: https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c


7
นี่ควรเป็นคำตอบที่ดีที่สุด มันเป็นคำสั่ง git เดียวโดยไม่มีการทุบตีไม่มีท่อและไม่มี xargs
G. Sylvie Davies

1
แทนที่originด้วยupstreamและคอมไพล์แก้ไขแท็กท้องถิ่นของฉันตามต้นน้ำ; git push origin :<deleted-tag-name>อัปเดตตัวแยก GitHub ของฉันต่อไปลบแท็กที่ถูกลบออก
ลีแอนน์

3
อย่างน้อยด้วย git 2.18.0 เราสามารถใช้ซินแท็กซ์นี้ได้ด้วยgit fetch --prune --prune-tags origin
มาร์ติน

3
เริ่มต้นด้วยคอมไพล์ 2.17.0 - The --prune แท็กตัวเลือกที่ถูกรวมและอธิบายไว้ในส่วนการตัดแต่งกิ่งในรายละเอียดกับคำสั่งเทียบเท่าในเอกสารดังต่อไปนี้: git-scm.com/docs/git-fetch/2.17.0 git fetch origin --prune --prune-tagsหรือ git fetch origin --prune 'refs/tags/*:refs/tags/*' หรือgit fetch <url of origin> --prune --prune-tags หรือgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*'
mkisaacs

8

Git นั้นรองรับการล้างแท็กในเครื่อง:

git fetch --tags --prune

คำสั่งนี้ดึงแท็กล่าสุดและลบแท็กที่ลบทั้งหมด


ดูเหมือนว่าควรเป็น "--prune" แทน "--prune-tags" มิฉะนั้นนั่นคือสิ่งที่ฉันต้องการขอบคุณ
AnyDev

ฉันได้รับปัญหาในซอร์สต้นไม้ล้มเหลวในการผลักดันผู้อ้างอิงถึง ... : ได้ผลสำหรับฉัน :) ขอบคุณมาก
Abhishek Thapliyal


4

แสดงความแตกต่างระหว่างแท็กโลคัลและรีโมต:

diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort)
  • git tag ให้รายการของแท็กท้องถิ่น
  • git ls-remote --tags ให้รายการเส้นทางแบบเต็มไปยังแท็กระยะไกล
  • cut -f2 | grep -v '\^' | sed 's#refs/tags/##' แยกวิเคราะห์เพียงชื่อแท็กจากรายการของเส้นทางแท็กระยะไกล
  • ในที่สุดเราก็จัดเรียงแต่ละรายการทั้งสองและแตกต่างกัน

บรรทัดที่ขึ้นต้นด้วย "<" เป็นแท็กท้องถิ่นของคุณที่ไม่อยู่ใน repo ระยะไกล หากพวกเขามีไม่กี่คุณสามารถลบออกด้วยตนเองทีละคนถ้าพวกเขามีจำนวนมากคุณทำ grep-ing และท่อเพื่ออัตโนมัติ


2
โปรดลองเพิ่มคำอธิบายลงในรหัสของคุณ สิ่งนี้จะปรับปรุงคุณภาพของคำตอบของคุณอย่างแน่นอน
honk

คำสั่งที่สมบูรณ์เพื่อลบแท็กระยะไกลทั้งหมดที่ไม่ได้อยู่ในเครื่องนั้นจะเป็น:diff <(git tag | sort) <( git ls-remote --tags origin | cut -f2 | grep -v '\^' | sed 's#refs/tags/##' | sort) | grep ">" | cut -c3- | xargs -I{} git push origin :refs/tags/{}
Daniel Gehriger

หากคุณจำเป็นต้องสร้างความแตกต่างและแสดงแฮชการกระทำในเวลาเดียวกัน: diff <(git show-ref --tags | grep -v '{}' | awk '{print $1 " " $2}') <(git ls-remote --tags origin | grep -v '{}' | awk '{print $1 " " $2}')
piroux

การเปรียบเทียบนี้เป็นสิ่งที่ฉันต้องการจริงๆขอบคุณ สิ่งเดียวที่ฉันสับสนคือมันส่งสัญญาณออกมาสองสามบรรทัดซึ่งไม่ได้ขึ้นต้นด้วยลูกศร<แต่ตัวเลขตามด้วยเครื่องหมายจุลภาคและจากนั้นอักขระสามตัวแรกของแฮชคอมมิท (?) เช่น7,8d4...
Kay

3

เพิ่งเพิ่มคำสั่ง git sync-local-tags ใน pivotal_git_scripts Gem fork บน GitHub:

https://github.com/kigster/git_scripts

ติดตั้งอัญมณีจากนั้นเรียกใช้ "git sync-local-tags" ในที่เก็บของคุณเพื่อลบแท็กท้องถิ่นที่ไม่มีอยู่ในระยะไกล

หรือคุณสามารถติดตั้งสคริปต์นี้ด้านล่างและเรียกมันว่า "git-sync-local-tags":


#!/usr/bin/env ruby

# Delete tags from the local Git repository, which are not found on 
# a remote origin
#
# Usage: git sync-local-tags [-n]
#        if -n is passed, just print the tag to be deleted, but do not 
#        actually delete it.
#
# Author: Konstantin Gredeskoul (http://tektastic.com)
#
#######################################################################

class TagSynchronizer
  def self.local_tags
    `git show-ref --tags | awk '{print $2}'`.split(/\n/)
  end

  def self.remote_tags
    `git ls-remote --tags origin | awk '{print $2}'`.split(/\n/)
  end

  def self.orphaned_tags
    self.local_tags - self.remote_tags
  end

  def self.remove_unused_tags(print_only = false)
    self.orphaned_tags.each do |ref|
      tag = ref.gsub /refs\/tags\//, ''
      puts "deleting local tag #{tag}"
      `git tag -d #{tag}` unless print_only
    end
  end
end

unless File.exists?(".git")
  puts "This doesn't look like a git repository."
  exit 1
end

print_only = ARGV.include?("-n")
TagSynchronizer.remove_unused_tags(print_only)

3

ฉันรู้ว่าฉันมางานปาร์ตี้ช้า แต่ตอนนี้มีคำตอบที่รวดเร็วสำหรับเรื่องนี้:

git fetch --prune --prune-tags # or just git fetch -p -P

ใช่ตอนนี้เป็นตัวเลือกในการดึงข้อมูล

หากคุณไม่ต้องการดึงข้อมูลและเพียงตัด:

git remote prune origin

1

วิธีการเกี่ยวกับสิ่งนี้ - วางแท็กท้องถิ่นทั้งหมดแล้วดึงข้อมูลอีกครั้ง พิจารณา repo ของคุณอาจมี submodules:

git submodule foreach --recursive  'git tag | xargs git tag -d'
(alternatively, "for i in `find .git  -type d -name '*tags*'`; do rm -f $i/*;  done")
git fetch -t
git submodule foreach --recursive git fetch -t

1

TortoiseGit สามารถเปรียบเทียบแท็กได้ทันที

บันทึกด้านซ้ายอยู่บนรีโมตขวาอยู่ที่โลคัล

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

การใช้คุณสมบัติเปรียบเทียบแท็กของกล่องโต้ตอบซิงค์:

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

ดูเพิ่มเติมTortoiseGit ฉบับที่ 2973


1

คำตอบเดียวกับ @Richard W แต่สำหรับ Windows (PowerShell)

git tag | foreach-object -process { git tag -d $_ }
git fetch -t

1

ฉันเพิ่มคำสั่งSourceTreeเป็น Custom Action บน MacOS ของฉัน


การตั้งค่าCustom ActionsโดยSourcetree-> Preferences...->Custom Actions


Script to runต้องเป็นgitเส้นทาง

ฉันใช้git fetch --prune --prune-tags originเพื่อซิงค์แท็กจากระยะไกลกับท้องถิ่น

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


0

ในเวอร์ชัน git ใหม่ (เช่น v2.26.2)

-P, --prune-tags ก่อนที่จะดึงข้อมูลให้ลบแท็กท้องถิ่นที่ไม่มีอยู่บนรีโมตถ้าเปิดใช้งาน --prune ตัวเลือกนี้ควรใช้อย่างระมัดระวังมากขึ้นซึ่งแตกต่างจาก --prune มันจะลบการอ้างอิงในท้องถิ่นใด ๆ (แท็กท้องถิ่น) ที่ได้รับการสร้างขึ้น ตัวเลือกนี้เป็นการจดชวเลขสำหรับการระบุแท็กอย่างชัดเจนพร้อมกับ --prune ดูการอภิปรายเกี่ยวกับสิ่งนั้นในเอกสารประกอบ

ดังนั้นคุณต้องวิ่ง:

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