Jak mogę edytować istniejącą wiadomość w git?

225

W naszym repozytorium git mamy kilka tagów z adnotacjami. Starsze tagi zawierają fałszywe wiadomości, które chcielibyśmy zaktualizować, aby były w naszym nowym stylu.

% git tag -n1
v1.0 message
v1.1 message
v1.2 message
v2.0 Version 2.0 built on 15 October 2011.

W tym przykładzie chcielibyśmy, aby komunikaty w wersji 1.x wyglądały jak komunikaty w wersji 2.0. Czy ktoś wie, jak byśmy to zrobili?

jared
źródło
2
Uwaga: w przypadku Git 2.17 (Q2 2018) wystarczyłoby proste git tag -m "A message" --edit v1.0. Zobacz moją odpowiedź poniżej
VonC
Powiązane: Jak zmienić nazwę tagu Git?
Stevoisiak,
@VonC Próbowałem i otrzymałem fatal: tag 'v6.6.2' already existsużywając 2.17.0.
Josh Habdas
1
Zawsze możesz usunąć poprzedni tag i zrobić to ponownie.
RoadRunner

Odpowiedzi:

264

git tag <tag name> <tag name>^{} -f -m "<new message>"

Spowoduje to utworzenie nowego znacznika o tej samej nazwie (poprzez zastąpienie oryginału).

Andy
źródło
7
Czy to utrzymuje datę oryginalnego tagu?
James M. Greene
16
Odpowiedź na moim komentarzu pytanie: Tak, to ma zmienić datę. :(
James M. Greene
10
Zobacz sekcję „O tagach backdating” w git tag --help.
dahlbyk
6
Należy również zauważyć, że możesz również dołączyć wiele wiadomości (są one oddzielone nową linią - na GitHub)git tag <tag name> <tag name> -f -m "<new message>" -m "<new message>" -m "<new message>"
Blair McMillan
5
@ChrisMorley patrzy na moją odpowiedź poniżej stackoverflow.com/a/23532519/603949 - w skrócie, użyj, <tag name>^{}gdy chcesz zastąpićold tag
Sungam
87

Aby zaktualizować złożoną wiadomość, wystarczy określić opcję znacznika z adnotacją za pomocą -alub opcję znacznika z podpisem -s:

git tag <tag name> <tag name>^{} -f -a

Spowoduje to otwarcie edytora z zawartością starej wiadomości tagu .

Eric Hu
źródło
39

git tag <tag name> <tag name>^{} -f -a

To jest ulepszenie: bez ^{}niego utworzy nowy obiekt znacznika, który będzie odwoływał się do starego obiektu znacznika, gdzie oba będą miały tę samą nazwę znacznika.

<tag name>^{} rozwiąże tag / referencję, dopóki nie znajdzie pierwszego skrótu zatwierdzenia.

Sungam
źródło
4
@BrentFoust, który działa tylko wtedy, gdy twoja głowa jest na oznaczonym zatwierdzeniu usage: git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]
Sungam
33

TL; DR

Możesz to zrobić, usuwając tag i odtwarzając go ponownie, fałszując datę i autora:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

Cała historia:

Opierając się na odpowiedzi Sungram (pierwotnie zaproponowanej jako edycja):

1. Zaakceptowana odpowiedź

To poprawa w stosunku do odpowiedzi Andy'ego i Erica Hu . Ich odpowiedzi utworzą nowy obiekt znacznika, który odwołuje się do starego obiektu znacznika i oba będą miały tę samą nazwę.

Aby to zilustrować, rozważ następujące kwestie:

> git tag tag1 tag1 -f -a  # accepted answer
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
260ab7928d986472895b8c55e54569b3f3cb9517 tag1
a5797673f610914a45ef7ac051e3ee831a6e7c25 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Original description]

[tagged commit details]

2. Poprawa Sungram

Użycie <tag name>^{}jako drugiego argumentu git tagspowoduje usunięcie wszystkich poprzednich znaczników o tej samej nazwie.

Rozważ kontynuację poprzedniej sesji terminalowej:

> git tag tag1 tag1^{} -f -a  # suggested improvement
> git rev-list --objects -g --no-walk --all
[ example output: ]
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
75f02acacfd7d91d55b5bcfdfb1f00aebeed15e3 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17 

> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of updated tag]
[Updated description]

[tagged commit details]

3. Zapisz datę

Na koniec, jeśli chcesz zachować datę oryginalnego tagu jako datę zaktualizowanego tagu, użyj magii awk (lub podobnej) lub po prostu wklej datę, którą chcesz. Poniższy przykład zastępuje drugi przykład (w przeciwnym razie pierwotna data zostałaby utracona z powodu zastąpienia ):

> GIT_COMMITTER_DATE="$(git show tag1 |                              # get info about the tag cascade including the date original of the original tag
> awk '{
>     if ($1 == "Date:") {
>         print substr($0, index($0,$3))
>     }
> }' |                                                               # extract all the dates from the info
> tail -2 | head -1)"                                               `# get the second to last date, as the last one is the commit date` \
> git tag tag1 tag1^{} -a -f                                         # finally, update the tag message, but save the date of the old one
>
> git rev-list --objects -g --no-walk --all
6bdcc347fca041a5138f89fdf5276b3ebf9095d5
e18c178f2a548b37799b100ab90ca785af1fede0 tag1
f22d6308c3cd330a3b0d86b9bf05562faf6b6f17
> git show tag1
tag tag1
Tagger: [tagger]
Date:   [date of original tag]
[Updated description]

[tagged commit details]

Bibliografia:

4. DIY

Alternatywnie do aktualizacji tagów, możesz je po prostu usunąć i utworzyć ponownie. Jak się okazuje, aktualizacja po prostu dodaje nowy tag i sprawia, że ​​wskazuje on na stary, lub, alternatywnie, po prostu domyślnie usuwa stary i tworzy nowy, aby wskazywać na to samo zatwierdzenie.

Możesz to osiągnąć, wydając:

> git tag -d <tag-name>
> [GIT_COMMITTER_DATE=<original-commit-date>] \
> [GIT_AUTHOR_NAME=<original-author-name>] \
> git tag <tag-name> [commit]

Oto [optional]pole opcjonalne; <required>jest polem wymaganym. Oczywiście po git tagpoleceniu możesz dodać dowolne flagi .

stanm
źródło
3
Dziękujemy za zwrócenie uwagi, że „Ich odpowiedzi utworzą nowy obiekt znacznika”!
cwhsu
Cytując Andreasa Schwaba : The tagger is controlled by the committer info. (...) GIT_COMMITTER_{NAME,EMAIL}. A tagger isn't really an author.
Ivan Vučica
11

Rozwiązanie @Andy

git tag <tag-name> <tag-name> -f -a

jest źle . Po tym, z

git show

polecenie, zobaczymy tagi stosu o tej samej nazwie.

Dodaje nowy tag o tej samej nazwie i nową wiadomość przy zatwierdzeniu <tag-name>. Ale to nie usuwa starej etykiety. Jest to szczególny przypadek tego polecenia:

git tag [<commit> | <old-tag>] <tag-name>

Ale tak <old-tag>samo jest z <tag-name>.


Prawidłowe rozwiązanie jest proste, wystarczy zaktualizować tag, jest OK.

git tag <tag-name> -f -a

Pamiętaj, tylko JEDEN tutaj.

Jeśli chcemy zmienić tag, który nie jest HEAD, potrzebujemy dodatkowego <commit>argumentu.

git tag <commit> <tag-name> -f -a
liuyang1
źródło
TAK! Masz rację. Dzięki za wskazanie tego. Po ponownym napisaniu tagu kilka razy z adnotacjami sprawdziłem swój tag git show <tag>i widzę wszystkie poprzednie wydania.
Manoel Vilela
Problem polega na tym: jeśli potrzebuję zaktualizować jakiś tag, który nie jest HEAD, przekazanie dodatkowego <commit>tagu jest pusty. Spodziewałem się, że stary tag po prostu będzie edytować. Czy jest jakiś sposób?
Manoel Vilela
Należy pamiętać, że rozwiązanie Andy'ego zostało zaktualizowane od momentu odpowiedzi. Być może byłoby miło zacząć od odpowiedzi z komunikatem, że została naprawiona? Czy może być również tak, że twoje polecenie git tag <commit> <tag-name> -f -a<commit> i <tag-name> zostało odwrócone? Tak wygląda to w porównaniu z innymi odpowiedziami i dokumentami, ale nie jestem ekspertem.
Jacob Akkerboom
7

chcielibyśmy, aby komunikaty w wersji 1.x wyglądały jak komunikaty w wersji 2.0

W Git 2.17 (Q2 2018) pojawi się alternatywa dla tworzenia nowego tagu git tag <tag name> <tag name> -f -m "<new message>", ponieważ „ git tag” nauczył się wyraźnej --editopcji „ ”, która pozwala na dalszą edycję wiadomości podanej za pomocą „ -m” i „ -F”.

Zobacz commit 9eed6e4 (06 lutego 2018) autor: Nicolas Morey-Chaisemartin ( nmorey) .
(Scalone przez Junio ​​C Hamano - gitster- w commit 05d290e , 06 marca 2018)

tag: dodaj --editopcję

Dodaj --editopcję, która pozwala modyfikować wiadomości dostarczane przez -mlub -F, w ten sam sposób git commit --edit.

VonC
źródło
4
Czy możesz podać spójny przykład, --editktóry dotyczy OP?
Josh Habdas
@JoshHabdas, tak naprawdę, musisz dodać opcję -f: --edit pozwala tylko na dalszą edycję wiadomości.
VC
Dzięki. Więc jeśli -fflaga zostanie również dodana, wtedy --editedytuje wiadomość i modyfikuje znacznik czasu, prawda?
Josh Habdas
@JoshHabdas To jest pomysł, tak.
VonC
4

Będziesz musiał ponownie oznaczyć tagiem, używając -fflagi siły.

git tag v1.0 -f -m "actual message"
manojlds
źródło
3
To rozwiązanie zakłada, że ​​obecna głowa git jest w wersji 1.0. Może to zepsuć, jeśli tak nie jest, ponieważ zmienia wersję związaną z wersją 1.0. Rozwiązanie Andy'ego pozwala uniknąć tej pułapki.
Eric O Lebigot
4

Korzystając z powyższych odpowiedzi, jest to mój alias one-liner dla .gitconfig. Zastępuje istniejący tag i zachowuje datę zatwierdzenia.

[alias]
    tm = "!sh -c 'f() { export GIT_COMMITTER_DATE=$(git log -1 --format=%ci $0); git tag -f -a $0 $0^{}; }; f '"

Ulepszenia?

h0tw1r3
źródło
1
Trzyma również autora: tag-amend = "!sh -c 'f() { name=$(git log -1 --format=%an $0); email=$(git log -1 --format=%ae $0); date=$(git log -1 --format=%ci $0); GIT_AUTHOR_NAME=\"${name}\" GIT_COMMITTER _NAME=\"${name}\" GIT_AUTHOR_EMAIL=\"${email}\" GIT_COMMITTER_EMAIL=\"${email}\" GIT_AUTHOR_DATE=\"${date}\" GIT_COMMITTER_DATE=\"${date}\" git tag -f -a $0 $0^{}; }; f '"
min.
1
Właśnie tego spróbowałem. Zamiast podawać zamiennemu znacznikowi informacje o autorze i dacie z samego znacznika, wykorzystuje informacje z zatwierdzenia, na które wskazuje znacznik. To niekoniecznie jest to samo i w rzeczywistości nie jest takie samo w naszym przypadku przez większość czasu. Posiadamy infrastrukturę z wieloma repozytoriami i używamy tagów z adnotacjami w repozytorium „core”, aby rejestrować informacje o wypchnięciach obejmujących wiele repozytoriów. Zasadniczo wskazanie zatwierdzenia może nawet nie być częścią prawdziwego pchnięcia. Informacje w tagu z adnotacjami powinny odzwierciedlać rzeczywiste zmiany w pozostałych repozytoriach.
tanager
0

Jeśli używasz GUI jak smartgit tylko

  1. utwórz ten sam tag ponownie w tej samej pozycji z nową wiadomością
  2. wybierz „zastąp istniejący tag”
  3. wymuszone wciśnięcie znacznika do repozytorium nadrzędnego
rubo77
źródło