Jak uzyskać najnowszą nazwę znacznika w bieżącym oddziale w Git?


462

Jaki jest najprostszy sposób na uzyskanie najnowszego tagu w Git?

git tag a HEAD
git tag b HEAD^^
git tag c HEAD^
git tag

wynik:

a
b
c

Czy powinienem napisać skrypt, aby uzyskać datę i godzinę każdego tagu i porównać je?


1
ostatnio utworzony tag lub najnowszy tag zamówiony według daty zatwierdzenia? Twoja zaakceptowana odpowiedź pokazuje ostatnio utworzony tag. Może to stanowić problem, jeśli ktoś zdecyduje się zmienić istniejące znaczniki ...
Paebbels,

Odpowiedzi:


412

Możesz rzucić okiem git describe, co robi coś bliskiego temu, o co pytasz.


194
Wraz z --abbrev=0nią powinien zwrócić najbliższy tag z komentarzem
Jakub Narębski,

13
Zwraca najnowszy tag w bieżącej gałęzi.
brittohalloran

42
Aby uzyskać najnowszy tag z adnotacjami, który jest skierowany tylko do bieżącego zatwierdzenia w bieżącej gałęzi , użyj git describe --exact-match --abbrev=0.
Naftuli Kay

5
Ta odpowiedź z komentarzami nie podała poprawnego tagu. @kilianic podał poprawne rozwiązanie.
Herman J. Radtke III

19
git describe --tagsi porównaj com ostatni tag na stronie wydania github
Adriano Resende,

627

Aby uzyskać najnowszy tag:

git describe --tags

Aby uzyskać najnowszy tag z adnotacjami :

git describe --abbrev=0

2
Tak, jak git describemówi strona --abbrev=<n> [...] An <n> of 0 will suppress long format, only showing the closest tag.
podręcznika

22
Lub po prostugit describe --tags
james_womack

5
Ta odpowiedź (i prawdopodobnie inne) ma problemy, jeśli masz dwa tagi wskazujące na to samo zatwierdzenie. O ile tagi nie są tagami z adnotacjami, myślę, że git nie ma sposobu na odróżnienie, który z nich został wcześniej utworzony.
Paul Lynch,

10
To powinna być zaakceptowana odpowiedź. Dziękujemy za przesłanie.
crmpicco

6
jeśli chcesz bezpośrednio git checkout $(git describe --abbrev=0 --tags)
sprawdzić

320

Wysyła tag najnowszego zatwierdzonego zatwierdzenia we wszystkich gałęziach

git describe --tags $(git rev-list --tags --max-count=1)

8
lub TAG=$(git describe --tags $(git rev-list --tags --max-count=1))@ william-pursell
kilianc

20
To najlepsza odpowiedź. W rzeczywistości pobiera tagi we wszystkich gałęziach, nie tylko w bieżącej gałęzi, jak robi to obecna „poprawna” odpowiedź.
brittohalloran

61
Z wyjątkiem pytania, które konkretnie dotyczy aktualnego oddziału.
michaeltwofish

3
@michaeltwofish, w tym czasie nie wiedziałem, później to rozgryzłem i odpowiednio poprawiłem swoją odpowiedź. Przepraszam za to.
kilianc

3
Uwagi: To polecenie zwraca tag „najnowszy”, nawet jeśli ten tag znajduje się w innej gałęzi.
Alan Zhiliang Feng

47

Aby uzyskać najnowszy tag, możesz:

$ git for-each-ref refs / tags --sort = -taggerdate --format = '% (refname)' --count = 1

Oczywiście możesz zmienić argument licznika lub pole sortowania według potrzeb. Wygląda na to, że mogłeś zadać nieco inne pytanie, ale to odpowiada na pytanie, gdy je interpretuję.


2
To jest dokładnie to, czego szukałem (najnowszy tag we wszystkich gałęziach), ale przynajmniej w mojej wersji git (1.7.7.6) tagi są produkowane w tej samej kolejności dla obu --sort=-authordatei --sort=authordate.
larsks

3
Aha, bo tak naprawdę chcesz --sort=-taggerdate. Dla tagów authordatei committerdatesą puste (tak bezużyteczne jak klucze sortowania).
larsks

8
git for-each-ref refs/tags --sort=-taggerdate --format='%(refname:short)' --count=1jest jeszcze lepszy :)
Christophe Eblé

5
Naprawdę, odrzucenie całkowicie poprawnej odpowiedzi, która ma prawie 5 lat bez komentarza? To po prostu niegrzeczne.
William Pursell,

1
I --points-at=$SHAda ci tag skrótu zatwierdzenia.
Ryan

34

Co powiesz na to?

TAG=$(git describe $(git rev-list --tags --max-count=1))

Technicznie niekoniecznie dostaniesz najnowszy tag, ale ostatni zatwierdzony tag, który może, ale nie musi być tym, czego szukasz.


Ten nie otrzymuje najnowszego tagu w bieżącej gałęzi, ale dla jakichkolwiek gałęzi. Co jest świetne, bo właśnie tego potrzebowałem. Dzięki Wincent.
jasongregori

2
Jeśli trzeba uzyskać tag pasujący wzorzec można użyć --tags=<pattern>w rev-list. Na przykład pobierz tag ostatniej wersjigit describe --tags $(git rev-list --tags='v[0-9].[0-9]*' --max-count=1)
Wirone

1
$ (git opisz - zawiera $ (git rev-parse HEAD))
Vaidas Zilionis

Dzięki, działało, ale musiałem dodaćgit describe --tags $(git rev-list --tags --max-count=1)
Gianluca Casati,

25

Możesz wykonać: git describe --tags $(git rev-list --tags --max-count=1)rozmawiałem tutaj: Jak uzyskać najnowszą nazwę tagu?


Zacząłem od najwyższej / zaakceptowanej odpowiedzi i zszedłem. To jest pierwsza odpowiedź, która faktycznie daje mi najnowszy tag (nie jestem pewien, dlaczego zwykły stary git describe ...zwraca wcześniejszy tag ?!)
Jeremy Davis,

To jedyny, który działa dla mnie. Wypróbowałem niektóre --abbrev=0odpowiedzi i odciąłem część tagu, który chcę.
Luke Davis,

22

„Najnowsze” może mieć dwa znaczenia pod względem git.

Możesz powiedzieć „który tag ma datę utworzenia najpóźniej w czasie”, a większość odpowiedzi tutaj dotyczy tego pytania. Jeśli chodzi o twoje pytanie, chciałbyś zwrócić tag c.

Lub może masz na myśli „która znajduje się najbliżej tag w historii rozwoju do pewnego nazwie oddziału”, zwykle gałęzi na której się znajdujesz, HEAD. W twoim pytaniu zwróci to tag a.

Mogą być oczywiście inne:

A->B->C->D->E->F (HEAD)
       \     \
        \     X->Y->Z (v0.2)
         P->Q (v0.1)

Wyobraźmy sobie, deweloper tag'ed Zjak v0.2w poniedziałek, a następnie tag'ed Qjak v0.1we wtorek. v0.1jest nowszy, ale v0.2bliżej historii rozwoju do HEAD, w tym sensie, że ścieżka, którą podąża zaczyna się w punkcie bliższym HEAD.

Myślę, że zwykle potrzebujesz drugiej odpowiedzi, bliżej historii rozwoju. Możesz się tego dowiedzieć, używając git log v0.2..HEADetc dla każdego tagu. Daje to liczbę zatwierdzeń w HEAD, ponieważ ścieżka kończąca się na v0.2odbiegała od ścieżki, po której następuje HEAD.

Oto skrypt w języku Python, który robi to poprzez iterację wszystkich tagów wykonujących tę kontrolę, a następnie wydrukowanie tagu z najmniejszą liczbą zatwierdzeń w HEAD od czasu rozejścia się ścieżki tagu:

https://github.com/MacPython/terryfy/blob/master/git-closest-tag

git describerobi coś nieco innego, ponieważ śledzi wstecz (np.) HEAD, aby znaleźć pierwszy znacznik, który znajduje się na ścieżce wstecz w historii od HEAD. Mówiąc git, git describeszuka tagów „osiągalnych” z HEAD. Dlatego nie znajdzie takich tagów v0.2, które nie znajdują się na ścieżce powrotnej od HEAD, ale na ścieżce, która się od niej różni.



15
git log --tags --no-walk --pretty="format:%d" | sed 2q | sed 's/[()]//g' | sed s/,[^,]*$// | sed  's ......  '

JEŚLI POTRZEBUJESZ WIĘCEJ NIŻ JEDNA OSTATNIA TAGA

(git opisz - tagi czasami dają nieprawidłowe hasze, nie wiem dlaczego, ale dla mnie - max-count 2 nie działa)

w ten sposób możesz uzyskać listę z 2 najnowszymi nazwami znaczników w odwrotnej kolejności chronologicznej, działa idealnie na git 1.8.4. We wcześniejszych wersjach git (jak 1.7. *) W danych wyjściowych nie ma łańcucha „tag:” - wystarczy usunąć ostatnie wywołanie sed

Jeśli chcesz więcej niż 2 najnowsze tagi - zmień to „sed 2q” na „sed 5q” lub cokolwiek potrzebujesz

Następnie możesz łatwo parsować każdą nazwę znacznika na zmienną lub inną.


jest to bardzo pomocne, wielu programistów spróbuje zautomatyzować proces wydania, cofając się do poprzedniego tagu, jeśli wdrożenie się zepsuje. Niesamowite rzeczy!!!
AkD

1
Aby pójść dalej: git log --tags --no-walk --pretty="format:%D" | sed -nr '5q;s;^.*(tag: )([^,]*).*;\2;p' gdzie in %Dwyklucza otaczające ()znaki, a seds zaczynające się od 5q pozostawia 4 wiersze przed 5, a następnie wypisuje wszystkie znaki między „tag:” a pierwszym „,”. Więc ... zakładając, że w tagu nie ma przecinków, działa to idealnie.
Cometsong

14

Co jest złego we wszystkich sugestiach (oprócz wyjaśnień Matthew Bretta , aktualnych odpowiedzi na ten post)?

Po prostu uruchom dowolne polecenie dostarczone przez innych w historii jQuery Git, gdy jesteś w innym punkcie historii i sprawdź wynik za pomocą wizualnej reprezentacji historii tagowania ( zrobiłem właśnie dlatego widzisz ten post):

$ git log --graph --all --decorate --oneline --simplify-by-decoration

Obecnie wiele projektów wykonuje wydania (a więc oznaczanie) w oddzielnej gałęzi od głównej linii .

Jest ku temu silny powód . Wystarczy spojrzeć na wszelkie dobrze znane projekty JS / CSS. Zgodnie z konwencjami użytkowników przenoszą one binarne / zminimalizowane pliki wydań w DVCS. Naturalnie, jako opiekun projektu, nie chcesz usuwać swojej historii różnic głównych z bezużytecznymi binarnymi obiektami blob i wykonywać zatwierdzanie kompilacji kompilacji poza linią główną .

Ponieważ Git używa DAG, a nie historii liniowej - trudno jest zdefiniować metrykę odległości, więc możemy powiedzieć - och, ta prędkość jest najbliższa mojej HEAD!

Zaczynam własną podróż (zajrzyj do środka, nie skopiowałem fantazyjnych zdjęć próbnych do tego długiego postu):

Jaki jest najbliższy tag w przeszłości w odniesieniu do rozgałęziania w Git?

Obecnie mam 4 rozsądne definicje odległości między tagiem a wersją ze zmniejszeniem użyteczności:

  • długość najkrótszej ścieżki od HEADdo połączenia bazy ze znacznikiem
  • Data z zasadą łączenia pomiędzy HEADi znacznika
  • liczba obrotów osiągalna z HEAD, ale niedostępna z tagu
  • data znacznika niezależnie od podstawy scalenia

Nie wiem, jak obliczyć długość najkrótszej ścieżki .

Skrypt tagi sortowania według daty z bazy seryjnej pomiędzy HEADi TAG:

$ git tag \
     | while read t; do \
         b=`git merge-base HEAD $t`; \
         echo `git log -n 1 $b --format=%ai` $t; \
       done | sort

Nadaje się do większości projektów.

Skrypt sortujący tagi według liczby obrotów osiągalnych z HEAD, ale niedostępnych z tagu:

$ git tag \
    | while read t; do echo `git rev-list --count $t..HEAD` $t; done \
    | sort -n

Jeśli historia twojego projektu ma dziwne daty na zatwierdzeniach (z powodu rebaseów lub innego przepisywania historii lub jakiegoś kretyna, zapomnij wymienić baterię BIOS lub inną magię, którą robisz w historii), użyj powyższego skryptu.

Aby uzyskać ostatnią opcję ( datę znacznika niezależnie od podstawy scalania ), aby uzyskać listę znaczników posortowaną według daty, użyj:

$ git log --tags --simplify-by-decoration --pretty="format:%ci %d" | sort -r

Aby poznać aktualną datę zmiany, użyj:

$ git log --max-count=1

Zauważ, że git describe --tagsmają zastosowanie we własnych przypadkach, ale nie do znajdowania oczekiwanego przez człowieka najbliższego znacznika w historii projektu .

UWAGA Możesz stosować powyższe przepisy w każdej wersji, wystarczy zastąpić HEADto, co chcesz!


12

git describe --abbrev=0 --tags

Jeśli nie widzisz najnowszego tagu, upewnij się, że pobierasz pochodzenie przed uruchomieniem tego:

git remote update


12
git tag -l ac* | tail -n1

Pobierz ostatni tag z prefiksem „ac” . Na przykład znacznik o nazwie z ac1.0.0lub ac1.0.5. Inne znaczniki nazwane 1.0.0, 1.1.0będą ignorowane.

git tag -l [0-9].* | tail -n1

Zdobądź ostatni tag, którego pierwszym znakiem jest 0-9. Te tagi z pierwszym chara-z zostaną zignorowane.

Więcej informacji

git tag --help # Help for `git tag`

git tag -l <pattern>

Wyświetl tagi z nazwami pasującymi do podanego wzorca (lub wszystkich, jeśli nie podano wzorca). Uruchomienie „git tag” bez argumentów wyświetla również wszystkie tagi. Wzorzec jest znakiem wieloznacznym powłoki (tzn. Dopasowanym za pomocą fnmatch (3)). Można podać wiele wzorów; jeśli którykolwiek z nich pasuje, znacznik jest wyświetlany.


tail -n <number> # display the last part of a file
tail -n1 # Display the last item 

Aktualizacja

Z git tag --help, o sortkłótni. Będzie używać lexicorgraphic orderdomyślnie, jeśli tag.sortwłaściwość nie istnieje.

Domyślna kolejność sortowania to wartość skonfigurowana dla zmiennej tag.sort, jeśli istnieje, lub w przeciwnym razie kolejność leksykograficzna. Zobacz git-config (1).

Po google ktoś powiedział , że obsługuje git 2.8.0 zgodnie ze składnią.

git tag --sort=committerdate

to nie wok dla mnie, ostatni tag to 2.11.174, ale ten wydruk 2.11.99, ponieważ sortuj nie jako wersję
Ali.MD 17.09.16


5

Poniższe działa dla mnie, jeśli potrzebujesz dwóch ostatnich znaczników (na przykład, aby wygenerować dziennik zmian między bieżącym i poprzednim znacznikiem). Testowałem to tylko w sytuacji, gdy najnowszy tag był HEAD.

PreviousAndCurrentGitTag=`git describe --tags \`git rev-list --tags --abbrev=0 --max-count=2\` --abbrev=0`
PreviousGitTag=`echo $PreviousAndCurrentGitTag | cut -f 2 -d ' '`
CurrentGitTag=`echo $PreviousAndCurrentGitTag | cut -f 1 -d ' '`

GitLog=`git log ${PreviousGitTag}..${CurrentGitTag} --pretty=oneline | sed "s_.\{41\}\(.*\)_; \1_"`

Odpowiada moim potrzebom, ale ponieważ nie jestem git-magiem, jestem pewien, że można go jeszcze ulepszyć. Podejrzewam też, że się zepsuje, jeśli historia zatwierdzeń pójdzie do przodu. Po prostu dzielę się na wypadek, gdyby komuś to pomogło.


4

Moja pierwsza myśl jest taka, że ​​możesz użyć git rev-list HEAD , który wymienia wszystkie obroty w odwrotnej kolejności chronologicznej, w połączeniu z git tag --contains. Gdy znajdziesz referencję, w której git tag --containspowstaje niepusta lista, znalazłeś najnowsze tagi.


4

Jeśli chcesz znaleźć ostatni tag, który został zastosowany w konkretnej gałęzi, możesz spróbować:

git describe --tag $(git rev-parse --verify refs/remotes/origin/"branch_name")

3

Jeśli potrzebujesz jednego linera, który pobiera najnowszą nazwę tagu (według daty tagu) w bieżącym oddziale :

git for-each-ref refs/tags --sort=-taggerdate --format=%(refname:short) --count=1 --points-at=HEAD

Używamy tego do ustawienia numeru wersji w konfiguracji.

Przykład wyjściowy:

v1.0.0

Działa również w systemie Windows.


1
W systemie Linux (Debian Stretch) dostaję-bash: syntax error near unexpected token '('
Jeremy Davis,

1
Jeśli zawijam tę część w cudzysłów (tj. --format="%(refname:short)") I pomijam, --points-at=HEADto działa. Z tym ostatnim przełącznikiem nic nie zwraca, bo chyba mój HEADtag nie jest oznaczony?
Jeremy Davis,

@JeremyDavis, tak, myślę, że to dlatego, że twój HEADnie jest oznaczony.
Markus,

2

To jest stary wątek, ale wydaje się, że wielu ludziom brakuje najprostszej, najłatwiejszej i najbardziej poprawnej odpowiedzi na pytanie OP: aby uzyskać najnowszy tag dla bieżącego oddziału , używaszgit describe HEAD . Gotowy.

Edycja: możesz także podać dowolną prawidłową nazwę, nawet piloty; tzn. git describe origin/masterpowie Ci najnowszy tag, który można uzyskać z origin / master.


Nic nie gwarantuje, że „najnowszy tag” będzie obsługiwany przez dowolny oddział. Dwa działające rozwiązania to for-each-refpolecenie ( stackoverflow.com/a/5261470/515973 ) oraz połączenie rev-listi describe( stackoverflow.com/a/7979255/515973 )
Julien Carsique

1
Nie otrzymuję dla mnie najnowszego tagu.
Karl Morrison,

git describe branchname --tagsdziała dla mnie, aby uzyskać najnowszy tag na gałęzi (git wersja 2.12.2)
Rob_M

0

Aby uzyskać najnowszy tag tylko dla bieżącej nazwy gałęzi / tagu, która poprzedza bieżącą gałąź, musiałem wykonać następujące czynności

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags --abbrev=0 $BRANCH^ | grep $BRANCH

Mistrz oddziału:

git checkout master

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags 
--abbrev=0 $BRANCH^ | grep $BRANCH

master-1448

Niestandardowy oddział:

git checkout 9.4

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags 
--abbrev=0 $BRANCH^ | grep $BRANCH

9.4-6

I moja ostatnia potrzeba zwiększenia i uzyskania tagu +1 do następnego tagowania.

BRANCH=`git rev-parse --abbrev-ref HEAD` && git describe --tags  --abbrev=0 $BRANCH^ | grep $BRANCH | awk -F- '{print $NF}'

0

W przypadku zadanego pytania

Jak uzyskać najnowszą nazwę znacznika w bieżącym oddziale

chcesz

git log --first-parent --pretty=%d | grep -m1 tag:

--first-parentmówi, git logaby nie wyszczególniać żadnych połączonych historii, --pretty=%dmówi, aby pokazywać tylko dekoracje, tj. lokalne nazwy dla jakichkolwiek zatwierdzeń. grep -m1mówi „dopasuj tylko jeden”, więc otrzymujesz tylko najnowszy tag.


0

jeśli twoje tagi są sortowalne:

git tag --merged $YOUR_BRANCH_NAME | grep "prefix/" | sort | tail -n 1

0

Nie ma tu wiele wzmianek o tagach bez adnotacji w porównaniu z tagami z adnotacjami. „opisz” działa na tagach z adnotacjami i ignoruje te bez adnotacji.

Jest to brzydkie, ale wykonuje zlecenie i nie znajdzie żadnych znaczników w innych gałęziach (a nie w tym określonym w poleceniu: master w poniższym przykładzie)

Filtrowanie powinno być zoptymalizowane (skonsolidowane), ale znowu wydaje się, że to zadanie.

git log  --decorate --tags master |grep '^commit'|grep 'tag:.*)$'|awk '{print $NF}'|sed 's/)$//'|head -n 1

Krytyki są mile widziane, ponieważ zamierzam teraz użyć tego :)


-2

Innym prostym sposobem na uzyskanie najnowszej nazwy znacznika jest

git tag | tail -1

lub

TAG=$(git tag | tail -1)

do przechowywania w zmiennej.

git tagwyświetla listę wszystkich dostępnych tagów i zwróci ostatni wiersz, jeśli wynik.tail-1


4
Bez sortowania jest to zły ruch.
mjd2
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.