Retrieve a single file from a repository

Viewed 299354

What is the most efficient mechanism (in respect to data transferred and disk space used) to get the contents of a single file from a remote git repository?

So far I've managed to come up with:

git clone --no-checkout --depth 1 git@github.com:foo/bar.git && cd bar && git show HEAD:path/to/file.txt

This still seems overkill.

What about getting multiple files from the repo?

24 Answers

If there is web interface deployed (like gitweb, cgit, Gitorious, ginatra), you can use it to download single file ('raw' or 'plain' view).

If other side enabled it, you can use git archive's '--remote=<URL>' option (and possibly limit it to a directory given file resides in), for example:

$ git archive --remote=git@github.com:foo/bar.git --prefix=path/to/ HEAD:path/to/ |  tar xvf -

I solved in this way:

git archive --remote=ssh://git@gitlab.com/user/mi-repo.git BranchName /path-to-file/file_name | tar -xO /path-to-file/file_name > /path-to-save-the-file/file_name

If you want, you could replace "BranchName" for "HEAD"

It seems to me the easiest way to use the following:

wget https://github.com/name/folder/file.zip?raw=true

If no other answer worked (i.e. restrictive GitLab access), you can do a "selective-checkout" by:

  1. git clone --no-checkout --depth=1 --no-tags URL
  2. git restore --staged DIR-OR-FILE
  3. git checkout DIR-OR-FILE

Although this solution is 100% git compliant and you can checkout a directory, it's not disk nor network optimal as doing a wget/curl on a file.

This is specific for git repos hosted on GitHub

Try the 'api' command of Github's command line app, gh, to make an authenticated call to Github's 'get repository contents' endpoint.

The basic command is:

$gh api /repos/{owner}/{repo}/contents/<path_to_the_file>

As an added bonus, when you do this from inside a directory that contains a clone of the repo you're trying to get the file from, the {owner} and {repo} part will be automatically filled in.

https://docs.github.com/en/rest/reference/repos#get-repository-content

The response will be a JSON object. If the <path_to_the_file> indeed points to a file, the JSON will include a 'size', 'name', several url fields to access the file, as well as a 'content' field, which is a base64 encoded version of the file contents.

To get the file contents, you can curl the value of the "download_url", or just decode the 'content' field. You can do that by piping the base64 command, like this:

$gh api /repos/{owner}/{repo}/contents/<path-to-the-file> --jq '.content' | base64 -d

If your Git repository hosted on Azure-DevOps (VSTS) you can retrieve a single file with Rest API.

The format of this API looks like this:

 https://dev.azure.com/{organization}/_apis/git/repositories/{repositoryId}/items?path={pathToFile}&api-version=4.1?download=true

For example:

 https://dev.azure.com/{organization}/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/items?scopePath=/MyWebSite/MyWebSite/Views/Home/_Home.cshtml&download=true&api-version=4.1

The following 2 commands worked for me:

git archive --remote={remote_repo_git_url} {branch} {file_to_download} -o {tar_out_file}

Downloads file_to_download as tar archive from branch of remote repository whose url is remote_repo_git_url and stores it in tar_out_file

tar -x -f {tar_out_file}.tar extracts the file_to_download from tar_out_file

Github Enterprise Solution

HTTPS_DOMAIN=https://git.your-company.com
ORGANISATION=org
REPO_NAME=my-amazing-library
FILE_PATH=path/to/some/file
BRANCH=develop
GITHUB_PERSONAL_ACCESS_TOKEN=<your-access-token>

URL="${HTTPS_DOMAIN}/raw/${ORGANISATION}/${REPO_NAME}/${BRANCH}/${FILE_PATH}"

curl -H "Authorization: token ${GITHUB_PERSONAL_ACCESS_TOKEN}" ${URL} > "${FILE_PATH}"

for bitbucket directly from browser (I used safari...) right-click on 'View Raw" and choose "Download Linked File":

enter image description here

If you don't mind cloning the entire directory, this small bash/zsh function will have the end result of cloning a single file into your current directory (by cloning the repo into a temp directory and removing it afterwards).

Pro: You only get the file you want

Con: You still have to wait for the whole repo to clone

git-single-file () {
        if [ $# -lt 2 ]
        then
                echo "Usage: $0 <repo url> <file path>"
                return
        fi
        TEMP_DIR=$(mktemp -d)
        git clone $1 $TEMP_DIR
        cp $TEMP_DIR/$2 .
        rm -rf $TEMP_DIR
}

If your goal is just to download the file there's a hassle-free application called gget:

gget github.com/gohugoio/hugo 'hugo_extended_*_Linux-ARM.deb'

The above example would download single file from hugo repository.

https://github.com/dpb587/gget

Related