On Sun, 26 Jul 2015 22:52:21 -0700 (PDT)
dexter ietf <dexter.i...@gmail.com> wrote:

> > git pull is actually the same as if you write git fetch and then
> > git merge.
> >
> > git-fetch doesn't update anything in your working directory, it
> > just download the changes from the remote. Think about it as if I
> > ask you "what did you change in the code?" You tell me, but I don't
> > apply it to my version yet; that's what git-merge is for.
> 
> Thanks for the reply.
> but i don't quiet get it, since its a bare repo i'm not worried about 
> merging the tree.
> the remote and bare-repo have diverged, i want to get that latest
> data from the
> remote (latest commits, tags etc..). if this doesn't happen, my
> bare-repo will always
> be out-of-date,maybe i'm using the wrong command. git fetch doesn't
> seem to be
> the right command for the job. i hope i'm clear now.

`git fetch`, like most (if not all) Git commands which deal with remote
repos, rely on the so-called "refspecs".  A refspec is a portmoneu of
"reference specification", and they define what to update with what
when a fetch or push operation is carried out.  If a command like
`git fetch` or `git push` does not receive an explicit refspec on
its command line, it attempts to look one up in the repository's
configuration, and uses it, if found.  Since long ago Git sets up
sensible refspecs in the configuration of your repositories, and so
unadorned `git push` and `git fetch` work most of the time, except when
they don't -- because your expectations contradict what they define.

Let's clone a (bare) repository:

  tmp% git clone git://git.domain.local/test.git
  Cloning into 'test'...
  ...
  Checking connectivity... done.
  tmp% cd test/
  test% cat .git/config 
  [core]
          repositoryformatversion = 0
          filemode = true
          bare = false
          logallrefupdates = true
  [remote "origin"]
          url = git://git.domain.local/test.git
          fetch = +refs/heads/*:refs/remotes/origin/*
  [branch "master"]
          remote = origin
          merge = refs/heads/master

Note that we did not pass any options to `git clone`.
Now observe that remote.origin.fetch configuration variable -- what it
says is that when fetching, Git has to:

1) tell the remote Git to send every ('*') ref under
   "refs/heads/" (that is, every branch it has), and
2) forcibly ('+') update local refs with matching names under the
   "refs/remotes/origin/" hierarchy.

Those refs under the "refs/remotes" are what called "remote branches".
And that's what get updated when you run `git fetch` in a non-bare repo.

OK, let's now "just fetch" and see:

  test% git fetch -v
  From git://git.domain.local/test
   = [up to date]      master     -> origin/master
   = [up to date]      foo        -> origin/foo
   = [up to date]      bar        -> origin/bar

As you can see, local Git actually asked the remote one for branches,
and that one told ours that OK, there are three head refs, and our local
Git figured out they match remote branches it already has.

Now let's re-clone the repository with the "--bare" command-line option:

  tmp% git clone --bare git://git.domain.local/test.git
  Cloning into bare repository 'test.git'...
  ...
  Checking connectivity... done.
  tmp% cd test.git/
  test.git% cat config 
  [core]
          repositoryformatversion = 0
          filemode = true
          bare = true
  [remote "origin"]
          url = git://git.domain.local/test.git

Do you see there's no default "fetch" refspec?

OK, so what happens if we "just run" `git fetch` now?

  test.git% git fetch -v
  From git://git.domain.local/test
   * branch            HEAD       -> FETCH_HEAD

What it said, is that it tried to fetch remote HEAD and updated the
special local ref named FETCH_HEAD in the local repository.
No local branch was updated.

Now let's pretend you did read the manual page for `git clone`
and figured out it supports an interesting command-line option
called "--mirror":

  tmp% git clone --mirror git://git.domain.local/test.git
  Cloning into bare repository 'ir-pdf-gen.git'...
  ...
  Checking connectivity... done.
  tmp% cd test.git/
  test.git% cat config 
  [core]
          repositoryformatversion = 0
          filemode = true
          bare = true
  [remote "origin"]
          url = git://git.domain.local/test.git
          fetch = +refs/*:refs/*
          mirror = true

Do you see this refspec?  It tells Git to grab every possible ref
(branches, tags, notes and whatever else there might be) and forcibly
update the same-named ref locally -- or create it, if it does not yet
exist.  That's why "--mirror": `git fetch` with this refspec would
*almost* mirror the remote repository.  "Almost" because there's no way
to tell Git to automatically delete what's disappeared from the remote
repo; for this, Git has a separate command
`git remote prune <remotename>`.

Now back to your concrete issue.

If I were you, I'd `git clone --mirror` your bare repos and use
`git fetch` + occasional `git remote prune` + `git gc --auto` on them.

On the other hand, you can easily do the same in your existing repos
just by calling `git fetch '+refs/*:refs/*'` and so on.

Now please take your time to open up the `git push` manual page
and read up on what "the refspec" means -- that's the second paragraph
under the "OPTIONS" section.

-- 
You received this message because you are subscribed to the Google Groups "Git 
for human beings" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to git-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to