Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Test if Git Repository is Shallow?

Tags:

git

When I make a local clone from a repository, the clone fails if the origin repository is shallow.

git clone -l -- . target-dir

As that is not always the case I'd like to find out prior clone but don't know how to do that.

What I tried so far is very little, basically creating error messages on clone. At the moment I just fetch to unshallow and if that fails, I do a plain fetch because if the repo would be shallow, it should be unshallow afterwards:

if ! git fetch --unshallow; then
    git fetch
fi

However there is no guarantee for being unshallow afterwards (remote to fetch from can be shallow, too), so a test for the (un)shallowness of a git repository would be much better.

like image 389
hakre Avatar asked May 30 '16 18:05

hakre


People also ask

What is a shallow git repository?

A shallow repository has an incomplete history some of whose commits have parents cauterized away (in other words, Git is told to pretend that these commits do not have the parents, even though they are recorded in the commit object).

What is shallow commit?

Definition. Shallow commits do have parents, but not in the shallow repo, and therefore grafts are introduced pretending that these commits have no parents.


2 Answers

If your Git is 2.15 or later, run:

git rev-parse --is-shallow-repository 

which will print false (not shallow) or true (shallow):

if $(git rev-parse --is-shallow-repository); then     ... repository is shallow ... fi 

The answer below dates back to Git versions before 2.15.


If your Git is older than 2.15,1 just test for the file shallow in the Git repository directory:2

if [ -f "$(git rev-parse --git-dir)"/shallow ]; then     echo this is a shallow repository; else     echo not a shallow repository; fi 

or (shorter):

[ -f "$(git rev-parse --git-dir)"/shallow ] && echo true || echo false 

You can turn this into a shell function:

test_shallow() {     [ -f "$(git rev-parse --git-dir)"/shallow ] && echo true || echo false } 

and even automate the Git version checking:

test_shallow() {     set -- $(git rev-parse --is-shallow-repository)     if [ x$1 == x--is-shallow-repository ]; then         [ -f "$(git rev-parse --git-dir)"/shallow ] && set true || set false     fi     echo $1 } 

1git --version will print the current version number:

$ git --version 2.14.1  $ git --version git version 2.7.4 

etc. (I have multiple versions on different VMs/machines at this point.) You can also run:

git rev-parse --is-shallow-repository 

If it just prints --is-shallow-repository, your Git is pre-2.15 and lacks the option.

2To see why there are double quotes around $(git rev-parse --git-dir), see Tom Hale's comment. Note that testing this is a bit tricky since git rev-parse --git-dir from the top level of, e.g., the repository /tmp/with space just prints .git; you must be in a subdirectory, such as /tmp/with space/sub to observe the problem.

like image 172
torek Avatar answered Sep 17 '22 23:09

torek


When you don't have access to the remote repository (not the case here, but still a possible scenario), a git clone is still a good way to test if that remote repository is shallow or not.

The problem is not transfer/create file needlessly when the clone would ultimately fail because of the shallow nature of said remote repository.

This is now fixed with Git 2.32 (Q2 2021): "git clone"(man) new --reject-shallow option fails the clone as soon as we notice that we are cloning from a shallow repository.

See commit 4fe788b (01 Apr 2021) by Li Linchao (Cactusinhand).
(Merged by Junio C Hamano -- gitster -- in commit 22eee7f, 08 Apr 2021)

builtin/clone.c: add --reject-shallow option

Signed-off-by: Li Linchao

In some scenarios, users may want more history than the repository offered for cloning, which happens to be a shallow repository, can give them.
But because users don't know it is a shallow repository until they download it to local, we may want to refuse to clone this kind of repository, without creating any unnecessary files.

The '--depth=x' option cannot be used as a solution; the source may be deep enough to give us 'x' commits when cloned, but the user may later need to deepen the history to arbitrary depth.

Teach '--reject-shallow' option to "git clone"(man) to abort as soon as we find out that we are cloning from a shallow repository.

No local file created!

The error message will be (with the test clone command):

git -c clone.rejectshallow=true clone --no-local shallow-repo source repository is shallow, reject to clone. 

git config now includes in its man page:

clone.rejectShallow

Reject to clone a repository if it is a shallow one, can be overridden by passing option --reject-shallow in command line.

git clone now includes in its man page:

--[no-]reject-shallow

Fail if the source repository is a shallow repository.
The 'clone.rejectShallow' configuration variable can be used to specify the default.

like image 36
VonC Avatar answered Sep 17 '22 23:09

VonC