git pull command output message meaning into which branch
Say there is a remote branch
br1 checkout on the remote repo, and the
master branch on a local repo.
Command 1: If I do a “
git pull origin br1:br1” it pulls remote
br1, and shows:
9188a5d..97d4825 br1 -> br1
9188a5d..97d4825 br1 -> origin/br1
- Why doesn't `git checkout` automatically do `git submodule update --recursive`?
- make sure git histories are the same
- Can I use Git to search for matching filenames in a repository?
- How to git grep in the whole tree when I'm in a subdirectory?
- Beginner in Git, Starting from Android Studio
- How to commit and push all changes, including deletes?
command 2: If I do just a “
git pull“, it will pull remote
master, but it shows only the following:
9188a5d..97d4825 br1 -> origin/br1
I’m expecting it also shows something like “
br1 -> master“. Why it does not show that?
br1 -> br1” mean pulling remote
br1 into local
What does that “
br1 -> origin/br1” mean?
Update: With help from VonC, I figured out the following:
git pullupdates all the tracking branches.
br1 -> origin/br1means
br1on the remote is pulled into local tracking branch
git pull origin br1:br1pulls remote
origin/br1. Then the messages after that mean the same change set is also pulled into the current checked-out branch (the message is
Updating ..., it does not show
br1 -> master):
$ git pull origin br1:br1
beb48a4..b344dd1 br1 -> br1
beb48a4..b344dd1 br1 -> origin/br1
file2 | 0
file3 | 0
4 files changed, 0 insertions(+), 0 deletions(-)
Previously I thought
git pullpulls into the local master. That is not the case. It is that
git pull origin br1:br1does it.
Update 2: With explanations by torek, the specific problem is that the command
git pull origin br1:br1 pulls remote
FETCH_HEAD after a sequence of other actions and subsequently merges the
FETCH_HEAD onto the current branch.
2 Solutions collect form web for “git pull command output message meaning into which branch”
Warning: long. TL;DR version: you are looking at
git fetch output and
git fetch is not affecting your
master at all, it’s the
git merge part of your
git pull that affects your
master. However, your
git fetch is updating a remote-tracking branch
origin/br1 and in one case updating or even creating a local branch
git pull is a convenience script
Always remember that
git pull is just a convenience script that runs two other git commands for you: first,
git pull passes your arguments on to
git fetch. Once that finishes,
git pull runs
git merge (or, if instructed,
git rebase), but all of the quoted action in your original question is occurring purely in
git fetch. (A bit in the “update” section is from
git merge, which I’ll get to later.)
If you do not provide a remote argument to
git pull, the
pull script extracts one from your current branch’s configuration. In this case, the one it extracts is clearly
origin. So If you run
git pull without specifying
origin, you are, in effect, running
git pull origin.
If you do not provide a refspec argument to
git pull, the
pull script extracts a very simple one from your current branch’s configuration—in this case, whatever you see from
git config --get branch.master.merge, which apparently is
br1. So this means that if you run
git pull origin, you are in effect running
git pull origin br1.1
Again, all of this is then just passed on to
git fetch, so whether you run
git pull origin, or
git pull origin br1, all of those just wind up invoking:
git fetch origin br1
(which you can also do manually, and you’ll see the above).
We’ll get to
git fetch origin br1:br1 later, below.
Background on possible misconceptions
Let’s take a brief look at your setup statement again:
Say there is a remote branch
br1checkout on the remote repo, and the
masterbranch on a local repo.
What branch, if any, is currently checked-out on the remote is mostly irrelevant for
fetch. The first (or first-enough) thing
fetch does is to connect to the remote and ask it for a list of all references and their corresponding SHA-1s (you can see what
git fetch can see by running
git ls-remote). The remote’s
HEAD is included in that list, and this allows you to direct your
fetch to use it, but if you don’t, your
fetch just ignores it (the remote’s
HEAD is mostly only used for controlling the default initial branch on an initial
The current branch in your local repo is important, though, for two reasons:
- if you don’t supply extra arguments to
git pull, it finds them based on your current branch; and
- after the
git pullruns either
git rebase, which uses your current branch.
Again, your current branch is
pull will use
branch.master.merge as the default remote and refspec arguments.2 This is how we can deduce, from the original output, that these are
git fetch, what it does is to confer with the remote git server a bit to find out what references (branches and tags, mostly) are available and what their corresponding SHA-1 values are. Once it has that information, it then looks at which references you’ve asked it to bring over. If you listed a specific reference like
br1, that’s the one reference it will bring over.
Along with each reference, of course, it has to bring any new objects (the commit itself, and its associated trees and files, plus any parent commits and their trees-and-files as needed) so that you get all the history from that particular point backwards. Whatever history you already have, of course, it can skip.3
As VonC already noted, git’s behavior on
git fetch remote refspec has changed in git 1.8.4 and later. It used to be the case that if you ran
git fetch remote refspec, your refspec overrode the rules in your git configuration entry for that remote, but now it simply selects from them. By default, the rule-set for the remote named
+refs/heads/*:refs/remotes/origin/*, so your
br1 refspec selects an item from this rule-set.
Let’s pause to see what happens if you run
git fetch with only three arguments, like this:
$ git fetch origin
Here you are instructing your local git to connect to the remote, find out what it has, and bring over all branches. The way (and reason) it does that is just as outlined above: it connects, gets a list, and then consults the output of
git config --get-all remote.origin.fetch.4 This is a list of “refspecs”, one per
git config --get-all line.
Since the standard line (one single line) for
+refs/heads/*:refs/remotes/origin/*, your local git will take every reference-name that matches
refs/heads/*. That is, it will take all branches on
origin, because branches are simply “references whose names start with
refs/heads/“. What it does with those branches is determined by the right-hand side of this refspec: it replaces
The result is a “remote-tracking branch”. If the remote has a branch
master, your local git translates this to
origin/master. If the remote has a
br1, your local git translates that to
origin/br1. For each branch on the remote, you get a (local) remote-tracking branch whose name starts with
Returning to our case of
git fetch origin br1, we can now see what happens: our local git brings over
br1, which turns out to be a branch so that its full name is
refs/heads/br1. Because of that, it matches the standard
remote.origin.fetch line and
refs/heads/br1 is translated to
refs/remotes/origin/br1, which causes git to print out
9188a5d..97d4825 br1 -> origin/br1
br1 on the left is the short name of the reference on the remote, and the name
origin/br1 on the right is the short name of the reference that
git fetch has updated.
In the past you would instead see something like this—and you still may see it:
* branch name -> FETCH_HEAD
This indicates that
git fetch found a branch named
name (i.e., a reference of the form
refs/heads/name) on the remote and brought it over to your local repo and put it in
FETCH_HEAD. What is
FETCH_HEAD? It’s a special file that exists pretty much just for the
git pull script. (It works a lot like a reference, but it has a special format and may contains multiple SHA-1s.)
Now we’re (finally) ready to tackle the
br1:br1 case. Here, you’re telling your local
git fetch to bring over reference
br1. It does the usual—call up the remote, discover that
br1 is really
refs/heads/br1, and bring over the reference and any needed objects—but this time, in addition to consulting the
remote.origin.fetch line, it writes the new SHA-1 into the reference you specified.
In this case, you specified
br1 with no qualifications: not
br1. In this case, git sees that it’s a
refs/heads/ reference on the remote, meaning it’s a branch; so git adds
refs/heads/ on your end as well, and creates or updates your own
In other words, this creates or updates your local branch
In addition, git still applies the
remote.origin.fetch line, which is still
+refs/heads/*:refs/remotes/origin/*, so it still updates your remote-tracking branch
origin/br1 (full name
refs/remotes/origin/br1). That’s why you got the output you got from Command 1.
FETCH_HEAD? Well, that’s where the rest of
git pull comes back in: after doing the
git fetch step, the
pull script runs either
git merge or
git rebase. What it merges (or rebases-on-to) is whatever
git fetch left behind in the
FETCH_HEAD file (with some special casing and other caveats that I won’t go into here).
When your current branch is
master but you instruct
git pull to pull
origin br1, it’s the
git merge step that brings
master up to date with
br1. More precisely, the merge gets you up to date with your copy of
origin/br1 as of the time the
git fetch finished—it’s possible that just after your
git fetch finished, someone else did a
git push that updated
br1 on your remote.
The merge is a “fast-forward” merge if possible, but again I won’t go into any more details on that here. I’ll just note that it was possible, so it was done; that’s the
Fast-forward line in the update.
In any case, the merge brought in to your current branch (
master) the changes since the merge-base of your current branch and your target commit (the raw SHA-1 that
git fetch left in the
FETCH_HEAD file, which is also the new SHA-1 of
origin/br1, and in one case, the new SHA-1 of new-or-updated local branch
In pre-1.8.4 versions of git, the
origin/br1 remote-tracking branch is not updated. Everything still works out of the
FETCH_HEAD file though, and it is, if anything, even more confusing than in newer gits, where we can say that you’re now up to date with
origin/br1 without having to be very exacting and picky about “
br1 as it was on the remote at the time you ran
What’s that plus sign?
Sharp-eyed readers will have noted the
+ symbol means “forced update”. Normally, when updating a branch reference—any reference starting with
refs/heads/—git won’t allow the update unless it’s a “fast-forward” label update. Setting the force flag in a refspec allows that particular update. Using
--force on the command line also allows that update, and all other reference updates as well. In other words, the plus sign is simply a more-targeted (single refspec) version of
1This is an overstatement: sometimes it uses a three-argument
2Always true for the remote bit but the refspec bit may be empty, with the
pull script figuring out which refspec to apply later, after
git fetch finishes.
3By default, the
fetch operation will also bring over any tag-name references that match any commit-IDs that it brings over. If you run
git fetch yourself, you can change the way
fetch handles these, but if you just let
git pull run
git fetch you will get this default behavior. Note that it’s your local git that makes these decisions: the remote git simply displays everything to your local git, and then your git decides whether to add tags to your repository.
git fetch just invokes the C code that does this, rather than actually running
git config --get-all. In any case, if there are multiple configuration entries for
git fetch origin really does apply all of them. The way it does this is a bit complicated though, and I will skip the gory details here.
5Remote-tracking branches are really just references whose name starts with
refs/remotes/, just as local branches are references whose name starts with
refs/heads/. This is a general thing in git: your tags are references whose name starts with
git stash script uses a single special reference,
refs/stash. Git’s “notes” are stored under
refs/notes/, and you can invent your own references: just pick a different starting string, and hope that nobody else picks the same one in the future for a new git feature. 🙂
Any line with
origin/xxxx means the
git fetch part of a
git pull (which is
git fetch +
git merge) has updated a remote tracking branch.
that is so since git 1.8.4 (before it only updated
If I do just a “git pull”, it will pull remote br1 into local master
That would depend on
git config branch.b1.merge, which instruct the git merge part of the
git pull where to merge.
By doing a
git pull b1:b1, you are overriding that config and instructing the merge to take place in the local
See also the result of
git branch -avvv to see what local branch is tracking what remote branch.
I’m expecting it also shows something like “br1 -> master”. Why it does not show that?
master was already at