Reputation: 979
I have the habit of not adding remote git-hub server and instead directly do the fetch
when i do
git fetch url //does not fetch all the changes from remote
git remote add origin url
git fetch origin //fetches all the changes from remote
Is there any command such that,fetch all changes in remote using single command. Also difference between fetch url and fetch origin.
Upvotes: 1
Views: 783
Reputation: 489083
You're probably much better off just getting in the habit of using remote names like origin
or github
, but I was wondering a bit about this myself so I investigated a bit. The short answer is that without a refspec, git fetch url
brings over whatever they have in HEAD
and drops that in your FETCH_HEAD
(see below).
git fetch
Not counting "groups" (which complicate this even more), the useful syntax allowed by the git fetch
command is one—but only one at a time—of the following three:
git fetch remote [refspecs]
git fetch url [refspecs]
git fetch --multiple remote [remotes]
where the square brackets indicate optional additional parameters.
A remote
is simply a name, like origin
, that you have had git store in a config file. When you first clone a repository, git creates the name origin
for you; for others you would generally want to use git remote add name url
to add a new remote named name
. Each remote stores a default set of fetch refspecs as well as the URL, and when you run git fetch
, these are the refspecs used if you omit them from the command-line. (If you supply at least one refspec, the configured defaults are ignored, and the ones you supply are used instead.)
The refspecs determine what to fetch. I'll describe this a bit more in a moment.
If, instead of the name of a remote, you specify a URL directly, git still behaves the same way here: it uses your supplied refspecs to determine what to fetch. The key difference with a URL, vs a named remote, is that with a URL, there is no config file entry to supply a default set of refspecs. This means that you should probably supply at least one refspec. If you don't, though, the default refspec in this case is just HEAD
. See below for what that means.
(For completeness, the last form, with --multiple
, just tells git fetch
that all the arguments are remote names, rather than just one remote name followed by some refspecs. In this case the refspecs all come from the config file as usual. In other words --multiple
simply tells git that, e.g., you did not mean to fetch refspec github
from origin
when you say git fetch --multiple origin github
, but rather to fetch from remote origin
and then also from remote github
.)
Git's refspecs are, I think, one of the least-documented and most-confusing aspects of using git. This is surprising since they are actually pretty simple and elegant, although there are several oddities that you must simply learn and remember.
The usual form of a refspec is just a pair of branch or tag names, like master:master
or v1.2:v1.2
. The full form spells out the full reference name, such as refs/heads/master
or refs/tags/v1.2
, and also includes an optional leading plus-sign +
(which I'll ignore here); and there is an even-more-abbreviated form consisting of just a branch or tag name, e.g., master
.
The slightly confusing bit is that fetch
and push
are not entirely symmetric.
First, with fetch
, you put their branch name on the left, and your name on the right. If you want to bring branch master
from the remote over to your branch work
, you can write this as master:work
. With push
, though, you put your branch name on the left, and their name on the right: to push from your work
to their master
, you would write work:master
. The easy way to remember this is that it is always from:to
, with the "source" on the left and the "destination" on the right. The source of a fetch is "their stuff" but the source of a push is "your stuff".
Second and more important, though, with fetch
, if you write only one name, the "destination" part defaults to empty: put the fetched stuff on no branch or tag. With push
, the "destination" part defaults to a rather complicated method I won't describe here, except to say that it's never empty.
Normally, if you bring over a branch, the best place to put it is the remote-tracking branch. For instance, if you bring over master
from origin
, you should put the result in refs/remotes/origin/master
(which is the fully-spelled out form of origin/master
). Similarly, if you bring over a tag, the best place to put it is also a tag. If you use a remote-name, git will have set all this up for you and you don't have to do anything special, you just git fetch origin
and all their branches are copied to your own remote-tracking branches, with special tag magic done for corresponding tags.
If you don't want to use a remote-tracking branch, however, you can make use of a much older way that git fetch
still handles things it brings over. There's a special file git keeps in the .git
directory named FETCH_HEAD
. Every fetch, even one that just goes to a URL, updates this file (usually replacing it entirely, but with -a
or --append
, leaving the old contents in place and just adding new stuff). Whatever git fetch
brings over, it writes into this file.
This has two implications:
fetch
brings over the the sources you name, but puts the result only into FETCH_HEAD
.git fetch
, because the remote-name form gets the default refspecs from the config file1—then git fetch
pretends you gave it HEAD
, which leaves the destination empty. This brings over HEAD
and, as with case 1, puts the result only into FETCH_HEAD
.The special HEAD
reference is whatever HEAD
is set to on the remote. With a typical "bare" repository HEAD
will normally be a symbolic ref pointing to branch master
, so your default with a URL is probably going to be to bring over their master
but put it only in your FETCH_HEAD
. But this depends on what they have done with their HEAD
reference (and of course that is theirs to control however they like).
1I'm not actually sure what happens when the config file has no fetch =
lines: does git fetch
treat this as "bring over no refs at all", or does it treat this as "I had no refspecs so supply the default HEAD
refspec with an empty destination, a la URLs"?
Upvotes: 2
Reputation: 1326832
This is because of the refspec added when you do a git remote add
.
[email protected]:<username>/<reponame>
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
That refspec will instruct git what to fetch and where:
heads
and remotes/origin/
(as I mentioned it also in this answer)
When you use the url directly, there is no respec in the local config to instruct Git what to fetch.
Upvotes: 2