[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 11:28:11 +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 10:12:37 +0100
>> >> git log --all --source
>> >
>> > This has the disadvantage of showing the branches in the obscure
>> > refs/foo/bar/branch format.  Its advantage (AFAIK) is that it will
>> > also show commits on remote branches that are not (yet) tracked by the
>> > repo (please correct me if I'm wrong).
>> 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.

> I didn't see that explained in detail anywhere.
> 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.

       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

       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.

git-clone does not create more _local_ branches than the one it creates
and checks out from the currently active branch of the remote

> 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).  Updating a _local_ branch requires merging the state of
the local branch with the state of the remote-tracking branch.  Git only
performs merges in a checked out working directory (if you want to pick
nits: merges are performed in the index, but the index is kept
reasonably close to a working directory and/or a particular checkout).
So fetching will not update any local branch but only the
remote-tracking branches.  Fetching never merges: if the history of a
remote-tracking branch has diverged from that of the remote repository,
the old information will just get thrown away and replaced from the
up-to-date version in the remote repository.

Git does not throw away information from a _local_ branch without
explicit instructions and/or warning, however.

git-pull merges (or rebases) _one_ local branch.  The one that is
checked out.  But it updates all remote-tracking branches.

> 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 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.

>> You are probably thinking of git showing remote-tracking branches
>> (those are always destructively updated from the remote reference
>> when fetching) as well as local branches (which may or may not have a
>> remote upstream).
> I was talking about local branches that track remote ones.

I'd call that "that have a remote upstream".  Because technically those
local branches track the remote-tracking branch.

> (And "remote-tracking", btw, is a term that should have not been
> there, because it unnecessarily muddies the water.  I suggest to
> refrain from using it.)

Then you need to devise alternative terminology and submit it to the Git
documentation.  You have my blessings for that since that bit of
terminology is really fundamentally messed up.  I tend to use "tracking"
_only_ in the context of remote-tracking, and otherwise refer to
"upstream branch".  But indeed, if you take a look at the option naming
and description of "git-branch", you get

       -t, --track
           When creating a new branch, set up branch.<name>.remote and
           branch.<name>.merge configuration entries to mark the start-point
           branch as "upstream" from the new branch. This configuration will
           tell git to show the relationship between the two branches in git
           status and git branch -v. Furthermore, it directs git pull without
           arguments to pull from the upstream when the new branch is checked

           This behavior is the default when the start point is a
           remote-tracking branch. Set the branch.autosetupmerge configuration
           variable to false if you want git checkout and git branch to always
           behave as if --no-track were given. Set it to always if you want
           this behavior when the start-point is either a local or
           remote-tracking branch.

           Do not set up "upstream" configuration, even if the
           branch.autosetupmerge configuration variable is true.

           If specified branch does not exist yet or if --force has been
           given, acts exactly like --track. Otherwise sets up configuration
           like --track would when creating the branch, except that where
           branch points to is not changed.

       -u <upstream>, --set-upstream-to=<upstream>
           Set up <branchname>'s tracking information so <upstream> is
           considered <branchname>'s upstream branch. If no <branchname> is
           specified, then it defaults to the current branch.

           Remove the upstream information for <branchname>. If no branch is
           specified it defaults to the current branch.

which means that "remote-tracking" and "tracking a remote branch" are
actually describing different things.  Good luck figuring that out if
you are new to Git.  Maybe a global replace of "remote-tracking" with
"remote mirroring" and subsequent proofreading to check that one did not
have too many false positives or negatives would sort out the bulk of
this particular mess.

It's been pretty much around from the early beginnings so it's likely a
blind spot for people accustomed to Git.

But if you want the terminology to change, you cannot change it just for
Emacs developers.  You need to do it upstream.

David Kastrup

reply via email to

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