Skip to content

Commit 4dcb167

Browse files
pcloudsgitster
authored andcommitted
fetch: add --unshallow for turning shallow repo into complete one
The user can do --depth=2147483647 (*) for restoring complete repo now. But it's hard to remember. Any other numbers larger than the longest commit chain in the repository would also do, but some guessing may be involved. Make easy-to-remember --unshallow an alias for --depth=2147483647. Make upload-pack recognize this special number as infinite depth. The effect is essentially the same as before, except that upload-pack is more efficient because it does not have to traverse to the bottom anymore. The chance of a user actually wanting exactly 2147483647 commits depth, not infinite, on a repository with a history that long, is probably too small to consider. The client can learn to add or subtract one commit to avoid the special treatment when that actually happens. (*) This is the largest positive number a 32-bit signed integer can contain. JGit and older C Git store depth as "int" so both are OK with this number. Dulwich does not support shallow clone. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 1599999 commit 4dcb167

File tree

7 files changed

+58
-4
lines changed

7 files changed

+58
-4
lines changed

Documentation/fetch-options.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
to the specified number of commits from the tip of each remote
1414
branch history. Tags for the deepened commits are not fetched.
1515

16+
--unshallow::
17+
Convert a shallow repository to a complete one, removing all
18+
the limitations imposed by shallow repositories.
19+
1620
ifndef::git-pull[]
1721
--dry-run::
1822
Show what would be done, without making any changes.

Documentation/git-fetch-pack.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ be in a separate packet, and the list must end with a flush packet.
8484

8585
--depth=<n>::
8686
Limit fetching to ancestor-chains not longer than n.
87+
'git-upload-pack' treats the special depth 2147483647 as
88+
infinite even if there is an ancestor-chain that long.
8789

8890
--no-progress::
8991
Do not show the progress.

Documentation/technical/shallow.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,6 @@ It also writes an appropriate $GIT_DIR/shallow.
5353
You can deepen a shallow repository with "git-fetch --depth 20
5454
repo branch", which will fetch branch from repo, but stop at depth
5555
20, updating $GIT_DIR/shallow.
56+
57+
The special depth 2147483647 (or 0x7fffffff, the largest positive
58+
number a signed 32-bit integer can contain) means infinite depth.

builtin/fetch.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ enum {
3232

3333
static int all, append, dry_run, force, keep, multiple, prune, update_head_ok, verbosity;
3434
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
35-
static int tags = TAGS_DEFAULT;
35+
static int tags = TAGS_DEFAULT, unshallow;
3636
static const char *depth;
3737
static const char *upload_pack;
3838
static struct strbuf default_rla = STRBUF_INIT;
@@ -82,6 +82,9 @@ static struct option builtin_fetch_options[] = {
8282
OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
8383
OPT_STRING(0, "depth", &depth, N_("depth"),
8484
N_("deepen history of shallow clone")),
85+
{ OPTION_SET_INT, 0, "unshallow", &unshallow, NULL,
86+
N_("convert to a complete repository"),
87+
PARSE_OPT_NONEG | PARSE_OPT_NOARG, NULL, 1 },
8588
{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
8689
N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
8790
{ OPTION_STRING, 0, "recurse-submodules-default",
@@ -970,6 +973,18 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
970973
argc = parse_options(argc, argv, prefix,
971974
builtin_fetch_options, builtin_fetch_usage, 0);
972975

976+
if (unshallow) {
977+
if (depth)
978+
die(_("--depth and --unshallow cannot be used together"));
979+
else if (!is_repository_shallow())
980+
die(_("--unshallow on a complete repository does not make sense"));
981+
else {
982+
static char inf_depth[12];
983+
sprintf(inf_depth, "%d", INFINITE_DEPTH);
984+
depth = inf_depth;
985+
}
986+
}
987+
973988
if (recurse_submodules != RECURSE_SUBMODULES_OFF) {
974989
if (recurse_submodules_default) {
975990
int arg = parse_fetch_recurse_submodules_arg("--recurse-submodules-default", recurse_submodules_default);

commit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *r
163163
extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup);
164164
extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
165165

166+
/* largest postive number a signed 32-bit integer can contain */
167+
#define INFINITE_DEPTH 0x7fffffff
168+
166169
extern int register_shallow(const unsigned char *sha1);
167170
extern int unregister_shallow(const unsigned char *sha1);
168171
extern int for_each_commit_graft(each_commit_graft_fn, void *);

t/t5500-fetch-pack.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,26 @@ test_expect_success 'clone shallow object count' '
264264
grep "^count: 52" count.shallow
265265
'
266266

267+
test_expect_success 'fetch --no-shallow on full repo' '
268+
test_must_fail git fetch --noshallow
269+
'
270+
271+
test_expect_success 'fetch --depth --no-shallow' '
272+
(
273+
cd shallow &&
274+
test_must_fail git fetch --depth=1 --noshallow
275+
)
276+
'
277+
278+
test_expect_success 'turn shallow to complete repository' '
279+
(
280+
cd shallow &&
281+
git fetch --unshallow &&
282+
! test -f .git/shallow &&
283+
git fsck --full
284+
)
285+
'
286+
267287
test_expect_success 'clone shallow without --no-single-branch' '
268288
git clone --depth 1 "file://$(pwd)/." shallow2
269289
'

upload-pack.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,10 +670,17 @@ static void receive_needs(void)
670670
if (depth == 0 && shallows.nr == 0)
671671
return;
672672
if (depth > 0) {
673-
struct commit_list *result, *backup;
673+
struct commit_list *result = NULL, *backup = NULL;
674674
int i;
675-
backup = result = get_shallow_commits(&want_obj, depth,
676-
SHALLOW, NOT_SHALLOW);
675+
if (depth == INFINITE_DEPTH)
676+
for (i = 0; i < shallows.nr; i++) {
677+
struct object *object = shallows.objects[i].item;
678+
object->flags |= NOT_SHALLOW;
679+
}
680+
else
681+
backup = result =
682+
get_shallow_commits(&want_obj, depth,
683+
SHALLOW, NOT_SHALLOW);
677684
while (result) {
678685
struct object *object = &result->item->object;
679686
if (!(object->flags & (CLIENT_SHALLOW|NOT_SHALLOW))) {

0 commit comments

Comments
 (0)