Meny for Per-Arne's Git Good!
Fag og prosjekt Per-Arne's Git Good!

Tagger: faste navn på viktige versjoner

Modul 2: Branches og merge · 10 min

Den interaktive leksjonen trenger JavaScript. Teksten under er hele leksjonen.

Etter leksjonen kan du

  • merke en utgivelse med git tag -a v1.0 -m og se på den med git show anvende
  • forklare at en tag står fast, mens en branch flytter seg ved hver commit forstå
  • skille annotated fra lightweight tagger, og velge riktig type for en utgivelse vurdere
  • tolke svaret fra git describe forstå

Forstå: Et bokmerke som ikke flytter seg

Når en versjon er ferdig, vil du kunne finne akkurat den igjen. En commit-ID er vanskelig å huske. En tag gir commiten et fast navn, for eksempel v1.0.

Her er forskjellen fra en branch. Når du committer videre, flytter main seg. Taggen v1.0 blir stående der den ble satt.

Det finnes to slags tagger. En lightweight tag er bare et navn på en commit, omtrent som en branch som aldri flytter seg. Den passer til private bokmerker, som try-1 her.

En annotated tag er et eget objekt i Git. Den lagrer hvem som laget den, når, og en melding. Bruk annotated tagger for utgivelser, med git tag -a.

Se demo: Merk en utgivelse

Prosjektet er klart for første utgivelse. Vi lager en annotated tag med en melding. Se grafen: v1.0 dukker opp på commiten vi står på.

$ git tag -a v1.0 -m "First release"

git show viser først selve taggen: hvem som laget den, når, og meldingen. Under kommer commiten den peker på.

$ git show v1.0

Nå jobber vi videre og committer. Se grafen: main flytter seg, og v1.0 står fast.

$ echo "Open 8-16" >> README.md && git add README.md && git commit -m "Add opening hours"

Loggen bekrefter det. Taggen står på den forrige commiten, og main peker på den nye.

$ git log --oneline --decorate

Nå lager vi en lightweight tag, uten -a og uten melding. Den er bare et navn på commiten vi står på.

$ git tag try-1

git describe svarer med v1.0, en 1 og en kort ID: én commit etter v1.0. Legg merke til at den hoppet over try-1, selv om den er nærmere. Som standard bruker git describe bare annotated tagger.

$ git describe

Oppgaver

  1. Merk commiten du står på som utgivelse v1.0, med en annotated tag.
  2. Se hva taggen v1.0 inneholder.
  3. Lag en ny commit på main som endrer README.md.
  4. Vis historikken med navnene på commitene.
  5. Lag en lightweight tag som heter try-1 på commiten du står på.
  6. Be Git beskrive commiten du står på ut fra taggene.

Øv: Overfør: tagg historikken i ettertid

Et repository med tre commits på main. Ingen av dem er tagget ennå.

Oppgaver

  1. Merk den aller første commiten som utgivelse v0.1. Andre skal kunne se hvem som ga den ut, når og hvorfor.
  2. Det er funnet en feil i v0.1. Lag en branch hotfix-0.1 som starter i v0.1, og stå på den.

Sjekk deg selv: Hent det fram igjen

Hva skiller en annotated tag fra en lightweight tag?

  • Den annotated taggen flytter seg med branchen
  • Den annotated taggen er et eget objekt med hvem som laget den, dato og melding
  • Bare lightweight tagger kan vises med git show

git describe skriver v1.0-3-g4f2a1c9. Hva betyr det?

  • Versjon 1.0.3
  • Tre commits etter v1.0, på en commit med ID som starter med 4f2a1c9
  • Det finnes tre tagger som heter v1.0

Læreren skal kunne se hvem som merket innleveringen og når. En medstudent foreslår git tag hand-in. Hva svarer du?

  • Greit, alle tagger lagrer hvem og når
  • Bruk heller git tag -a hand-in -m "Hand-in 1", for den lagrer hvem, når og en melding
  • Bruk heller en branch som heter hand-in, så følger merket med videre arbeid

Repetisjon: Så lenge ingen flytter taggen, hvorfor betyr v1.0 nøyaktig de samme filene om mange år?

  • Git låser filene i commiten, så ingen kan redigere dem
  • Taggen lagrer sin egen kopi av alle filene
  • Commit-ID-en regnes ut fra innholdet. Endres noe, blir det en ny commit med ny ID.

Vanlige misforståelser

  • «En tag flytter seg med branchen.» Den står fast på commiten der den ble satt.
  • «Lightweight og annotated tagger er det samme.» Bare en annotated tag lagrer hvem, når og en melding, og git describe bruker bare dem som standard.

Les mer

To slags tagger, to slags objekter

En lightweight tag er bare et navn i refs/tags/ som peker rett på en commit, som en branch som aldri flytter seg. En annotated tag er et eget objekt i Git-databasen. Den lagrer objektet den merker, tagnavnet, hvem som laget den, når, og en melding. Tagnavnet peker så på dette tag-objektet.

$ git tag -a v1.0 -m "First release"
$ git tag try-1
$ git cat-file -t v1.0
tag
$ git cat-file -t try-1
commit
$ git cat-file -p v1.0
object 69966c17bf0d690babd2d565d9b9a7358820e38a
type commit
tag v1.0
tagger Student <student@example.invalid> 1799744400 +0100
First release

Linjen object er commiten som er merket. Derfor skriver git rev-parse v1.0 ut ID-en til tag-objektet, mens git rev-parse v1.0^{commit} følger det videre til commiten. Bruk den andre formen i skript og sjekker.

Annotated tagger kan også signeres med git tag -s, slik at andre kan bekrefte med git tag -v at utgivelsen virkelig kommer fra deg. Hvis du dropper -m, åpner Git editoren for meldingen.

Bruk Type
Utgivelser, innleveringer, alt andre stoler på annotated: git tag -a
Private, midlertidige bokmerker lightweight: git tag name

Flere kommandoer ser bare på annotated tagger som standard, blant dem git describe og git push --follow-tags.

Tagge en eldre commit

En tag havner på HEAD med mindre du oppgir en annen commit:

$ git log --oneline
15cecfd Add opening hours
69966c1 Add contact info
eff28a0 Initial snapshot
$ git tag -a v0.1 -m "Early release" eff28a0

HEAD~2 hadde fungert like godt som ID-en.

Liste og se på tagger

$ git tag -l 'v*' -n
v1.0            First release
$ git show --no-patch v1.0
tag v1.0
Tagger: Student <student@example.invalid>
Date:   Tue Jan 12 10:00:00 2027 +0100
First release
commit 69966c17bf0d690babd2d565d9b9a7358820e38a
Author: Student <student@example.invalid>
Date:   Tue Jan 12 10:00:00 2027 +0100
    Add contact info

-n tar med første linje av hver melding. For en lightweight tag hopper git show rett til commiten, fordi det ikke finnes noe tag-objekt å vise. git log --oneline --decorate viser taggene ved siden av commitene.

Lese git describe

$ git describe
v1.0-1-g15cecfd

Git går bakover fra HEAD til nærmeste annotated tag og skriver tre deler: taggen, antall commits siden den, og g (for git) fulgt av forkortet ID for commiten du står på. På en tagget commit er svaret bare v1.0. Byggeskript bruker dette til å stemple en versjon inn i et program.

  • --tags tar også med lightweight tagger.
  • Finnes det ingen tag å gå ut fra, feiler kommandoen med en melding som begynner med fatal:. Med --always får du i stedet den korte ID-en.

En tag skal aldri flyttes

Å lage en tag som allerede finnes, feiler:

fatal: tag 'v1.0' already exists

-f ville flyttet den, men alle som allerede har hentet taggen, beholder den gamle, og git fetch nekter å overskrive en eksisterende tag uten tvang. Da mener to personer forskjellig kode med v1.0. Var en utgivelse feil, lager du en ny, for eksempel v1.0.1. Mange prosjekter nummererer versjoner som MAJOR.MINOR.PATCH, kalt semantisk versjonering.

Dele tagger

Tagger bor i ditt repository. Når du pusher en branch, blir de ikke med:

$ git push origin v1.0                  # én navngitt tag
 * [new tag]         v1.0 -> v1.0
$ git push --follow-tags origin main    # branchen, pluss annotated tags den når
$ git push origin --tags                # alle tagger, også lightweight

Foretrekk å navngi taggen eller bruke --follow-tags: --tags publiserer også private bokmerker som try-1. git ls-remote --tags origin viser hva serveren har. En linje som slutter på ^{}, er commiten en annotated tag peker på:

b31f5cff91109e1958c1d82922501178bb6c608b    refs/tags/v1.0
69966c17bf0d690babd2d565d9b9a7358820e38a    refs/tags/v1.0^{}

Sletting er to separate steg: git tag -d try-1 fjerner taggen lokalt, og git push origin --delete v1.0 fjerner den fra serveren.

Jobbe ut fra en tag

En tag er ikke en branch, så git switch v1.0 feiler med fatal: a branch is expected, got tag 'v1.0'. Bruk git switch --detach v1.0 for å se deg rundt, eller git switch -c hotfix-1.0 v1.0 for å starte en branch der og rette en feil.

Offisiell dokumentasjon