når jeg tjekker fjern-Git-tag bruger kommandoen sådan her:
git checkout -b local_branch_name origin/remote_tag_name
Jeg fik fejl som denne:
error: pathspec `origin/remote_tag_name` did not match any file(s) known to git.
Jeg kan finde remote_tag_name, når jeg bruger git tag-kommandoen.
[]]1
Et tag bruges til at mærke og markere et specifikt commit i historikken.
Det bruges normalt til at markere udgivelsespunkter (f.eks. v1.0, osv.).
Selv om et tag kan ligne en gren, et tag ændrer sig dog ikke.
Det peger direkte på et specifikt commit i historikken.
[]]2
Du vil ikke kunne tjekke tagsene ud, hvis de ikke er lokalt i dit arkiv, så først skal du hente tagsene til dit lokale arkiv.
Først skal du sikre dig, at tagget findes lokalt ved at gøre
# --all will fetch all the remotes.
# --tags will fetch all tags as well
git fetch --all --tags --prune
Så tjek tagget ud ved at køre
git checkout tags/<tag_name> -b <branch_name>
I stedet for origin
skal du bruge præfikset tags/
.
I dette eksempel har du 2 tags version 1.0 & version 1.1 du kan tjekke dem ud med en af følgende:
git checkout A ...
git checkout version 1.0 ...
git checkout tags/version 1.0 ...
Alle ovenstående vil gøre det samme, da tagget kun er en pegepind til en given commit.
[]]3 origin: https://backlog.com/git-tutorial/img/post/stepup/capture_stepup4_1_1.png
# list all tags
git tag
# list all tags with given pattern ex: v-
git tag --list 'v-*'
Der er 2 måder at oprette et tag på:
# lightweight tag
git tag
# annotated tag
git tag -a
Forskellen mellem de 2 er at når du opretter et annoteret tag kan du tilføje metadata som du har i et git commit:
navn, e-mail, dato, kommentar & signatur
[]]4
# delete any given tag
git tag -d <tag name>
# Don't forget to remove the deleted tag form the server with push tags
For at få fat i indholdet af et givet tag kan du bruge kommandoen checkout
.
Som forklaret ovenfor er tags som alle andre commits, så vi kan bruge checkout
og i stedet for at bruge SHA-1 erstatte det blot med tag_name.
Mulighed 1:
# Update the local git repo with the latest tags from all remotes
git fetch --all
# checkout the specific tag
git checkout tags/<tag> -b <branch>
Mulighed 2:
Da git understøtter shallow clone ved at tilføje --branch
til clone-kommandoen kan vi bruge tag-navnet i stedet for branch-navnet. Git ved hvordan man "oversætter" den givne SHA-1 til den relevante commit
# Clone a specific tag name using git clone
git clone <url> --branch=<tag_name>
git clone --branch=
--branch
kan også tage tags og fjerner HEAD'en ved det pågældende commit i det resulterende repository.
git push --tags
For at skubbe alle tags:
git push --tags
For at skubbe annoterede tags og aktuelle historiekæde-tags skal du bruge::
git push --follow-tags
Dette flag --follow-tags
skubber både commits og kun tags, der er begge dele:
Fra Git 2.4 kan du indstille det ved hjælp af konfiguration
git config --global push.followTags true
Der findes ikke noget som et "remote Git tag". Der findes kun "tags". Jeg påpeger alt dette ikke for at være pedantisk,1 men fordi der er stor forvirring omkring dette hos tilfældige Git-brugere, og Git-dokumentationen er ikke særlig hjælpsom2 for begyndere. (Det er ikke klart, om forvirringen skyldes dårlig dokumentation, eller om den dårlige dokumentation skyldes, at dette i sig selv er noget forvirrende, eller hvad).
Der er "remote branches", mere korrekt kaldet "remote-tracking branches", men det er værd at bemærke, at disse faktisk er lokale enheder. Der findes dog ingen fjernmærker (medmindre du (gen)opfinder dem). Der er kun lokale tags, så du skal hente tagget lokalt for at kunne bruge det.
Den generelle form for navne til specifikke commits - som Git kalder references - er enhver streng, der begynder med refs/
. En streng der starter med refs/heads/
navngiver en gren; en streng der starter med refs/remotes/
navngiver en gren med fjernsporing; og en streng der starter med refs/tags/
navngiver et tag. Navnet refs/stash
er stash-referencen (som den bruges af git stash
; bemærk manglen på en afsluttende skråstreg).
Der er nogle usædvanlige navne i særtilfælde, som ikke begynder med refs/
: HEAD
, ORIG_HEAD
, MERGE_HEAD
og CHERRY_PICK_HEAD
er især også alle navne, der kan henvise til specifikke commits (selvom HEAD
normalt indeholder navnet på en gren, dvs. indeholder ref: refs/heads/branch
). Men generelt starter referencer med refs/
.
En ting Git gør for at gøre dette forvirrende er, at det giver dig mulighed for at udelade refs/
, og ofte ordet efter refs/
. For eksempel kan du udelade refs/heads/
eller refs/tags/
når du henviser til en lokal gren eller et tag - og faktisk skal du udelade refs/heads/
når du checker en lokal gren ud! Du kan gøre dette når resultatet er entydigt, eller - som vi lige har bemærket - når du skal gøre det (for git checkout branch
).
Det er sandt, at referencer ikke kun findes i dit eget arkiv, men også i eksterne arkiver. Git giver dig dog kun adgang til et fjernrepositorium's referencer på meget specifikke tidspunkter: nemlig under fetch
- og push
-operationer. Du kan også bruge git ls-remote
eller git remote show
for at se dem, men fetch
og push
er de mere interessante kontaktpunkter.
Under fetch
og push
bruger Git strenge, som Git kalder refspecs til at overføre referencer mellem det lokale og det eksterne repository. Det er således på disse tidspunkter, og via refspecs, at to Git-repositorier kan blive synkroniseret med hinanden. Når dine navne er synkroniseret, kan du bruge det samme navn som en anden med det eksterne bruger. Der er dog noget særlig magi her på fetch
, og det påvirker både branch-navne og tag-navne.
Du skal tænke på git fetch
som at du dirigerer din Git til at ringe til (eller måske sende en sms til) en anden Git - "remote"- og føre en samtale med den. Tidligt i denne samtale opregner fjerneren alle sine referencer: alt i refs/heads/
og alt i refs/tags/
, sammen med alle andre referencer den har. Din Git scanner disse igennem og (baseret på den sædvanlige fetch refspec) omdøber deres branches.
Lad os tage et kig på den normale refspec for den fjernbetjening, der hedder origin
:
$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
$
Denne refspec instruerer din Git om at tage hvert navn, der matcher refs/heads/*
- dvs. hver gren på fjernopkaldet - og ændre navnet til refs/remotes/origin/*
, dvs. at beholde den matchede del på samme måde, men ændre grennavnet (refs/heads/
) til et grennavn, der følger fjernopkaldet (refs/remotes/
, nærmere bestemt refs/remotes/origin/
).
Det er gennem denne refspec at origin
's grene bliver dine remote-tracking grene for remote origin
. Branch name bliver navnet på den fjernsporende gren, med navnet på den fjerntliggende filial, i dette tilfælde origin
, inkluderet. Plustegnet +
foran refspec'en sætter flaget "force", dvs. at din fjernsporing-gren vil blive opdateret til at matche fjernoprettelsesgrenens navn, uanset hvad der skal til for at få det til at matche. (Uden +
er branch-opdateringer begrænset til "fast forward" ændringer, og tag-opdateringer ignoreres simpelthen siden Git version 1.8.2 eller deromkring - før da gjaldt de samme fast-forward regler).
Men hvad med tags? Der er ingen refspec for dem - i det mindste ikke som standard. Du kan indstille en, i hvilket tilfælde refspec'ens form er op til dig; eller du kan køre git fetch --tags
. Brug af --tags
har den virkning at tilføje refs/tags/*:refs/tags/*
til refspec'en, dvs, det bringer alle tags over (men opdaterer ikke dit tag, hvis du allerede har et tag med det navn, uanset hvad fjernbetjeningen's tag siger Redigering, jan. 2017: Fra Git 2.10, viser test, at --tags
tvinger dig til at opdatere dine tags fra fjernbetjeningens tags, som om refspec'en læste +refs/tags/*:refs/tags/*
; dette kan være en forskel i adfærd fra en tidligere version af Git).
Bemærk, at der ikke sker nogen omdøbning her: hvis fjernbetjeningen origin
har tag xyzzy
, og du ikke har det, og du git fetch origin "refs/tags/*:refs/tags/*"
, får du refs/tags/xyzzy
tilføjet til dit repository (og peger på samme commit som på fjernbetjeningen). Hvis du bruger +refs/tags/*:refs/tags/*
, så bliver dit tag xyzzy
, hvis du har et, erstattet af det fra origin
. Det vil sige, at +
force-flaget på en refspec betyder "erstatte min reference's værdi med den, som min Git får fra deres Git".
Af historiske årsager,3 hvis du hverken bruger --tags
-indstillingen eller --no-tags
-indstillingen, tager git fetch
en særlig handling. Husk, at vi ovenfor sagde, at fjernprogrammet starter med at vise alle dets referencer til din lokale Git, uanset om din lokale Git ønsker at se dem eller ej.4 Din Git noterer sig alle de tags, den ser på dette tidspunkt. Når den så begynder at hente de commit-objekter, den har brug for til at håndtere det, den henter, hvis en af disse commits har det samme ID som et af disse tags, vil Git tilføje dette tag - eller disse tags, hvis flere tags har dette ID - til dit repository.
Edit, Jan 2017: Test viser, at opførslen i Git 2.10 er nu: Hvis deres Git leverer et tag ved navn T, og du ikke har et tag ved navn T, og commit-ID'et, der er forbundet med T, er en forfader til en af deres grene, som din git fetch
undersøger, tilføjer dit Git T til dine tags med eller uden --tags
. Tilføjelse af --tags
får din Git til at hente alle deres tags, og også tvinge opdatering.
Du kan være nødt til at bruge git fetch --tags
for at få deres tags. Hvis deres tag-navne er i konflikt med dine eksisterende tag-navne, kan du (afhængigt af Git-versionen) endda være nødt til at slette (eller omdøbe) nogle af dine tags, og derefter køre git fetch --tags
, for at få deres tags. Da tags - i modsætning til remote branches - ikke har automatisk omdøbning, skal dine tagnavne matche deres tagnavne, hvilket er grunden til, at du kan få problemer med konflikter.
I de fleste normale tilfælde vil en simpel git fetch
dog gøre arbejdet, og bringe deres commits og deres matchende tags, og da de - hvem de end er - vil tagge commits på det tidspunkt, hvor de udgiver disse commits, vil du følge med i deres tags. Hvis du ikke laver dine egne tags, og heller ikke blander deres repository og andre repositories (via flere remotes), vil du heller ikke have nogen tag-navnekollisioner, så du behøver ikke at bøvle med at slette eller omdøbe tags for at få deres tags.
Jeg nævnte ovenfor, at du kan udelade refs/
næsten altid, og refs/heads/
og refs/tags/
osv. det meste af tiden. Men hvornår kan't du det?
Det fuldstændige (eller næsten fuldstændige i hvert fald) svar findes i [dokumentationen til gitrevisions
] (https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html). Git vil opløse et navn til et commit-ID ved hjælp af den seks-trins sekvens, der er angivet i linket. Mærkeligt nok tilsidesætter tags grene: Hvis der er et tag xyzzy
og en gren xyzzy
, og de peger på forskellige commits, så:
git rev-parse xyzzy
gitrevisions
- git checkout
foretrækker branch-navne, så git checkout xyzzy
vil sætte dig på branchen, uden at tage hensyn til tagget.
I tilfælde af tvetydighed kan du næsten altid stave ref-navnet ud med det fulde navn, refs/heads/xyzzy
eller refs/tags/xyzzy
. (Bemærk, at dette fungerer med git checkout
, men på en måske uventet måde: git checkout refs/heads/xyzzy
forårsager en udkørsel af en detached-HEAD checkout i stedet for en udkørsel af en gren. Derfor skal du bare være opmærksom på at git checkout
vil bruge det korte navn som branchnavn først: det er sådan du tjekker ud af branchen xyzzy
, selv om tagget xyzzy
eksisterer. Hvis du ønsker at tjekke tagget ud, kan du bruge refs/tags/xyzzy
).
Fordi (som gitrevisions
bemærker) Git vil prøve refs/name
, kan du også blot skrive tags/xyzzy
for at identificere commit'et med tagget xyzzy
. (Hvis nogen har formået at skrive en gyldig reference med navnet xyzzy
ind i $GIT_DIR
, vil dette dog blive opløst som $GIT_DIR/xyzzy
. Men normalt bør kun de forskellige *HEAD
-navne være i $GIT_DIR
).1Okay, okay, okay, "ikke bare for at være pedantisk". :-)
2Nogle vil sige "meget uhjælpeligt", og jeg er faktisk enig.
3Grundlæggende var git fetch
, og hele konceptet med remotes og refspecs, en lidt sen tilføjelse til Git, der skete omkring Git 1.5. Før da var der bare nogle ad hoc specialtilfælde, og tag-fetching var et af dem, så det blev indført via en særlig kode.
4Hvis det hjælper, så tænk på fjern-Git som en flasher, i slangens betydning.