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?

culebrón
źródło
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.

JB.
źródło
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
podwozie
źródło
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)
kilianc
źródło
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ę.

William Pursell
źródło
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.

Wincentego Colaiuta
źródło
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?

Xserrat
źródło
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.

Matthew Brett
źródło
21

git describe --tags

zwraca ostatni znacznik widoczny dla bieżącej gałęzi

werehere4hours
źródło
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ą.

Wschód
źródło
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!

gavenkoa
źródło
12

git describe --abbrev=0 --tags

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

git remote update

Walter B.
źródło
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
AechoLiu
źródło
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
8
git tag --sort=committerdate | tail -1
użytkownik2957741
źródło
Wyjaśnij, w jaki sposób ten fragment kodu rozwiąże problem, zamiast publikować tylko odpowiedź na kod.
Arun Vinoth,
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.

Ivan Vučica
źródł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.

Greg Hewgill
źródło
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")
Scyssion
źródło
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.

Markus
źródło
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.

dohpaz42
źródło
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}'
Sankarganesh Eswaran
źródło
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.

jthill
źródło
0

jeśli twoje tagi są sortowalne:

git tag --merged $YOUR_BRANCH_NAME | grep "prefix/" | sort | tail -n 1
Clintm
źródło
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 :)

Rondo
źródło
-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

Xaver
źródło
4
Bez sortowania jest to zły ruch.
mjd2