In git, how do I sync my tags against a remote server?
A bit of research has shown that git has no way to tell the difference between local or foreign tags (all tags go to .git/refs/tags/). Therefore, it is not possible to determine the difference between locally created tags and prune-able remote tags. The options, are then reduced to: having an ever growing set of tags, or only the tags that are on the server.
git push --tags origin && \
git tag | xargs -n1 git tag -d && \
git fetch --tags
Drop the first line for the latter behaviour, and could be potentially git alias'd for frequent usage.
An alternative would be to create a branch (as they can be identified as local/remote) at a tag point and are never write to it again. Then using remotename/branchname as a tag to checkout would keep tags in sync (in addition to git fetch
and git remote prune remotename
).
Either way is a hack, and the "right" answer is to stop changing tags all the time.
The following worked for me:
git fetch --prune --tags
...also prune tags no longer on a remote
git fetch
gets with Git 2.17 (Q2 2018) an handy short-hand for getting
rid of stale tags that are locally held.
See commit 6317972, commit 97716d2, commit e249ce0, commit 627a129, commit d0e0747, commit 2c72ed7, commit e1790f9, commit 59caf52, commit 82f34e0, commit 6fb23f5, commit ca3065e, commit bf16ab7, commit eca142d, commit 750d0da, commit 0711883, commit ce3ab21, commit aa59e0e (09 Feb 2018) by Ævar Arnfjörð Bjarmason (avar
).
(Merged by Junio C Hamano -- gitster
-- in commit c1a7902, 06 Mar 2018)
fetch: add a
--prune-tags
option andfetch.pruneTags
config
Add a
--prune-tags
option togit-fetch
, along withfetch.pruneTags
config option and a-P
shorthand (-p
is--prune
).
This allows for doing any of:git fetch -p -P git fetch --prune --prune-tags git fetch -p -P origin git fetch --prune --prune-tags origin
Or simply:
git config fetch.prune true && git config fetch.pruneTags true && git fetch
Instead of the much more verbose:
git fetch --prune origin 'refs/tags/*:refs/tags/*' '+refs/heads/*:refs/remotes/origin/*'
Before this feature it was painful to support the use-case of pulling from a repo which is having both its branches and tags deleted regularly, and have our local references to reflect upstream.
At work we create deployment tags in the repo for each rollout, and there's lots of those, so they're archived within weeks for performance reasons.
Without this change it's hard to centrally configure such repos in
/etc/gitconfig
(on servers that are only used for working with them). You need to setfetch.prune=true
globally, and then for each repo:git -C {} config --replace-all remote.origin.fetch "refs/tags/*:refs/tags/*" "^\+*refs/tags/\*:refs/tags/\*$"
Now I can simply set
fetch.pruneTags=true
in/etc/gitconfig
as well, and users running "git pull
" will automatically get the pruning semantics I want.
Update Apr. 2021, Git for Windows 2.30.1 and GitHub Desktop 2.8
It works if you have set prune
and pruneTags
options:
cd C:\path\to\local\repo
git config fetch.prune true
git config fetch.pruneTags true
Then click on Fetch origin in GitHub Deskop: the logs will show:
2021-04-28T20:25:21.244Z - info: [ui] Executing fetch:
git -c credential.helper= -c protocol.version=2 fetch --progress --prune origin (took 2.986s)
... and any local tag not present in the remote will be gone!