lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Copying a bare git repository


From: Vadim Zeitlin
Subject: Re: [lmi] Copying a bare git repository
Date: Mon, 18 Oct 2021 10:37:59 +0200

On Sun, 17 Oct 2021 23:28:09 +0000 Greg Chicares <gchicares@sbcglobal.net> 
wrote:

GC> TL;DR: These two commands:
GC>   git fetch URL
GC>   git fetch URL master:master
GC> have different effects as demonstrated below, but isn't the
GC> 'master:master' part implicit, implying identical effects?

 No, this part is not implicit. As the documentation at 

https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt-ltrefspecgt

says:

        When no <refspec>s appear on the command line, the refs to fetch
        are read from remote.<repository>.fetch variables instead

and the default value of this config key is something like

        fetch = +refs/heads/*:refs/remotes/<repository>/*

 So by default git-fetch fetches all remote "heads" (i.e. branches) and
updates the local pointers to them under refs/remotes. Notably it does
_not_ update any local branches.

GC> I have a bare repository (of proprietary stuff) in an old chroot,
GC> and I want to copy it to a location outside any chroot, whence I
GC> can easily copy or clone into new chroots. But when I clone from
GC> that copy, I get a repository that isn't up to date.
GC> 
GC> Here's my "global" bare repository, in a convenient directory:
GC> 
GC> /home/greg[0]$pushd /srv/cache_for_lmi/blessed/proprietary
GC> 
GC> I thought I could fetch thither from a chroot's bare repository:
GC> 
GC> /srv/cache_for_lmi/blessed/proprietary[0]$git fetch 
/srv/chroot/bullseye0/opt/lmi/blessed/proprietary
GC> fatal: Couldn't find remote ref HEAD

 FWIW, this is normal for bare repositories, they don't really need the
HEAD pointer, so they may well not have it. You should still be able to
fetch from this bare repository by specifying the branch name explicitly
and, of course, if you really want to copy it, you can just run "git clone
--mirror" to do it instead of creating the repository manually (as you must
have done) and running git-fetch explicitly -- git-clone will do both for
you.

GC> ...but that didn't work, so I fetch from a corresponding non-bare
GC> repository that is fully up to date, which has this:
GC>   63b2f9d4 (HEAD -> master, origin/master) Use an ELF 'test_coding_rules' 
regardless of $LMI_TRIPLET
GC> as its last commit:
GC> 
GC> /srv/cache_for_lmi/blessed/proprietary[128]$git fetch 
/srv/chroot/bullseye0/opt/lmi/proprietary/
GC> remote: Enumerating objects: 7132, done.
GC> remote: Counting objects: 100% (7132/7132), done.
GC> remote: Compressing objects: 100% (2375/2375), done.
GC> remote: Total 6675 (delta 5968), reused 4971 (delta 4300), pack-reused 0
GC> Receiving objects: 100% (6675/6675), 2.93 MiB | 7.11 MiB/s, done.
GC> Resolving deltas: 100% (5968/5968), completed with 315 local objects.
GC> From /srv/chroot/bullseye0/opt/lmi/proprietary
GC>  * branch              HEAD       -> FETCH_HEAD
GC> 
GC> That appeared to succeed, giving 63b2f9d4 as expected:
GC> 
GC> /srv/cache_for_lmi/blessed/proprietary[0]$cat FETCH_HEAD 
GC> 63b2f9d4d55c03a3221fc25a028bb097690e08da                
/srv/chroot/bullseye0/opt/lmi/proprietary
GC> 
GC> ...but when 'lmi_setup_43.sh' copies it into a brand-new chroot:
GC> 
GC>   # Duplicate proprietary repository (if available).
GC>   # First, copy "blessed" repository (here, 'cp' is sufficient: this
GC>   # bare repository has no references that need to be resolved):
GC>   cd /opt/lmi || { printf 'failed: cd\n'; exit 3; }
GC>   cp --dereference --preserve --recursive /srv/cache_for_lmi/blessed .
GC> 
GC> ...and then clones from that copy...
GC> 
GC>   # Then create a working copy by cloning the bare repository...
GC>   git clone -b master file:///opt/lmi/blessed/proprietary
GC> 
GC> ...the new working copy is 170 commits in arrears:
GC> 
GC> /srv/chroot/lmi_bookworm_4/opt/lmi/proprietary[0]#git log -1
GC> commit b12435394717dcd45f37eead944ca82ab2a59812 (HEAD -> master, 
origin/master)

 Sorry if I'm being particularly obtuse (at least I can assure you I don't
do it on purpose), but why are you surprised by this? The master branch
hasn't been updated by git-fetch above, so it remains at where it
originally was. The fact that git-fetch updated a local reference to the
remote branch doesn't change anything for the local master.

GC> ...as measured by reference to the working copy I've been using
GC> for everyday work:
GC>   git log --oneline b1243539..HEAD |wc -l
GC>   170

 FWIW "git rev-list --count b1243539..HEAD" is a more idiomatic way to do
the same thing.

GC> Going back to my "global" bare repository, I've discovered
GC> an incantation that seems to make everything "just work":
GC> 
GC> /srv/cache_for_lmi/blessed/proprietary[0]$git --no-pager log -1 --oneline 
master 
GC> b1243539 (master) Replace glosses with comments
GC> /srv/cache_for_lmi/blessed/proprietary[0]$git fetch 
/srv/chroot/bullseye0/opt/lmi/proprietary/ master:master 
GC> From /srv/chroot/bullseye0/opt/lmi/proprietary
GC>    b1243539..63b2f9d4  master     -> master
GC> /srv/cache_for_lmi/blessed/proprietary[0]$git --no-pager log -1 --oneline 
master
GC> 63b2f9d4 (master) Use an ELF 'test_coding_rules' regardless of $LMI_TRIPLET
GC> 
GC> Thus, I have two commands:
GC> 
GC> /srv/cache_for_lmi/blessed/proprietary[0]$git fetch 
/srv/chroot/bullseye0/opt/lmi/proprietary/
GC> /srv/cache_for_lmi/blessed/proprietary[0]$git fetch 
/srv/chroot/bullseye0/opt/lmi/proprietary/ master:master
GC> 
GC> which I thought meant the same thing, but only the second "works". Why?

 Because it updates the local master and your HEAD is a (symbolic) pointer
to master, so it also updates it as well (symbolic means that it's a
synonym for "master" and not just a pointer to the same commit that master
points to right now).

 Note that updating master like this works only if it is _not_ your current
branch in the blessed/proprietary non-bare repository. If it were,
git-fetch would refuse to update the current branch. The usual way to
update the current branch is by using git-pull although it, of course, just
does git-fetch and then git-merge (with --ff-only option, if the pull.ff
option is set to the recommended "only" value in your ~/.gitconfig), so you
can also do the same thing manually:

        $ git switch master # if not already there
        $ git fetch $remote
        $ git merge --ff-only $remote/master

 This is just the normal way of updating your current branch, of course.

 Sorry again if I'm misunderstanding the question, as I have the impression
to do, but everything here seems perfectly logical with the possible
exception of using git-fetch to make a copy of the existing repository in
the first place: as I wrote above, this is what 'git clone --mirror" is for
and I'd use it instead.

 Please let me know if you have any follow-up questions,
VZ

Attachment: pgpV5cHvLszGa.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]