threads / discuss / 28460

any way to "re-sync" a bare repository against another bare repository?

Subject: any way to "re-sync" a bare repository against another bare repository?

## tl;dr

3 messages between Sep 22, 2011 and Sep 22, 2011.

replies: 2people: 2as markdown or json

Chris Friesen· Sep 22, 2011, 17:22 UTC · lore

Suppose I have a parent bare repository. I do a "git clone --bare" to create a child repository, and then clone the child to create a grandchild repository.

If changes get pushed into the parent repository, is there any way to cause the child to be updated?

Just a "git fetch <parent>" doesn't seem to help. If I set up parent as a remote branch I can fetch it, but then it shows all the branches as "parent/<branch>" rather than updating the child.

I just tried a "git clone --mirror" to create the child and it seems to allow me to pick up changes in the parent via "git fetch". Is that the proper way to handle this?

Thanks, Chris

-- 
Chris Friesen
Software Developer
GENBAND
chris.friesen@genband.com
www.genband.com
Michael Witten· Sep 22, 2011, 18:41 UTC · re: Chris Friesen · lore

Re: any way to "re-sync" a bare repository against another bare repository?

On Thu, 22 Sep 2011 11:22:37 -0600, Chris Friesen wrote:
> Suppose I have a parent bare repository.  I do a "git clone --bare" to 
> create a child repository, and then clone the child to create a 
> grandchild repository.

Firstly, what exactly is the scenario you are trying to achieve? Perhaps there is a better way to do what you are trying to do.

> If changes get pushed into the parent repository, is there any way to 
> cause the child to be updated?

The documentation answers your question (but badly, as with much of the documentation); from `git help clone':

  --bare
      Make a bare GIT repository. That is, instead of creating
      <directory> and placing the administrative files in
      <directory>/.git, make the <directory> itself the $GIT_DIR.
      This obviously implies the -n because there is nowhere to
      check out the working tree. Also the branch heads at the
      remote are copied directly to corresponding local branch
      heads, without mapping them to refs/remotes/origin/. When
      this option is used, neither remote-tracking branches nor
      the related configuration variables are created.
In particular:
                                  Also the branch heads at the
      remote are copied directly to corresponding local branch
      heads, without mapping them to refs/remotes/origin/. When
      this option is used, neither remote-tracking branches nor
      the related configuration variables are created.
In particular:
                                                           When
      this option is used, neither remote-tracking branches nor
      the related configuration variables are created.

Thus, you have to explicitly tell git what you fetched and which branch heads should be updated.

Consider this:
  $ git init parent
  $ git clone        parent child0
  $ git clone --bare parent child1
Now, look at the config file for the child0 repository:
  $ cat child0/.git/config 
  [core]
          repositoryformatversion = 0
          filemode = true
          bare = false
          logallrefupdates = true
  [remote "origin"]
          fetch = +refs/heads/*:refs/remotes/origin/*
          url = /path/to/parent
  [branch "master"]
          remote = origin
          merge = refs/heads/master
In particular:
          fetch = +refs/heads/*:refs/remotes/origin/*

That is the default `refspec'; when `git fetch' is not explicitly told on the command line what to fetch and which branch head[s] to update, then this refspec is used as a default.

Now, look at the config file for the child1 repository:
  $ cat child1/config
  [core]
          repositoryformatversion = 0
          filemode = true
          bare = true
  [remote "origin"]
          url = /path/to/parent

In particular, note that a bare repository doesn't include any such default information for `git fetch'. However, you could be explicit about it; from within the chidl1 repo:

  $ git fetch origin '+refs/heads/*:refs/remotes/origin/*'
> Just a "git fetch <parent>" doesn't seem to help.  If I set up parent as 
> a remote branch I can fetch it,

Firstly, it doesn't make any sense to say "set up parent as a remote branch"; what you mean is "set up `<parent>' as a remote with a default refspec that creates any associated remote-tracking branch heads".

Secondly, by setting up `<parent>' as a remote, you are creating the missing refspec in your config file:

  [remote "<parent>"]
          url = /path/to/parent
          fetch = +refs/heads/*:refs/remotes/<parent>/*
which is why you get this:
> but then it shows all the branches as "<parent>/<branch>" rather
> than updating the child.
You need a different refspec, namely:
  +refs/heads/*:refs/heads/*
So, either be explicit:
  git fetch '<parent>' '+refs/heads/*:refs/heads/*'
or update your config:
  git config 'remote.<parent>.fetch' '+refs/heads/*:refs/heads/*'

Of course, there is an easier way that does all of this [and more] for you:

> I just tried a "git clone --mirror" to create the child and it seems to 
> allow me to pick up changes in the parent via "git fetch".  Is that the 
> proper way to handle this?

The documentation answers your question (but badly, as with much of the documentation); from `git help clone':

  --mirror
      Set up a mirror of the source repository. This implies
      --bare. Compared to --bare, --mirror not only maps local
      branches of the source to local branches of the target, it
      maps all refs (including remote-tracking branches, notes
      etc.) and sets up a refspec configuration such that all
      these refs are overwritten by a git remote update in the
      target repository.
In particular:
                sets up a refspec configuration such that all
      these refs are overwritten by a git remote update in the
      target repository.
Consider this:
  $ git clone --mirror parent child2
  $ cat child2/config
  [core]
          repositoryformatversion = 0
          filemode = true
          bare = true
  [remote "origin"]
          fetch = +refs/*:refs/*
          mirror = true
          url = /path/to/parent
In particular:
          fetch = +refs/*:refs/*

That's a very liberal refspec! It basically says that fetch should mirror everything by default.

Sincerely, Michael Witten

Chris Friesen· Sep 22, 2011, 19:23 UTC · re: Michael Witten · lore

Re: any way to "re-sync" a bare repository against another bare repository?

Thanks for that very thorough response.

The rationale for this is somewhat convoluted...I have a vendor-supplied build system that expects to be pointed at a bare repository. For performance reasons I want to have a local bare repo on each build machine that can be kept in sync with a master repo on a main server.

Chris
On 09/22/2011 12:50 PM, Michael Witten wrote:
Show 166 quoted lines
> On Thu, 22 Sep 2011 11:22:37 -0600, Chris Friesen wrote:
>
>> Suppose I have a parent bare repository.  I do a "git clone --bare" to
>> create a child repository, and then clone the child to create a
>> grandchild repository.
>
> Firstly, what exactly is the scenario you are trying to achieve? Perhaps
> there is a better way to do what you are trying to do.
>
>> If changes get pushed into the parent repository, is there any way to
>> cause the child to be updated?
>
> The documentation answers your question (but badly, as with much of the
> documentation); from `git help clone':
>
>    --bare
>        Make a bare GIT repository. That is, instead of creating
>        <directory>  and placing the administrative files in
>        <directory>/.git, make the<directory>  itself the $GIT_DIR.
>        This obviously implies the -n because there is nowhere to
>        check out the working tree. Also the branch heads at the
>        remote are copied directly to corresponding local branch
>        heads, without mapping them to refs/remotes/origin/. When
>        this option is used, neither remote-tracking branches nor
>        the related configuration variables are created.
>
> In particular:
>
>                                    Also the branch heads at the
>        remote are copied directly to corresponding local branch
>        heads, without mapping them to refs/remotes/origin/. When
>        this option is used, neither remote-tracking branches nor
>        the related configuration variables are created.
>
> In particular:
>
>                                                             When
>        this option is used, neither remote-tracking branches nor
>        the related configuration variables are created.
>
> Thus, you have to explicitly tell git what you fetched and which
> branch heads should be updated.
>
> Consider this:
>
>    $ git init parent
>    $ git clone        parent child0
>    $ git clone --bare parent child1
>
> Now, look at the config file for the child0 repository:
>
>    $ cat child0/.git/config
>    [core]
>            repositoryformatversion = 0
>            filemode = true
>            bare = false
>            logallrefupdates = true
>    [remote "origin"]
>            fetch = +refs/heads/*:refs/remotes/origin/*
>            url = /path/to/parent
>    [branch "master"]
>            remote = origin
>            merge = refs/heads/master
>
> In particular:
>
>            fetch = +refs/heads/*:refs/remotes/origin/*
>
> That is the default `refspec'; when `git fetch' is not explicitly
> told on the command line what to fetch and which branch head[s] to
> update, then this refspec is used as a default.
>
> Now, look at the config file for the child1 repository:
>
>    $ cat child1/config
>    [core]
>            repositoryformatversion = 0
>            filemode = true
>            bare = true
>    [remote "origin"]
>            url = /path/to/parent
>
> In particular, note that a bare repository doesn't include any
> such default information for `git fetch'. However, you could be
> explicit about it; from within the chidl1 repo:
>
>    $ git fetch origin '+refs/heads/*:refs/remotes/origin/*'
>
>> Just a "git fetch<parent>" doesn't seem to help.  If I set up parent as
>> a remote branch I can fetch it,
>
> Firstly, it doesn't make any sense to say "set up parent as a remote
> branch"; what you mean is "set up `<parent>' as a remote with a default
> refspec that creates any associated remote-tracking branch heads".
>
> Secondly, by setting up `<parent>' as a remote, you are creating the
> missing refspec in your config file:
>
>    [remote "<parent>"]
>            url = /path/to/parent
>            fetch = +refs/heads/*:refs/remotes/<parent>/*
>
> which is why you get this:
>
>> but then it shows all the branches as "<parent>/<branch>" rather
>> than updating the child.
>
> You need a different refspec, namely:
>
>    +refs/heads/*:refs/heads/*
>
> So, either be explicit:
>
>    git fetch '<parent>' '+refs/heads/*:refs/heads/*'
>
> or update your config:
>
>    git config 'remote.<parent>.fetch' '+refs/heads/*:refs/heads/*'
>
> Of course, there is an easier way that does all of this [and more]
> for you:
>
>> I just tried a "git clone --mirror" to create the child and it seems to
>> allow me to pick up changes in the parent via "git fetch".  Is that the
>> proper way to handle this?
>
> The documentation answers your question (but badly, as with much of the
> documentation); from `git help clone':
>
>    --mirror
>        Set up a mirror of the source repository. This implies
>        --bare. Compared to --bare, --mirror not only maps local
>        branches of the source to local branches of the target, it
>        maps all refs (including remote-tracking branches, notes
>        etc.) and sets up a refspec configuration such that all
>        these refs are overwritten by a git remote update in the
>        target repository.
>
> In particular:
>
>                  sets up a refspec configuration such that all
>        these refs are overwritten by a git remote update in the
>        target repository.
>
> Consider this:
>
>    $ git clone --mirror parent child2
>    $ cat child2/config
>    [core]
>            repositoryformatversion = 0
>            filemode = true
>            bare = true
>    [remote "origin"]
>            fetch = +refs/*:refs/*
>            mirror = true
>            url = /path/to/parent
>
> In particular:
>
>            fetch = +refs/*:refs/*
>
> That's a very liberal refspec! It basically says that fetch
> should mirror everything by default.
>
> Sincerely,
> Michael Witten
-- 
Chris Friesen
Software Developer
GENBAND
chris.friesen@genband.com
www.genband.com

← back to recent threads