jones j alapat
jones j alapat

Reputation: 979

fetch all changes in remote server using single command

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

Answers (2)

torek
torek

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).

Three modes for 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:

  1. git fetch remote [refspecs]
  2. git fetch url [refspecs]
  3. 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.)

Refspecs

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:

  1. If you supply refspecs via arguments, but leave their destinations empty, fetch brings over the the sources you name, but puts the result only into FETCH_HEAD.
  2. If you don't supply any refspecs at all—and remember, this is only possible with the URL-only form of 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

VonC
VonC

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:

  • it fetches all heads and
  • put them in your local cloned repo in 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

Related Questions