Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to shallow clone a local git repository with a relative path?

Tags:

git

Shallow clones of local directories require file:// as explained at: git clone: warning: --depth is ignored in local clones; use file:// instead

But how to use relative paths with that?

E.g.: if I have a repo myrepo in the current directory, and then I do:

git clone --depth 1 file://mymodule mymodule2

then it fails with:

Cloning into 'mymodule2'...
fatal: No path specified. See 'man git-pull' for valid url syntax

And if I try:

git clone --depth 1 file://./mymodule mymodule2

It fails with:

Cloning into 'mymodule2'...
fatal: '/./mymodule' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

The only workaround I could find was to convert it to an absolute path starting with /:

git clone --depth 1 "file://$(pwd)/mymodule" mymodule2

Is there a profound reason for this behavior, or it just buggy?

Maybe file URIs simply don't support relative paths:

  • File Uri Scheme and Relative Files
  • https://superuser.com/questions/210263/file-to-point-a-relative-file-to-current-directory

git 2.14.1.


2 Answers

But how to use relative paths with that?

This is not supported; file:// expects only absolute paths. There are e.g. RFC1738 and RFC8089 which describe this kind of URIs.

A file URL takes the form:

   file://<host>/<path>

where is the fully qualified domain name of the system on
which the is accessible, and is a hierarchical
directory path of the form //.../.

When you write file://mymodule, the mymodule can be interpreted as a hostname.

like image 71
ensc Avatar answered Oct 28 '22 23:10

ensc


It's neither necessary nor beneficial to shallow clone a local repo. Just git clone ./relative/path and you are good to go.

I assume you want to shallow copy because you want to save the disk space and save time, but

1. It doesn't save disk space in local cloning.

From Git 2.24.1 manual:

For local repositories, also supported by Git natively, the following syntaxes may be used:

• /path/to/repo.git/

• file:///path/to/repo.git/

These two syntaxes are mostly equivalent, except the former implies --local option.

and

-l, --local

When the repository to clone from is on a local machine, this flag bypasses the normal "Git aware" transport mechanism and clones the repository by making a copy of HEAD and everything under objects and refs directories. The files under .git/objects/ directory are hardlinked to save space when possible.

So a shallow copy with file:///path/to/repo.git/ syntax should consume more disk space than a full copy with /path/to/repo.git/ syntax because the former has real copies of objects instead of hard links.

(And I believe that hard-linking is the reason why --depth get ignored when --local is set.)

2. It doesn't save time either.

Still, Git 2.24.1 manual:

-l, --local

When the repository to clone from is on a local machine, this flag bypasses the normal "Git aware" transport mechanism and clones the repository by making a copy of HEAD and everything under objects and refs directories. The files under .git/objects/ directory are hardlinked to save space when possible.

"Git aware" transport mechanism is time-consuming even when the URI is file://... because it includes object compressing:

$ time git clone --depth 1 --local --shallow-submodules file://$(pwd)/../linux
Cloning into 'linux'...
warning: --local is ignored
remote: Enumerating objects: 65607, done.
remote: Counting objects: 100% (65607/65607), done.
remote: Compressing objects: 100% (61137/61137), done.
remote: Total 65607 (delta 4886), reused 39965 (delta 3556)
Receiving objects: 100% (65607/65607), 176.65 MiB | 10.81 MiB/s, done.
Resolving deltas: 100% (4886/4886), done.
Updating files: 100% (61793/61793), done.
git clone --depth 1 --local --shallow-submodules  73.55s user 4.97s system 245% cpu 31.976 total

(I don't know why the receiving speed is 10.81 MiB/s on my NVMe SSD)

And cloning with --local flag is much quicker:

$ time git clone ../linux
Cloning into 'linux'...
done.
Updating files: 100% (61793/61793), done.
git clone ../linux  4.16s user 1.71s system 100% cpu 5.857 total
like image 28
ReeseWang Avatar answered Oct 28 '22 23:10

ReeseWang