Reputation: 149
Jenkins Git plugin generated the below command in console output based on my ref spec
What's the difference between below 2 commands? Their output looks little different. I have given their output below:
Command 1:
git fetch --no-tags --progress repo.git +refs/heads/qa:refs/remotes/origin/qa --depth=1
Output:
From <repo>
* [new branch] qa -> origin/qa
Command 2:
git fetch --no-tags --progress repo.git refs/heads/qa --depth=1
Output:
From <repo>
* branch qa -> FETCH_HEAD
What does FETCH_HEAD here mean?
I believe refs/heads/qa
is local working copy of 'qa' branch and refs/remotes/origin/qa
is remote 'qa' branch. But, what does this convention imply?
+refs/heads/qa:refs/remotes/origin/qa
Upvotes: 3
Views: 4056
Reputation: 487755
The syntax with two references separated by a colon, with the whole thing optionally prefixed with a plus sign, is a refspec. Refspecs may also omit the colon and contain only one reference, in which case the plus sign may (depending on the use of this degenerate refspec) be functionless. For more on refspecs, see, e.g., What is the difference between these `git fetch` syntaxes?
Taking the questions themselves in reverse order, though:
Item 3 is just plain wrong. The name refs/heads/qa
is the branch name; it's simply spelled out in full, as it should be in a refspec. It's not a "working copy" at all: it's just a name. Git uses names—references—to map from human-readable strings like master
and qa
to Git's internal hash IDs. The word reference is a generalization of branches, tags, remote-tracking branches, and other such names.
Similarly, refs/remotes/origin/qa
is the fully-spelled-out reference that is your remote-tracking branch normally shortened to origin/qa
. Just as with the branch whose full name is refs/heads/qa
, Git uses this name to map from the human-readable string origin/qa
to hash ID.
The name FETCH_HEAD
refers to a file in the .git
directory, .git/FETCH_HEAD
. When you use the very ancient form of git fetch
, from before the invention of remote-tracking branches, Git has to store all the fetched name-and-ID values somewhere. That "somewhere" is this file. Other Git commands can then fish out each name-and-ID pair.
Back in the Dim Time, before 2007 or so, this was the only way you could use git fetch
. Remote-tracking branch names were invented because it is nice to have your own Git remember these names for much longer periods—each new git fetch
overwrites old data1 unless you use -a
—and in ways that are easier to use.
For item 1 (what's the difference), see the other answer.
1If you only ever fetch from one remote (e.g., from origin
), and you always fetch all names, this is actually perfectly reasonable behavior: overwrite the old, stale information with new, correct information. It breaks down when you fetch from more than one remote and/or when you fetch items piecemeal. Remote-tracking branch names, despite their not-so-great-in-retrospect name, are really quite an improvement.
Upvotes: 2