12

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:

git 2.14.1.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
  • From the documentation for git clone: `git clone C:\folder1 folder2` https://www.kernel.org/pub/software/scm/git/docs/git-clone.html#URLS – Ivan Sheihets Nov 15 '17 at 12:52
  • 2
    @IvanSheigets but isn't `C:\ ` an absolute path? And does it work with `--depth` without `file://`? In Linux `--depth` requires `file://`. – Ciro Santilli OurBigBook.com Nov 15 '17 at 13:36
  • 2
    You are correct: URL/URI simply does not allow relative paths. Git probably should embrace-and-extend here, so as to allow it anyway. – torek Nov 15 '17 at 20:14
  • 2
    This is killer. Thanks so much. Way too many people say this is not possible. – jooks Mar 07 '18 at 19:16

3 Answers3

4

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
ReeseWang
  • 131
  • 1
  • 7
  • Thank you for you clear explanation. However, I can't agree with you that it doesn't save space and isn't faster. It DOES save space, and, most importantly, DOES make things faster (well, just normal), in some circumstances. In my case, it is working on the mounted NFS share, and since it doesn't hard-link (thinks different machines maybe), and works so slow with many small files, it is a real problem. So, before judging "you are all wrong", think about use-cases you just didn't know about. But thanks. – latitov Nov 26 '21 at 11:53
2

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.

Community
  • 1
  • 1
ensc
  • 6,704
  • 14
  • 22
-3

You should try without the file:// prefix:

git clone --depth 1 ./mymodule mymodule2
mab
  • 378
  • 1
  • 8
  • That's a great way to get the warning/error/bug described here: https://stackoverflow.com/q/40383230/1180930. – jvriesem May 08 '19 at 22:36