Does "git fetch --tags" include "git fetch"?
Note: starting with git 1.9/2.0 (Q1 2014), git fetch --tags
fetches tags in addition to what are fetched by the same command line without the option.
To fetch only tags:
git fetch <remote> 'refs/tags/*:refs/tags/*'
In details:
See commit c5a84e9 by Michael Haggerty (mhagger):
Previously, fetch's "
--tags
" option was considered equivalent to specifying the refspecrefs/tags/*:refs/tags/*
on the command line; in particular, it caused the
remote.<name>.refspec
configuration to be ignored.But it is not very useful to fetch tags without also fetching other references, whereas it is quite useful to be able to fetch tags in addition to other references.
So change the semantics of this option to do the latter.If a user wants to fetch only tags, then it is still possible to specifying an explicit refspec:
git fetch <remote> 'refs/tags/*:refs/tags/*'
Please note that the documentation prior to 1.8.0.3 was ambiguous about this aspect of "
fetch --tags
" behavior.
Commit f0cb2f1 (2012-12-14)fetch --tags
made the documentation match the old behavior.
This commit changes the documentation to match the new behavior (seeDocumentation/fetch-options.txt
).
Request that all tags be fetched from the remote in addition to whatever else is being fetched.
Since Git 2.5 (Q2 2015) git pull --tags
is more robust:
See commit 19d122b by Paul Tan (pyokagan
), 13 May 2015.
(Merged by Junio C Hamano -- gitster
-- in commit cc77b99, 22 May 2015)
pull
: remove--tags
error in no merge candidates case
Since 441ed41 ("
git pull --tags
": error out with a better message., 2007-12-28, Git 1.5.4+),git pull --tags
would print a different error message ifgit-fetch
did not return any merge candidates:It doesn't make sense to pull all tags; you probably meant: git fetch --tags
This is because at that time,
git-fetch --tags
would override any configured refspecs, and thus there would be no merge candidates. The error message was thus introduced to prevent confusion.However, since c5a84e9 (
fetch --tags
: fetch tags in addition to other stuff, 2013-10-30, Git 1.9.0+),git fetch --tags
would fetch tags in addition to any configured refspecs.
Hence, if any no merge candidates situation occurs, it is not because--tags
was set. As such, this special error message is now irrelevant.To prevent confusion, remove this error message.
With Git 2.11+ (Q4 2016) git fetch
is quicker.
See commit 5827a03 (13 Oct 2016) by Jeff King (peff
).
(Merged by Junio C Hamano -- gitster
-- in commit 9fcd144, 26 Oct 2016)
fetch
: use "quick"has_sha1_file
for tag following
When fetching from a remote that has many tags that are irrelevant to branches we are following, we used to waste way too many cycles when checking if the object pointed at by a tag (that we are not going to fetch!) exists in our repository too carefully.
This patch teaches fetch to use HAS_SHA1_QUICK to sacrifice accuracy for speed, in cases where we might be racy with a simultaneous repack.
Here are results from the included perf script, which sets up a situation similar to the one described above:
Test HEAD^ HEAD ---------------------------------------------------------- 5550.4: fetch 11.21(10.42+0.78) 0.08(0.04+0.02) -99.3%
That applies only for a situation where:
- You have a lot of packs on the client side to make
reprepare_packed_git()
expensive (the most expensive part is finding duplicates in an unsorted list, which is currently quadratic).- You need a large number of tag refs on the server side that are candidates for auto-following (i.e., that the client doesn't have). Each one triggers a re-read of the pack directory.
- Under normal circumstances, the client would auto-follow those tags and after one large fetch, (2) would no longer be true.
But if those tags point to history which is disconnected from what the client otherwise fetches, then it will never auto-follow, and those candidates will impact it on every fetch.
Git 2.21 (Feb. 2019) seems to have introduced a regression when the config remote.origin.fetch
is not the default one ('+refs/heads/*:refs/remotes/origin/*'
)
fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed
Git 2.24 (Q4 2019) adds another optimization.
See commit b7e2d8b (15 Sep 2019) by Masaya Suzuki (draftcode
).
(Merged by Junio C Hamano -- gitster
-- in commit 1d8b0df, 07 Oct 2019)
fetch
: useoidset
to keep the want OIDs for faster lookup
During
git fetch
, the client checks if the advertised tags' OIDs are already in the fetch request's want OID set.
This check is done in a linear scan.
For a repository that has a lot of refs, repeating this scan takes 15+ minutes.In order to speed this up, create a
oid_set
for other refs' OIDs.
Note: this answer is only valid for git v1.8 and older.
Most of this has been said in the other answers and comments, but here's a concise explanation:
-
git fetch
fetches all branch heads (or all specified by the remote.fetch config option), all commits necessary for them, and all tags which are reachable from these branches. In most cases, all tags are reachable in this way. -
git fetch --tags
fetches all tags, all commits necessary for them. It will not update branch heads, even if they are reachable from the tags which were fetched.
Summary: If you really want to be totally up to date, using only fetch, you must do both.
It's also not "twice as slow" unless you mean in terms of typing on the command-line, in which case aliases solve your problem. There is essentially no overhead in making the two requests, since they are asking for different information.
I'm going to answer this myself.
I've determined that there is a difference. "git fetch --tags" might bring in all the tags, but it doesn't bring in any new commits!
Turns out one has to do this to be totally "up to date", i.e. replicated a "git pull" without the merge:
$ git fetch --tags
$ git fetch
This is a shame, because it's twice as slow. If only "git fetch" had an option to do what it normally does and bring in all the tags.
The general problem here is that git fetch
will fetch +refs/heads/*:refs/remotes/$remote/*
. If any of these commits have tags, those tags will also be fetched. However if there are tags not reachable by any branch on the remote, they will not be fetched.
The --tags
option switches the refspec to +refs/tags/*:refs/tags/*
. You could ask git fetch
to grab both. I'm pretty sure to just do a git fetch && git fetch -t
you'd use the following command:
git fetch origin "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"
And if you wanted to make this the default for this repo, you can add a second refspec to the default fetch:
git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"
This will add a second fetch =
line in the .git/config
for this remote.
I spent a while looking for the way to handle this for a project. This is what I came up with.
git fetch -fup origin "+refs/*:refs/*"
In my case I wanted these features
- Grab all heads and tags from the remote so use refspec
refs/*:refs/*
- Overwrite local branches and tags with non-fast-forward
+
before the refspec - Overwrite currently checked out branch if needed
-u
- Delete branches and tags not present in remote
-p
- And force to be sure
-f