[Top][All Lists]

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

Re: Obscure error/warning/information message from git pull

From: David Kastrup
Subject: Re: Obscure error/warning/information message from git pull
Date: Sat, 15 Nov 2014 15:30:31 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux)

Eli Zaretskii <address@hidden> writes:

>> From: David Kastrup <address@hidden>
>> Cc: address@hidden
>> Date: Sat, 15 Nov 2014 11:28:11 +0100
>> >> git cannot magically show anything that isn't in the repo.
>> >
>> > It is unclear to me, at my current level of knowledge, what exactly
>> > "is in the repo".
>> All the references you fetched/cloned and everything they point to.
> Thanks, but that explains nothing.

Unless you take very special pains (like using a "shallow" repository),
Git makes sure that it can follow _any_ SHA1/object/reference as far as
it wants: it knows the tree for any commit known to it, it knows the
parent commits to any commits known to it, it knows the blobs for any
file in any tree known to it.

When you do "git fetch", it updates the heads of its remote-mirroring
branches to point to the new SHA1 hash code.  Afterwards it makes sure
that it, again, knows everything about any reachable object from this
new state (the actual references are updated once this everything-can-be
reached state has actually been accomplished: if you bomb out with
SIGINT before, you'll get dangling objects, having some SHA1 and
substance behind it, but nothing pointing to them.  They will either
disappear with some future git-gc, or get a reference on some future
fetch and then stay around: there are no linkages other than the SHA1
for anything).

So "git fetch" updates references and then completes the repository by
fetching all objects that are referenced but not present.

>> > For example, "git clone" is advertised as "clone a repository", but
>> > that evidently only "fully" clones the master branch; other branches
>> > won't even be updated by the following "git pull"s unless you say
>> > "git checkout BRANCH" once (or give some other command that has the
>> > same effect).  Then what exactly is brought downstream by 'clone', and
>> > why is it called "repository" rather than "branch"?
>> The manual is clear about that.
> "Clear", right.
>>        Clones a repository into a newly created directory, creates
>>        remote-tracking branches for each branch in the cloned repository
>>        (visible using git branch -r), and creates and checks out an initial
>>        branch that is forked from the cloned repository\u2019s currently 
>> active
>>        branch.
>>        After the clone, a plain git fetch without arguments will update all
>>        the remote-tracking branches, and a git pull without arguments will in
>>        addition merge the remote master branch into the current master 
>> branch,
>>        if any (this is untrue when "--single-branch" is given; see below).
>>        This default configuration is achieved by creating references to the
>>        remote branch heads under refs/remotes/origin and by initializing
>>        remote.origin.url and remote.origin.fetch configuration variables.
> Sorry, but that's a bunch of gobbledygook.  What does "create
> remote-tracking branches" mean,

Fetching the references to their heads.

> and how is it different from "creates the initial branch"?

The initial branch is a local branch that is not a remote-tracking
branch but rather tracks the corresponding remote branch (remember that
"remote-tracking" is a magical phrase meaning "mirroring a remote
branch" rather than "tracking a remote branch" for some unfathomable

> What does "update" in "update the remote-tracking branches" means,

Making the references point to the same objects that the remote
repository has and making sure that the referenced objects (and
everything referenced by them) are fetched into your repository as well.

> and how is it different from what is described after that for the
> master branch?

_Your_ master branch is a local branch.  It cannot be fetched from the
remote site.  But the _remote_ master branch is fetched into its
remote-tracking branch in your repository, and then your local master
branch is merged with the remote-tracking branch of the corresponding
remote master branch.

>> > Furthermore, even if you have other branches tracked, "git pull"
>> > evidently won't update them as it does with the current branch, since
>> > switching to another branch after a pull will cheerfully tell you that
>> > you are behind the branch tip and need another "git pull" to fix that.
>> > Then what exactly does "branch tracking" mean, by default?
>> It means that Git tracks the remote branches: it knows what's there and
>> can show you even when offline (of course, it shows the state since the
>> last fetch).
> Does that include updating their parts of the DAG?


> Below you seem to say it doesn't;

Then appearances would seem to deceive.

>> git-pull merges (or rebases) _one_ local branch.  The one that is
>> checked out.  But it updates all remote-tracking branches.
> "Updates" how?  Does it update their part of the DAG?


>> > These and other similar complexities stand in the way of my
>> > understanding of what exactly do I have in my clone of the repository,
>> > and what I don't have.
>> git branch -a should tell you.
> It shows the list of the branches, where I know how to discern a
> branch I call "tracking", i.e. the one for which I did a checkout at
> some point, and those for which I didn't.  What else should it tell
> me?

That tells you the branches that are available for
viewing/merging/operating in your repository even when you are offline.
git branch -a -v
tells some more details.

>> > It is all the more perplexing, since (AFAIU) the repo met-data is (or
>> > includes) the history DAG, where (AFAIK) branches are all interwoven
>> > in a single graph.  So how come a 'pull' doesn't update the whole DAG,
>> > and if it does, why do I need to do something in addition to have all
>> > my branches updated?
>> A pull updates those parts of the DAG that can be reached from the
>> references you have in your "fetch" specification.
> What is my "fetch specification", and how did I specify that?

Take a look in your .git/config file.  You'll find a section
[remote "origin"] containing, among other things, a fetch specification.

For a typical repository containing all branches (whether that is the
case depends on the fetch specification), the complete DAG is
available.  git pull updates _all_ fetched remote-tracking branches.
But it only merges the currently checked-out _local_ branch with the
remote-tracking branch for the corresponding remote branch.

Strictly speaking, the local branch is tracking the remote-tracking
branch, and the remote-tracking branch is not actually "tracking" the
remote in the sense that "tracking" is used for local branches, but
mirroring it.

As I said: "remote-tracking" is a magical buzzword to be replaced by
"remote-mirroring" or whatever.  "tracking" in the "proper" sense is a
connection to a branch that is happening in your local repository,
either tracking another local branch, or tracking a remote-tracking

As I said: replace the exact letter-combination "remote-tracking" with
"remote-mirroring" everywhere, and you have one less muddled piece of
terminology to worry about.

I think that particular bit may well be about the most enfuriatingly
confuddled bit of terminology in general Git operations.

David Kastrup

reply via email to

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