On Wed, 2 Oct 2013 12:04:28 -0700 (PDT)
dkoleary wrote:
> Apologies for replying to my own post, but I did just find the "git
> --bare fetch". While that seems to have worked,
That's odd: `git fetch` does not support "--bare", only `git clone`
does. If `git fetch` doesn't fail on this option, it's a bug, I think.
> # git --bare fetch ${prod}:/opt/app/git/filemover
> From ${prod}:/opt/app/git/filemover
> * branchHEAD -> FETCH_HEAD
>
> how do I go about getting those changes into the bare repo? A git
> log isn't showing the new commits yet...
Well, it's all in "the refspecs". The refspec if short for "ref
specification" and "ref" is a short form of "reference" in Git's
parlance. A ref is a symbolic name pointing to an object in the Git
database; branches, tags and notes are all example of refs.
Refspecs tell certain Git commands on which refs to operate, and how.
For instance, the full form of the `git fetch` call is
git fetch [OPTIONS] [ [ ...]]
where is either an URL or the name of a named remote (those
managed with the `git remote` command).
Now let's cite the `git fetch` manual:
The format of a parameter is an optional plus +, followed
by the source ref , followed by a colon :, followed by the
destination ref .
The remote ref that matches is fetched, and if is not
empty string, the local ref that matches it is fast-forwarded using
. If the optional plus + is used, the local ref is updated even
if it does not result in a fast-forward update.
and earlier there:
The ref names and their object names of fetched refs are stored
in .git/FETCH_HEAD. This information is left for a later merge
operation done by git merge.
The missing bit of information is that if Git fails to obtain a refspec
-- there's no refspec on the command line and none can be obtained from
the local repo configuration (more on this later) it assumes you want
to get whatever HEAD ref points in the remote repo, that is, if no
refspec is available Git uses HEAD, literally.
Now let's put the parts of "the puzzle" together: a call
git fetch
is turned out to be
git fetch HEAD
since no refspec is available. Now Git contacts the repository at
, fetches whatever HEAD points there (in bare repos it's usually
refs/heads/master), writes all the objects fetched into the local Git
database and then writes the SHA-1 name of the fetched tip commit into
a special ref FETCH_HEAD. No local branches are updated as the result
as there's nothing in the default refspec which tells Git to do so.
Now if you want to fetch all tags and branches from the remote repo and
update everything with matching names in a local repo, you'll have to
be clear about this:
git fetch '+refs/*:refs/*'
which means "grab every ref from the remote side and update
corresponding refs locally with the fetched data". I used single
quotes deliberately as you had to protect asterisks from being expanded
by the Unix shell. A plus sign is there to force owerwriting the
local refs if the remote history changed in a non-linear way since the
last fetch. If you only need branches (called "heads" in Git lingo) and
tags (but not notes, for instance), use several refspecs:
git fetch '+refs/heads/*:refs/heads/*' '+refs/tags/*:refs/tags/*'
This information by itself is already a solution to your problem, but
let's dig deeper.
A part of "the magic" `git clone` does is to set up a single named
remote called "origin". Setting up a named remote means creating a
special section in the configuration of a local repository -- in the
file named ".git/config" (or just "config" in a bare repository).
This section looks like this:
[remote "origin"]
url = REPO_URL_PASSED_TO_GIT_CLONE
fetch = +refs/heads/*:refs/remotes/origin/*
Notice the "fetch" variable there which defines a refspec for
`git fetch` (and, by definition, for `git pull` as well).
I copied this section from the configuration of a non-bare repo so you
might notice that the right-hand side of the refspec ("what to update")
speficies "refs/remotes/origin/*" and not just "refs/heads/*". That's
because in non-bare repos `git fetch` by default updates the so-called
remote branches, and not your own local branches you're working on.
Now when you call `git fetch origin` (or just `git fetch`) in a
repository set up like this, Git sees no refspec passed to it on the
command line and so it looks up the .fetch configuration
variable in the local repo (in this case it will be origin.fetch), and
if it's found, uses the refspec it defines. Note that contrary to the
default refspec, HEAD, this one set up by `git clone` actually
specifies what to update with the fetched data.
Now let's turn to `git clone --bare`. As specified in its manual page,
--bare
Make a bare GIT repository. That is, instead of creating
and placing the administrative files in
/.git, make the itself the $GIT_DIR. This
obviously implies the -n beca