Jak mogę przenieść znacznik na gałęzi git do innego zatwierdzenia?


858

W gałęzi master utworzyłem tag o nazwie v0.1tak:

git tag -a v0.1

Ale potem zdałem sobie sprawę, że wciąż muszę wprowadzić pewne zmiany, aby połączyć się w master w wersji 0.1, więc to zrobiłem. Ale teraz mój v0.1tag utknął (aby przywołać analogię karteczek post-it) niewłaściwe zatwierdzenie. Chcę, aby utknęła na ostatnim zatwierdzeniu na master, ale zamiast tego utknęła na drugim ostatnim zatwierdzeniu na master.

Jak mogę przenieść go do ostatniego zatwierdzenia na master?

Odpowiedzi:


1199

Użyj -fopcji, aby git tag:

-f
--force

    Replace an existing tag with the given name (instead of failing)

Prawdopodobnie chcesz użyć -fw połączeniu z, -aaby wymusić utworzenie znacznika z adnotacjami zamiast tagu bez adnotacji.

Przykład

  1. Usuń znacznik na dowolnym pilocie przed naciśnięciem przycisku

    git push origin :refs/tags/<tagname>
    
  2. Zamień znacznik, aby odwoływał się do ostatniego zatwierdzenia

    git tag -fa <tagname>
    
  3. Wciśnij znacznik do zdalnego źródła

    git push origin master --tags
    

90
Dobrym pomysłem może być usunięcie znacznika na dowolnym pilocie przed wypchnięciem, wykonując następujące czynności: git push origin :refs/tag/<tagname>a następnie zrób git tag -fa <tagname>i zrób git push origin master --tags. W przeciwnym razie możesz skończyć z dziwnymi rzeczami na liście ref na pilocie z dołączonymi znakami ^ i {}. Dziękujemy Danowi na codebasehq.com za zwrócenie na to uwagi.
eedeep

47
@eedeep: Drobne poprawki - zamiast :refs/tag/<tagname>tego powinny być :refs/tags/<tagname>.
Ben Hocking

8
Działa to tylko wtedy, gdy nie zepchnąłeś kodu ze swojego komputera. Jeśli tak, najlepszą odpowiedzią jest „na świecie jest mnóstwo liczb”, ponieważ prawdopodobnie nie jest to warte kłopotów.
Chris Huang-Leaver,

33
Jeśli już wypchnąłeś tag, nadal możesz zaktualizować tag zdalny za pomocą wymuszonego pushgit push -f origin <tagname>
rc_luke

11
To, czego nie wspomniano tutaj ani w dokumentach, to fakt, że rzeczywiście powoduje to przeniesienie wiadomości tagu, jeśli nie zostanie podana nowa wiadomość.
Twonky,

259

Mówiąc dokładniej, musisz wymusić dodanie tagu, a następnie nacisnąć opcję --tags i -f:

git tag -f -a <tagname>
git push -f --tags

171

Podsumowując, jeśli Twój pilot jest wywoływany origini pracujesz w masteroddziale:

git tag -d <tagname>
git push origin :refs/tags/<tagname>
git tag <tagname> <commitId>
git push origin <tagname>
  • Wiersz 1 usuwa tag w lokalnej środowisku.
  • Wiersz 2 usuwa tag w zdalnej env.
  • Wiersz 3 dodaje znacznik do innego zatwierdzenia
  • Linia 4 przekazuje zmianę do pilota

Możesz także wymienić wiersz 4, aby git push origin --tagswypchnąć wszystkie zmiany tagami z lokalnych zmian.

Na podstawie @ stuart-golodetz, @ greg-hewgill, @eedeep, @ ben-hocking, komentarze pod ich odpowiedziami i komentarze NateS pod moją odpowiedzią.


87

Usuń go za pomocą, git tag -d <tagname>a następnie utwórz ponownie przy poprawnym zatwierdzeniu.


3
@eedeep: Myślę, że odpowiedź Grega jest tutaj lepsza, aby była uczciwa.
Stuart Golodetz

Nie komplikuj. Usuń to, zrób to, co zrobiłeś wcześniej.
ooolala,

1
To powinna być zaakceptowana odpowiedź ze względu na jej prostotę. Nie używa też nadmiernie siły -f.
chinnychinchin

48

Staram się unikać kilku rzeczy podczas korzystania z Git.

  1. Wykorzystanie wiedzy na temat elementów wewnętrznych, np. Referencji / tagów. Staram się używać wyłącznie udokumentowanych poleceń Git i unikam używania rzeczy, które wymagają znajomości wewnętrznej zawartości katalogu .git. (To znaczy traktuję Git jako użytkownika Git, a nie programistę Git).

  2. Użycie siły, gdy nie jest wymagane.

  3. Przesadzanie. (Pchanie gałęzi i / lub wielu tagów, aby uzyskać jeden tag tam, gdzie chcę.)

Oto moje pokojowe rozwiązanie zmiany tagu, zarówno lokalnie, jak i zdalnie, bez znajomości wewnętrznych elementów Git.

Używam go, gdy poprawka oprogramowania ostatecznie ma problem i wymaga aktualizacji / ponownego wydania.

git tag -d fix123                # delete the old local tag
git push github :fix123          # delete the old remote tag (use for each affected remote)
git tag fix123 790a621265        # create a new local tag
git push github fix123           # push new tag to remote    (use for each affected remote)

githubto przykładowa nazwa zdalna, fix123to przykładowa nazwa znacznika i 790a621265przykładowe zatwierdzenie.


26

Zostawię tutaj kolejną formę tego polecenia, która odpowiada moim potrzebom. Byłem
tag, v0.0.1.2który chciałem przenieść.

$ git tag -f v0.0.1.2 63eff6a

Updated tag 'v0.0.1.2' (was 8078562)

I wtedy:

$ git push --tags --force

dobrze, dziękuję, 2 proste i proste polecenia
Sérgio

10

Jeszcze jeden sposób:

Przenieś tag w zdalnym repozytorium (w razie potrzeby zastąp HEAD innym).

$ git push --force origin HEAD:refs/tags/v0.0.1.2

Pobierz zmiany z powrotem.

$ git fetch --tags

Jest to bardziej „transakcyjne” niż inne odpowiedzi.
Justin M. Keyes

9

Alias, aby przenieść jeden znacznik do innego zatwierdzenia.

W swojej próby, aby przenieść popełnić z e2ea1639 hash zrobić: git tagm v0.1 e2ea1639.

W przypadku tagów wypychanych użyj git tagmp v0.1 e2ea1639.

Oba aliasy przechowują oryginalną datę i wiadomość. Jeśli używasz git tag -d, utraciłeś oryginalną wiadomość.

Zapisz je w swoim .gitconfigpliku

# Return date of tag. (To use in another alias)
tag-date = "!git show $1 | awk '{ if ($1 == \"Date:\") { print substr($0, index($0,$3)) }}' | tail -2 | head -1 #"

# Show tag message
tag-message = "!git show $1 | awk -v capture=0 '{ if(capture) message=message\"\\n\"$0}; BEGIN {message=\"\"}; { if ($1 == \"Date:\" && length(message)==0 ) {capture=1}; if ($1 == \"commit\" ) {capture=0}  }; END { print message }' | sed '$ d' | cat -s #"

### Move tag. Use: git tagm <tagname> <newcommit> 
tagm = "!GIT_TAG_MESSAGE=$(git tag-message $1) && GIT_COMMITTER_DATE=$(git tag-date $1) && git tag-message $1 && git tag -d $1 && git tag -a $1 $2 -m \"$GIT_TAG_MESSAGE\" #"

### Move pushed tag. Use: git tagmp <tagname> <newcommit> 
tagmp = "!git tagm $1 $2 && git push --delete origin $1 && git push origin $1 #"

1

Jeśli chcesz przenieść tag z adnotacjami, zmieniając tylko ukierunkowane zatwierdzenie, ale zachowując komunikat adnotacji i inne użycie metadanych:

moveTag() {
  local tagName=$1
  # Support passing branch/tag names (not just full commit hashes)
  local newTarget=$(git rev-parse $2^{commit})

  git cat-file -p refs/tags/$tagName | 
    sed "1 s/^object .*$/object $newTarget/g" | 
    git hash-object -w --stdin -t tag | 
    xargs -I {} git update-ref refs/tags/$tagName {}
}

użycie: moveTag <tag-to-move> <target>

Powyższa funkcja została opracowana przez odwołanie do teerapap / git-move-annotated-tag.sh .


1
Wydaje się, że nie jest to już potrzebne: git tag -f -a my_tagzachowuje już wiadomość z poprzedniej wiadomości (w wersji git 2.11.0).
Matthijs Kooijman,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.