자식 태그를 다시 만든 후 "태그가 이미 원격에 존재합니다"오류


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. 생성 된 태그 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 --tagsgit push origin --tags
sawe

답변:


175

편집, 2016 년 11 월 24 일 :이 답변은 분명히 인기가 있으므로 여기에 메모를 추가하고 있습니다. 중앙 서버에서 태그 를 교체 하면 이전 태그 (태그가 이미있는 중앙 서버 저장소의 복제본)를 가진 사람은 기존 태그를 유지할 수 있습니다. 따라서 이것이 수행 방법을 알려주는 동안 실제로 하고 싶습니다 . 이미 "잘못된"태그가있는 모든 사람이 "잘못된 태그" 를 삭제 하고 새 "올바른 태그"로 교체해야합니다.

Git 2.10 / 2.11에서 테스트 한 결과 이전 태그를 유지하는 것이 실행중인 클라이언트의 기본 동작 git fetch이며 업데이트는 실행중인 클라이언트의 기본 동작입니다 git fetch --tags.

(원래 답변은 다음과 같습니다.)


태그 푸시를 요청하면 git push --tags(커밋 및 필요한 기타 객체 및 푸시 설정의 다른 참조 업데이트와 함께) 형식의 업데이트 요청을 원격으로 보냅니다 . (그러나 각 태그마다 하나를 많이 보냅니다.)new-sha1 refs/tags/name

업데이트 요청은 원격에 의해 수정되어 old-sha1 (또는 태그마다 하나씩) 수신 된 후 및 / 또는 업데이트 훅 (원격에있는 후크)에 전달됩니다. 이러한 후크는 태그 생성 / 삭제 / 업데이트 허용 여부를 결정할 수 있습니다.

old-sha1값은 모두 제로 "NULL"SHA-1, 태그가 생성되는 경우이다. 그만큼new-sha1 태그가 삭제되는 경우 널 SHA-1입니다. 그렇지 않으면 두 SHA-1 값이 모두 유효하고 유효한 값입니다.

후크가없는 경우에도 일종의 "내장 후크"가 실행됩니다. "force"플래그를 사용하지 않으면 리모콘이 태그 이동을 거부합니다 ( "내장 후크"는 항상 두 가지 모두 OK 임) "추가"및 "삭제"). 보고있는 거부 메시지는이 내장 후크에서 나옵니다. (실제로이 내장 후크는 빨리 감기되지 않는 분기 업데이트도 거부합니다.) 1

그러나 여기에 무슨 일이 일어나고 있는지 이해하는 열쇠가 있습니다. git push 는 리모컨에 현재 해당 태그가 있는지 여부와 그에 따른 SHA-1 값이 무엇인지 알 수 없습니다. "내 SHA-1 값과 함께 전체 태그 목록이 있습니다"라고만 표시됩니다. 리모콘은 값을 비교하고 추가 및 / 또는 변경이있는 경우 해당 값에 대한 후크를 실행합니다. (같은 태그의 경우에는 아무 것도 수행하지 않습니다. 태그가없는 태그의 경우 아무 것도 수행하지 않습니다!)

태그를 로컬에서 삭제하면 push푸시만으로 태그가 전송되지 않습니다. 리모콘은 변경하지 않아야한다고 가정합니다.

로컬에서 태그를 삭제 한 다음 새 위치를 가리키는 태그를 생성하면을 push누르면 푸시가 태그를 전송하고 원격에서이 태그를 태그 변경으로 인식하고 강제 푸시가 아닌 한 변경을 거부합니다.

따라서 두 가지 옵션이 있습니다.

  • 강제 푸시를 수행하거나
  • 리모컨에서 태그를 삭제하십시오.

후자 태그를 로컬로 삭제하고 ing이 효과가 없지만 git push2 를 통해 가능 push합니다. 리모컨의 이름이 origin이고 삭제하려는 태그가 다음과 같다고 가정합니다 dev.

git push origin :refs/tags/dev

이것은 리모콘이 태그를 삭제하도록 요청합니다. dev로컬 저장소에 태그 가 있는지 여부 는 관련이 없습니다. 이런 종류의 push와 함께, refspec로, 순수 삭제 푸시입니다.:remoteref

리모컨은 추가 된 후크에 따라 태그 삭제를 허용하거나 허용하지 않을 수 있습니다. 삭제를 허용하면 태그가 사라지고 두 번째 git push --tagsdev커밋 또는 주석이 달린 태그 저장소 객체를 가리키는 로컬 태그가 있으면 새 dev태그를 보냅니다 . dev이제 원격에서 새로 생성 된 태그가 될 것이므로 원격에서 푸시를 허용 할 것입니다 (다시 추가 된 후크에 따라 다름).

강제 푸시가 더 간단합니다. 당신이 업데이트 아무것도 확실하지 수 있도록하려면 다른 태그보다 단지 이야기 git push만 하나 refspec를 밀어 :

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

(참고 : --tags하나의 태그 참조 스펙 만 명시 적으로 푸시하는 경우 필요하지 않습니다 ).


1 물론, 이유는 이 내장 된 후크 도움이되는 행동을 강제하기위한 그 다른 사용자가 동일한 원격 REPO 기대 : 가지 되감기하지 않고, 태그가 움직이지 않는다. 강제 푸시하는 경우 다른 사용자에게이 작업을 수행하고 있음을 알리면 문제를 해결할 수 있습니다. "태그가 전혀 움직이지 않습니다"는 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에서 테스트했으며, 당신은 --force2 단계 업데이트 기술 이 필요하다 .
torek

2
@John ツ : update : 릴리스 노트 에 따르면 1.8.2부터 새로운 동작 입니다. 이것을 각주 1로 편집하겠습니다.
torek

이 상황에 어떻게 도달했는지 모르지만 태그가 삭제되어 트리스에서 다시 만들어졌습니다.
RiggsFolly

4
제다이가 아니라면 어떻게 강제 푸시를합니까?
Fonix

54

Mac SourceTree에서는 모든 태그 푸시 확인란 만 선택 해제하십시오 .

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


3
hahahah 너무 간단한 사람, 나는 받아 들여진 대답을 읽고 있었고 나는 이것을 속일 것이라고 생각했다.
MegaManX

10
이것은 실제로 문제를 해결하지 않고 극복하는 것입니다. 이렇게하면 원격 및 로컬에서 태그 이름이 일치하지 않습니다.
amalBit

1
Windows 버전에서도 작동합니다! 명령 프롬프트에서 무슨 일이 일어나고 있는지 신경 쓰지 않는 소스 트리 사용자를 생략하는 오랫동안 받아 들여진 대답을 읽지 못하게 해 주셔서 감사합니다 :)
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

끝난


12

이 문제에 늦었거나 이미 답변을받은 것으로 보이지만 수행 할 수있는 작업은 다음과 같습니다. (내 경우에는 로컬에 하나의 태그 만있었습니다 .. :

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 플래그 를 사용하는 이유 는 다른 충돌을 피할 수 있도록 원격 작업 위에 작업을 배치하기 때문입니다.

또한, 내가 이해하지 못하는 것은 왜 dev태그 를 삭제 하고 다시 만드는 것입니까 ??? 태그는 소프트웨어 버전 또는 마일스톤을 지정하는 데 사용됩니다. 자식 태그의 예 v0.1dev, v0.0.1alpha, v2.3-cr(CR - 후보 자료) 등등 ..


이 문제를 해결할 수있는 또 다른 방법은 문제를 해결하고 리모컨 git reflog에서 dev태그 를 누른 순간으로 이동하는 것 입니다. (가) 복사 ID를 커밋 하고 git reset --mixed <commmit_id_from_reflog>당신이 당신의 태그를 알고이 방법은 당신이 그것을 밀어 순간에 원격으로 동기화이고 충돌은 발생하지 않습니다.


예를 들어 현재 프로덕션중인 커밋에 태그를 지정하려는 경우. 그런 다음 특정 커밋에서 이전 프로덕션 태그를 삭제하고 새 프로덕션 릴리스 후 커밋에 대한 새 태그를 작성하고 푸시해야합니다.
Ville Miekk-oja

2

Windows SourceTree에서을 선택하십시오 Push all tags to remotes.

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


0

여기에 좋은 답변이 있습니다. 특히 @torek의 것 입니다. 나는 서두르는 사람들을 위해 약간의 설명 으로이 해결 방법을 추가 할 것이라고 생각했습니다.

요약하면, 태그를 로컬로 이동하면 널이 아닌 커밋 값에서 다른 값으로 태그가 변경됩니다. 그러나 git (기본 동작)은 null이 아닌 원격 태그를 변경할 수 없으므로 변경 사항을 적용 할 수 없습니다.

해결 방법은 태그를 삭제하고 모든 리모컨을 제거하는 것입니다. 그런 다음 동일한 태그를 만들고 푸시하십시오.

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