더 이상 원격 저장소에없는 로컬 자식 태그를 제거하십시오.


468

배포 프로세스의 일부로 git에서 태그를 사용합니다. 때때로이 태그를 원격 저장소에서 제거하여 정리하려고합니다.

이것은 매우 간단합니다. 한 명의 사용자가 한 세트의 명령에서 로컬 태그와 원격 태그를 삭제합니다. 우리는 두 단계를 결합한 작은 쉘 스크립트를 가지고 있습니다.

두 번째 (3, 4, ...) 사용자는 이제 더 이상 리모컨에 반영되지 않는 로컬 태그를 갖습니다.

git remote prune origin원격 분기가 삭제 된 로컬 추적 분기를 정리하는 것과 비슷한 명령을 찾고 있습니다.

또는을 통해 반환 된 로컬 태그와 비교하기 위해 원격 태그를 나열하는 간단한 명령을 사용할 수 있습니다 git tag -l.


2
나는 가지 치기 태그 제거를 지원하기 위해 git의 새로운 기능을 제안했다 : 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
아래 답변 중 하나에서 댓글을 재개시 하나는이 구문을 사용할 수 있습니다 자식 2.18.0와 적어도 : --prune --prune-태그 기원 가져 GIT
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

이 목록에 의해 생성 된 태그와 로컬에있는 태그를 비교하기 위해 bash 스크립트를 확실히 만들 수 있습니다. 를 살펴보면 ) git show-ref --tags와 같은 형식으로 태그 이름이 생성됩니다 git ls-remote.


제쳐두고, git show-ref당신이 원하는 것과 반대되는 옵션이 있습니다. 다음 명령은 로컬에 없는 원격 브랜치의 모든 태그를 나열합니다 .

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

고마워 마이크. 비교를 위해 각 목록을 사용하여 내 bash 스크립트를 굴릴 것입니다.
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. 로컬 저장소에서 모든 태그를 삭제하십시오. xargs는 "tag -l"의 각 태그 출력을 "tag -d"의 명령 줄에 배치합니다. 이것이 없으면 git은 stdin (silly git)을 읽지 않기 때문에 아무것도 삭제하지 않습니다.

  2. 원격 저장소에서 모든 활성 태그를 가져옵니다.

이것은 심지어 Windows에서도 잘 작동합니다.


57
이것은 StackOverflow에서 내가 가장 좋아하는 자식 대답이어야합니다. 그것은 지식, 단순성 및 속임수를 결합하여 모든 것을 설명합니다. 위대한
tymtam

25
별도의 대답에 언급 한 바와 같이,하지 원격 REPO이 모두 삭제 지역 태그, 사람은 분명히 다시 만들어-되지 않습니다
두 번째

13
그러나 이것은 완전히 불필요합니다. 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

최신 정보

커밋 e66ef7ae6f31f2로 인해 최신 버전의 git (v1.9.0으로 시작)에서는 작동하지 않습니다. . 일부 사람들에게는 효과가 있었으므로 삭제하고 싶지 않습니다.

v1.7.8 이후의 모든 Git 버전과 함께 "Chad Juliano"에서 제안한대로 다음 명령을 사용할 수 있습니다.

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

와일드 카드 확장을 피하려면 태그 부분을 따옴표로 묶어야합니다 (예 : Windows에서).

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

2
Windows 용 Git 1.9.4-preview20140611과 함께 제공되는 설명서를 참조합니다 (그리고 모든 이전 버전이 의심됩니다). "git fetch --help"[quote]를 사용하여 해당 문서에 액세스합니다. 태그는 기본 태그 자동 추적 또는 --tags 옵션으로 인해 페치 된 경우에만 제거되지 않습니다. [/ quote]
Félix Cantournet

2
git fetch --prune <remote> +refs/tags/*:refs/tags/*ZSH에서는 작동하지 않지만 BASH에서는 작동합니다.
Alex

3
@Alex 그것은 단지 zsh가 확장 되었기 때문 *이지만 작은 따옴표를 사용하면 괜찮습니다.
NSF

3
@ v01pe는 - 지금이 자식 바로 가기를 사용할 수 --prune-태그 치기 섹션에서 문서에 설명 된 자식 2.17.0 가입일 : git-scm.com/docs/git-fetch/2.17.0 문서에서 : - -prune-tags 옵션은 원격의 참조 스펙에 refs / tags / * : refs / tags / *를 선언 한 것과 같습니다. 동등 물 : git fetch origin --prune --prune-tagsOR git fetch origin --prune 'refs/tags/*:refs/tags/*'OR 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원격 추적 분기 및 태그를 모두 제거하십시오. git 2.18 버전에서 확인되었습니다.
Number945

158

리모컨에 존재하는 태그 만 원한다면 모든 로컬 태그를 삭제하십시오.

$ git tag -d $(git tag)

그런 다음 모든 원격 태그를 가져옵니다.

$ git fetch --tags

1
완벽하게, 나는 태그를 찾지 못한 xargs에 문제가 있었다
Marcio Toshio

3
@ocroquette, 나는 그것이 어떻게 더 좋은지 잘 모르겠습니다 xargs. 태그보다 많 ARG_MAX거나 비슷한 제한이 있으면 작동하지 않습니다. 가능하지는 않지만 가능하기 때문에 이것이 xargs좋습니다.
Paul Draper

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을 구성 할 수도 있습니다.

git config fetch.pruneTags true

특정 리모컨에서 가져올 때만 태그를 제거하려는 경우 remote.<remote>.pruneTags옵션을 사용할 수 있습니다 . 예를 들어 원점에서 가져올 때 항상 다른 태그를 가져올 때 태그를 제거하려면,

git config remote.origin.pruneTags true


우수한! "git-shell died of signal 13"으로 git push failure가 발생했습니다. http.postbuffer가 증가해도 효과가 없습니다. GIT_TRACE_PACKET 및 GIT_TRACE를 활성화 한 후 "-prune-tags"를 사용하여 잘못된 참조 / 태그를 푸시하는 것을 확인했습니다. 고마워요!
Ivellios

78

git fetchv1.7.8 이후의 모든 버전의 Git 은 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

Git v1.9.0에서 "--prune"동작의 "--tags"동작이 어떻게 변경되었는지에 대한 자세한 내용은 https://github.com/git/git/commit/e66ef7ae6f31f246dead62f574cc2acb75fd001c를 참조하십시오.


7
이것이 최고의 답변이되어야합니다. bash, 파이프 및 xargs가없는 단일 git 명령입니다.
G. Sylvie Davies '

1
대체 originupstream상류에 따라 내 로컬 태그를 수정 자식; 다음으로 git push origin :<deleted-tag-name>GitHub 포크를 업데이트하여 삭제 된 태그를 제거했습니다.
leanne

3
적어도 git 2.18.0에서는 다음과 같은 구문을 사용할 수 있습니다.git fetch --prune --prune-tags origin
Martin

3
git 2.17.0부터 --prune-tags 옵션이 포함되어 다음 문서에서 동등한 명령으로 PRUNING 섹션에 자세히 설명되어 있습니다. git-scm.com/docs/git-fetch/2.17.0 git fetch origin --prune --prune-tags OR git fetch origin --prune 'refs/tags/*:refs/tags/*' OR git fetch <url of origin> --prune --prune-tags ORgit fetch <url of origin> --prune 'refs/tags/*:refs/tags/*'
mkisaacs

8

Git은 기본적으로 로컬 태그 정리를 지원합니다.

git fetch --tags --prune

이 명령은 최신 태그를 가져 와서 삭제 된 모든 태그를 제거합니다.


"--prune-tags"대신 "--prune"이어야합니다. 그렇지 않으면 감사합니다.
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/##' 원격 태그 경로 목록에서 태그 이름 만 구문 분석합니다.
  • 마지막으로 우리는 두 목록 각각을 정렬하고 diff

"<"로 시작하는 줄은 더 이상 원격 저장소에없는 로컬 태그입니다. 그것들이 적 으면 하나씩 하나씩 수동으로 제거 할 수 있으며, 많으면 자동화하기 위해 더 많은 그 리핑 및 배관을 수행합니다.


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...
케이

3

GitHub에서 git sync-local-tags 명령을 pivotal_git_scripts Gem fork에 추가했습니다.

https://github.com/kigster/git_scripts

gem을 설치 한 다음 리포지토리에서 "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

어때요-모든 로컬 태그를 삭제 한 다음 다시 가져 오시겠습니까? 리포지토리에 하위 모듈이 포함되어 있다고 생각하면 :

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

SourceTreeMacOS 에서 명령을 사용자 정의 조치로 추가합니다 .


설정 Custom Actions에서 Sourcetree-> Preferences...->Custom Actions


Script to rungit경로 가되어야합니다 .

git fetch --prune --prune-tags origin태그를 원격에서 로컬로 동기화 하는 데 사용 합니다.

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오


0

새로운 git 버전 (v2.26.2와 같은)

-P, --prune-tags 가져 오기 전에 --prune이 활성화 된 경우 원격에 더 이상 존재하지 않는 로컬 태그를 제거하십시오. 이 옵션은 --pr과 달리보다 신중하게 사용해야하며, 생성 된 모든 로컬 참조 (로컬 태그)를 제거합니다. 이 옵션은 --prune과 함께 명시 적 태그 참조 스펙을 제공하기위한 약식입니다. 설명서에서 이에 대한 설명을 참조하십시오.

따라서 다음을 실행해야합니다.

git fetch august --prune --prune-tags
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.