Retrieve specific commit from a remote Git repository

后端 未结 10 1612
谎友^
谎友^ 2020-11-22 06:32

Is there any way to retrieve only one specific commit from a remote Git repo without cloning it on my PC? The structure of remote repo is absolutely same as that of mine and

相关标签:
10条回答
  • 2020-11-22 06:51

    You can simply fetch a single commit of a remote repo with

    git fetch <repo> <commit>
    

    where,

    • <repo> can be a remote repo name (e.g. origin) or even a remote repo URL (e.g. https://git.foo.com/myrepo.git)
    • <commit> can be the SHA1 commit

    for example

    git fetch https://git.foo.com/myrepo.git 0a071603d87e0b89738599c160583a19a6d95545
    

    after you fetched the commit (and the missing ancestors) you can simply checkout it with

    git checkout FETCH_HEAD
    

    Note that this will bring you in the "detached head" state.

    0 讨论(0)
  • 2020-11-22 06:52

    You can simply fetch the remote repo with:

    git fetch <repo>
    

    where,

    • <repo> can be a remote repo name (e.g. origin) or even a remote repo URL (e.g. https://git.foo.com/myrepo.git)

    for example:

    git fetch https://git.foo.com/myrepo.git 
    

    after you fetched the repos you may merge the commits that you want (since the question is about retrieve one commit, instead merge you may use cherry-pick to pick just one commit):

    git merge <commit>
    
    • <commit> can be the SHA1 commit

    for example:

    git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545
    

    or

    git merge 0a071603d87e0b89738599c160583a19a6d95545
    

    if is the latest commit that you want to merge, you also may use FETCH_HEAD variable :

    git cherry-pick (or merge) FETCH_HEAD
    
    0 讨论(0)
  • 2020-11-22 06:53

    In a project we had a problem so that we had to revert back to a certain commit. We made it with the following command successfully:

    git reset --hard <commitID>
    
    0 讨论(0)
  • 2020-11-22 06:57

    Starting with Git version 2.5+ (Q2 2015), fetching a single commit (without cloning the full repo) is actually possible.

    See commit 68ee628 by Fredrik Medley (moroten), 21 May 2015.
    (Merged by Junio C Hamano -- gitster -- in commit a9d3493, 01 Jun 2015)

    You now have a new config (on the server side)

    uploadpack.allowReachableSHA1InWant
    

    Allow upload-pack to accept a fetch request that asks for an object that is reachable from any ref tip. However, note that calculating object reachability is computationally expensive.
    Defaults to false.

    If you combine that server-side configuration with a shallow clone (git fetch --depth=1), you can ask for a single commit (see t/t5516-fetch-push.sh:

    git fetch --depth=1 ../testrepo/.git $SHA1
    

    You can use the git cat-file command to see that the commit has been fetched:

    git cat-file commit $SHA1
    

    "git upload-pack" that serves "git fetch" can be told to serve commits that are not at the tip of any ref, as long as they are reachable from a ref, with uploadpack.allowReachableSHA1InWant configuration variable.


    The full documentation is:

    upload-pack: optionally allow fetching reachable sha1

    With uploadpack.allowReachableSHA1InWant configuration option set on the server side, "git fetch" can make a request with a "want" line that names an object that has not been advertised (likely to have been obtained out of band or from a submodule pointer).
    Only objects reachable from the branch tips, i.e. the union of advertised branches and branches hidden by transfer.hideRefs, will be processed.
    Note that there is an associated cost of having to walk back the history to check the reachability.

    This feature can be used when obtaining the content of a certain commit, for which the sha1 is known, without the need of cloning the whole repository, especially if a shallow fetch is used.

    Useful cases are e.g.

    • repositories containing large files in the history,
    • fetching only the needed data for a submodule checkout,
    • when sharing a sha1 without telling which exact branch it belongs to and in Gerrit, if you think in terms of commits instead of change numbers.
      (The Gerrit case has already been solved through allowTipSHA1InWant as every Gerrit change has a ref.)

    Git 2.6 (Q3 2015) will improve that model.
    See commit 2bc31d1, commit cc118a6 (28 Jul 2015) by Jeff King (peff).
    (Merged by Junio C Hamano -- gitster -- in commit 824a0be, 19 Aug 2015)

    refs: support negative transfer.hideRefs

    If you hide a hierarchy of refs using the transfer.hideRefs config, there is no way to later override that config to "unhide" it.
    This patch implements a "negative" hide which causes matches to immediately be marked as unhidden, even if another match would hide it.
    We take care to apply the matches in reverse-order from how they are fed to us by the config machinery, as that lets our usual "last one wins" config precedence work (and entries in .git/config, for example, will override /etc/gitconfig).

    So you can now do:

    git config --system transfer.hideRefs refs/secret
    git config transfer.hideRefs '!refs/secret/not-so-secret'
    

    to hide refs/secret in all repos, except for one public bit in one specific repo.


    Git 2.7 (Nov/Dec 2015) will improve again:

    See commit 948bfa2, commit 00b293e (05 Nov 2015), commit 78a766a, commit 92cab49, commit 92cab49, commit 92cab49 (03 Nov 2015), commit 00b293e, commit 00b293e (05 Nov 2015), and commit 92cab49, commit 92cab49, commit 92cab49, commit 92cab49 (03 Nov 2015) by Lukas Fleischer (lfos).
    Helped-by: Eric Sunshine (sunshineco).
    (Merged by Jeff King -- peff -- in commit dbba85e, 20 Nov 2015)

    config.txt: document the semantics of hideRefs with namespaces

    Right now, there is no clear definition of how transfer.hideRefs should behave when a namespace is set.
    Explain that hideRefs prefixes match stripped names in that case. This is how hideRefs patterns are currently handled in receive-pack.

    hideRefs: add support for matching full refs

    In addition to matching stripped refs, one can now add hideRefs patterns that the full (unstripped) ref is matched against.
    To distinguish between stripped and full matches, those new patterns must be prefixed with a circumflex (^).

    Hence the new documentation:

    transfer.hideRefs:
    

    If a namespace is in use, the namespace prefix is stripped from each reference before it is matched against transfer.hiderefs patterns.
    For example, if refs/heads/master is specified in transfer.hideRefs and the current namespace is foo, then refs/namespaces/foo/refs/heads/master is omitted from the advertisements but refs/heads/master and refs/namespaces/bar/refs/heads/master are still advertised as so-called "have" lines.
    In order to match refs before stripping, add a ^ in front of the ref name. If you combine ! and ^, ! must be specified first.


    R.. mentions in the comments the config uploadpack.allowAnySHA1InWant, which allows upload-pack to accept a fetch request that asks for any object at all. (Defaults to false).

    See commit f8edeaa (Nov. 2016, Git v2.11.1) by David "novalis" Turner (novalis):

    upload-pack: optionally allow fetching any sha1

    It seems a little silly to do a reachabilty check in the case where we trust the user to access absolutely everything in the repository.

    Also, it's racy in a distributed system -- perhaps one server advertises a ref, but another has since had a force-push to that ref, and perhaps the two HTTP requests end up directed to these different servers.

    0 讨论(0)
提交回复
热议问题