Short version: Is it possible to use 'git fetch' to get commits from a remote repo that are not visible in the git log (part of/under the HEAD commit)
Longer version: I have a repo (remote copy) that looks like this:
A - B - C - D(HEAD)
\
\-E
The remote version got to this state by making commit E, resetting to commit C, then making commit D.
Locally, I have an old clone of that repo that looks like this:
A - B - C(HEAD)
When I fetch from the remote repo, I only get commit D, but I would like to be able to reset --hard to commit E in my local repo.
Some background first so that it's clearer what I mean below: The fetch
command works in two parts, one on your end (you run git fetch
) and one on the remote (the remote gets the incoming request over http://
, git://
, ssh://
, or some other protocol and fires up something, usually the internal git upload-pack
program). The upload-pack step, which runs on the remote, makes a series of offers of the form "I have an object" (typically a commit or annotated tag) "with ID id of type type named name".
You can see what the remote will offer by running git ls-remote
instead of git fetch
. This still runs upload-pack
but instead of retrieving what is offered, it just shows (lists) the offers.
Whatever you see here in the offer list is what you can get. If it does not show up here, you cannot get it—or at least, not through git fetch
. Some other methods, including git archive
, may allow you to access commits by their raw SHA-1s, if you know them.
Given your description, it sounds like the remote has reflogs turned on (is a regular, non-bare repository). Commit E
used to be on some branch (and at HEAD
) but has been reset away so that it is only accessible through the two reflogs for HEAD
and the branch.
Normally1 upload-pack
offers HEAD
plus all refs in refs
. Reflogs are not in refs
so upload-pack
does not offer them. This means that if there is no current ref pointing to your commit E
it will not be offered. To get it to be offered, log in to the remote and create a ref pointing to commit E
, and then it will.
1This is somewhat configurable; see git-namespaces
and the three hideRefs
configuration items in git-config
.