Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git fetch a single commit

Tags:

git

github

I would like to fetch a single commit (with history, of course) of a remote repository into a local one. Some Stack Overflow responses suggest that the following should work, but it does not:

md foo
cd foo
git init
git fetch https://github.com/ld4apps/lda-serverlib.git f1e32e18a90e10c150221af55c69aeafaa42c57a

This produces the following error:

error: no such remote ref f1e32e18a90e10c150221af55c69aeafaa42c57a

Surprisingly (to me) the following does (sort of) work:

git fetch https://github.com/ld4apps/lda-serverlib.git :f1e32e18a90e10c150221af55c69aeafaa42c57a

This creates a new local branch called f1e32e18a90e10c150221af55c69aeafaa42c57a (which I did not want), but at least the new branch has the contents I was trying to fetch. I might have expected that the following command would do the same thing, but it gets the same error as the first example:

git fetch https://github.com/ld4apps/lda-serverlib.git f1e32e18a90e10c150221af55c69aeafaa42c57a:f1e32e18a90e10c150221af55c69aeafaa42c57a

I tried this on Windows and Linux with a couple of different git versions and saw the same behavior.

Can anyone explain what is going on here? What am I not understanding about Git, fetch, and refspecs? What I really want is a single git fetch command to which I can provide either the id of a remote branch or tag or a commit id and it will fetch the corresponding commit.

like image 235
Martin Nally Avatar asked Sep 12 '14 19:09

Martin Nally


People also ask

How do I pull a single commit?

How do I pull a specific commit? The short answer is: you cannot pull a specific commit from a remote. However, you may fetch new data from the remote and then use git-checkout COMMIT_ID to view the code at the COMMIT_ID .

How do I find a specific commit in git?

Looking up changes for a specific commit If you have the hash for a commit, you can use the git show command to display the changes for that single commit. The output is identical to each individual commit when using git log -p .

How do I fetch a single branch?

just need to run git fetch , which will retrieve all branches and updates, and after that, run git checkout <branch> which will create a local copy of the branch because all branches are already loaded in your system.

Can you pull a single file from git?

GitHub lets you download one file from a repository. This is a useful feature because it means you do not have to clone or retrieve an entire repository to download a particular file.


1 Answers

Update: since Git 2.5 (mid-2015 or so), servers now may expose raw hashes. This is a server-side configuration item. You must have sufficient control on the server to set it, and you should consider potential security issues before you do set it. See this answer to Retrieve specific commit from a remote Git repository for details. (Original answer, which applies to pre-2.5 or if the configuration knob is not set, below.)


The git fetch command delivers references (names, not raw commit-IDs) to the remote, more or less. (More specifically, use git ls-remote remotename to see what the remote is willing to give you in terms of names. This produces a list of SHA-1s on the left with names on the right, and the only thing your fetch can ask for is the names-on-the-right. At which point you'll get the ID-on-the-left if the name on the remote still points to that ID, so it depends on how actively that remote gets updated.)

It is possible, in various ways, to deliver raw commit-IDs to a remote and ask that remote what is visible starting from that point, and sometimes working backwards through history as well, but not via git fetch. (You can use git archive but the remote can decide whether or not to allow you to access via raw commit-IDs; or with remotes that have web server access, including to specific commits, you can often just view the top-level contents of a commit, and use that to "drill down", as they say, to the various pieces. But that is a very slow way to do it.)

If you'd like to use git fetch to get some particular commit, probably the easiest way to do that is to have someone with access to the remote attach a name—most likely a tag—to that commit ID. Then you can have your git fetch bring over that refspec, and put it under any other refspec you like. For instance, suppose you can ssh directly to whatever hosts origin:

$ 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 need not be a branch, it need only be a reference you can pull over with git fetch and see with git ls-remote. You then use a name that will match that on the left-hand-side of your refspec when fetching. The name created in your repo is controlled by the right-hand-side of the refspec (refs/heads/newbranch in the example above).

This is also the answer to your last paragraph question: you can only name things that have names on the remote (this is partly intended to avoid "leaking" unnamed commits that remain in a repository before garbage-collection, so it's considered a feature rather than a bug). These names go on the LHS of the refspec. Your own names go on the right.

Your name on the right is assumed to be a branch or tag name (based on what the name on the left matches, though you can explicitly spell out refs/heads/ or refs/tags/ to override it), so even though f1e32e1... is a valid SHA-1, it's treated as a branch name here—the missing name on the left translates to HEAD, as missing names almost always do—and git fetch creates a branch whose name is disturbingly SHA-1-ish. (Incidentally I once created a branch name that looked like an SHA-1, and later confused myself. I forget exactly what the name was, something like de-bead without the hyphen. I renamed it to the hyphenated version just to make it clear I didn't mean a raw commit ID! :-) )

like image 140
torek Avatar answered Oct 11 '22 22:10

torek