Update: With Git 2.5 (mid-2015 or so), servers can now expose raw hashes. This is a server side configuration item. You must have sufficient control over the server to install it, and you must consider potential security issues before installing it. See this answer in Get a specific commit from a remote Git repository for more details. (Original answer that applies to pre-2.5 or if the configuration knob is not installed below).
The git fetch command delivers links (names, not raw commit identifiers) to the console, more or less. (More specifically, use git ls-remote remotename to find out what the remote user wants to give you in terms of names. This will display the SHA-1 list on the left with the names on the right, and the only thing your fetch for can offer are the names by -Right. At this point, you will get ID-on-left if the name on the remote computer still points to this ID, so it depends on how actively this remote file is updated.)
In different ways, you can deliver raw commit identifiers to a remote server and request the remote what is visible from this point, and sometimes work backwards through history, but not through git fetch . (You can use git archive , but the remote computer can decide whether to allow you access through raw commit identifiers, or using remote controls that have access to the web server, including specific commits, you can simply simply view the contents the top level of the commit and use this to βexpandβ, as they say, different parts, but this is a very slow way to do this.)
If you want to use git fetch to get a specific commit, perhaps the easiest way to do this is to force someone with remote access to connect the name, most likely a commit identifier tag. You can then return git fetch this refspec and place it under any other refspec you like. For example, suppose you can ssh directly to any origin hosts:
$ ssh our.origin.host 'cd /repos/repo.git; git tag temporary f1e32e1' [enter password, etc; observe tag created] $ git fetch origin refs/tags/temporary:refs/heads/newbranch [observe fetch happen; now you have local branch 'newbranch'] $ ssh our.origin.host 'cd /repos/repo.git; git tag -d temporary'
Note that the name does not have to be a branch, it should only be a link that you can pull with git fetch and see with git ls-remote . Then you use a name that will match the one on the left side of your refspec when retrieving. The name created in your repo is controlled by the right side of refspec ( refs/heads/newbranch in the above example).
This is also the answer to your last question in the paragraph: you can only name names that have names on the remote computer (this is partially designed to avoid the βleakβ of unnamed commits that remain in the repository until garbage collection, so he looked at the function, not a mistake). These names are included in the LHS refspec. Your own names go to the right.
Your name on the right is considered the name of the branch or tag (depending on what matches the name on the left, although you can explicitly specify refs/heads/ or refs/tags/ to override it), so even if f1e32e1... is a valid SHA -1, it is considered as the branch name here - the missing name on the left translates to HEAD , since the missing names are almost always executed - and git fetch creates a branch whose name causes the SHA-1 -ish alarm. (By the way, I once created a branch name that looked like SHA-1, and later embarrassed myself. I forgot that it was this name, something like a de-bead without a hyphen. I renamed it to a portable version to make it understandable I did not mean the raw commit id! :-))