I just did
get fetch origin feature/8067
and below it I got 3 columns:
* branch feature/8067 -> FETCH_HEAD
* [new branch] feature/8067 -> origin/feature/8067
Trying to process this...reading from here I just learned that FETCH_HEAD
basically means the tip of where I last did a fetch
. The file will contain a commit.
Does that [new branch]
refer to the new branch created under my refs/remote
?
I'm not sure if my reading of the following is correct: feature/8067 -> origin/feature/8067
Is the 2nd column the <nameOfBranchOnRemoteRepo>
while the 3rd column is <repoName/nameOfBranchOnRemoteRepo>
and it says my fetched remote branch in the refs is pointing to that in the remote?
The fetch output is confusing even to an old hand. Here's how I decode them:
* branch feature/8067 -> FETCH_HEAD * [new branch] feature/8067 -> origin/feature/8067
Work each line from right to left:
The first line ends with FETCH_HEAD
, which means that the reference was deposited into FETCH_HEAD
. See the note about FETCH_HEAD
below. The arrow is hardcoded (always appears and you can just sort of ignore it); the name feature/8067
is the name of the reference on the remote; and * branch
tells you that it was really refs/heads/feature/8067
on the remote, i.e., was a branch. Because this was deposited into FETCH_HEAD
there's no additional information available.
The second line ends with origin/feature/8067
. Your remote-tracking name1 origin/feature/8067
(full name refs/remotes/origin/feature/8067
) has been created or updated. As before, we have the arrow and the same name. Then we have * [new branch]
: this tells us that origin/feature/8067
did not exist before, and that feature/8067
was—as we already know—a branch name on the remote.
Here's what I get updating a Git repository for Git:
ab15ad1a3b..aa25c82427 master -> origin/master ef7435264c..5a294203ad next -> origin/next + f98c0007ae...e49ac33073 pu -> origin/pu (forced update) 0f4b6a451a..ff8db353a4 todo -> origin/todo * [new tag] v2.22.0-rc1 -> v2.22.0-rc1
Again we can work right to left:
My origin/master
got created-or-updated, from their master
. The value of my origin/master
was ab15ad1a3b
but is now aa25c82427
. Since there was a value, it's been updated, not created.
My origin/next
has been created-or-updated, with everything else basically the same as above (modulo the obvious differences).
My origin/pu
has been updated by force, i.e., this is not a fast-forward and some commits have been deleted. The source was their pu
branch and my origin/pu
used to be f98c0007ae
but is now ff8db353a4
. The fact that there are three dots between the two hash IDs—the other lines have only two dots—means that the update was forced, hence not a fast-forward. The plus sign at the very front means that the update was forced. (Clearly, it's pretty important that the update was forced: I have three announcements to that effect!)
My origin/todo
has been created-or-updated, and by the time we get to the left side, it's obviously an update.
My v2.22.0-rc1
has been created-or-updated, from their v2.22.0-rc1
; this is a new tag.
Any time you have a new name (branch, tag, or any other reference), it's by definition a regular non-forced creation and there's no old..new
hash available, so the left edge will read * [new whatever]
.
FETCH_HEAD
is special: all updates get written to .git/FETCH_HEAD
, usually wiping out whatever was in it before (but with -a
or --append
, git fetch
will append instead). Each fetched reference results in one line appearing in FETCH_HEAD
, giving:
not-for-merge
stringthe type and name of the reference and its source:
$ cat .git/FETCH_HEAD
aa25c82427ae70aebf3b8f970f2afd54e9a2a8c6 branch 'master' of git://...
[snipped for length]
The one line that is not marked not-for-merge
is suitable for the git pull
script2 to fish out and pass that hash ID to git merge
or git rebase
.
1A remote-tracking name, which most of Git calls a remote-tracking branch, is a reference in your repository whose full name starts with refs/remotes/
and goes on to include the name of the remote, in this case origin
, and another slash, and then normally holds the rest of the branch name as seen on that remote.
A reference is just the generalized name for things that are branches, tags, remote-tracking names, refs/stash
, and so on: a string-format name, generally starting with refs/
, that remembers one hash ID. For a branch, the one hash ID the name remembers is the commit that Git should consider to be the tip of that branch. For a tag, the one hash ID the name remembers is either the hash ID of the commit, or the hash ID of an annotated tag object that contains additional information (perhaps including a signing key), plus the hash ID of the tagged object (typically a commit though any tag can point to any one of Git's internal object types).
Git builds remote-tracking names through a refspec. You can supply a refspec when you run git fetch
. If you do not supply a refspec, but do supply a remote name like origin
, Git fishes the correct refspec from your configuration:
$ git config --get-all remote.origin.fetch
+refs/heads/*:refs/remotes/origin/*
A standard configuration for origin
always has this exact default refspec, but there are some useful nonstandard configurations, such as the one created by git clone --single-branch
. You can also make your own totally bizarre refspecs, though depending on how twisted you get, some combinations will result in a non-functioning git fetch
.
2Well, back when when git pull
was a script, anyway. It's been re-coded in C for speed on Windows.