Skip to content

Commit

Permalink
git clone: Add --recursive to automatically checkout (nested) submodules
Browse files Browse the repository at this point in the history
Many projects using submodules expect all submodules to be checked out
in order to build/work correctly. A common command sequence for
developers on such projects is:

	git clone url/to/project
	cd project
	git submodule update --init (--recursive)

This patch introduces the --recursive option to git-clone. The new
option causes git-clone to recursively clone and checkout all
submodules of the cloned project. Hence, the above command sequence
can be reduced to:

	git clone --recursive url/to/project

--recursive is ignored if no checkout is done by the git-clone.

The patch also includes documentation and a selftest.

Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Johan Herland authored and Junio C Hamano committed Aug 20, 2009
1 parent e3ae4a8 commit e7fed18
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
10 changes: 9 additions & 1 deletion Documentation/git-clone.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ SYNOPSIS
'git clone' [--template=<template_directory>]
[-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
[-o <name>] [-u <upload-pack>] [--reference <repository>]
[--depth <depth>] [--] <repository> [<directory>]
[--depth <depth>] [--recursive] [--] <repository> [<directory>]

DESCRIPTION
-----------
Expand Down Expand Up @@ -139,6 +139,14 @@ then the cloned repository will become corrupt.
with a long history, and would want to send in fixes
as patches.

--recursive::
After the clone is created, initialize all submodules within,
using their default settings. This is equivalent to running
'git submodule update --init --recursive' immediately after
the clone is finished. This option is ignored if the cloned
repository does not have a worktree/checkout (i.e. if any of
`--no-checkout`/`-n`, `--bare`, or `--mirror` is given)

<repository>::
The (possibly remote) repository to clone from. See the
<<URLS,URLS>> section below for more information on specifying
Expand Down
11 changes: 10 additions & 1 deletion builtin-clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static const char * const builtin_clone_usage[] = {
};

static int option_quiet, option_no_checkout, option_bare, option_mirror;
static int option_local, option_no_hardlinks, option_shared;
static int option_local, option_no_hardlinks, option_shared, option_recursive;
static char *option_template, *option_reference, *option_depth;
static char *option_origin = NULL;
static char *option_upload_pack = "git-upload-pack";
Expand All @@ -59,6 +59,8 @@ static struct option builtin_clone_options[] = {
"don't use local hardlinks, always copy"),
OPT_BOOLEAN('s', "shared", &option_shared,
"setup as shared repository"),
OPT_BOOLEAN(0, "recursive", &option_recursive,
"setup as shared repository"),
OPT_STRING(0, "template", &option_template, "path",
"path the template repository"),
OPT_STRING(0, "reference", &option_reference, "repo",
Expand All @@ -73,6 +75,10 @@ static struct option builtin_clone_options[] = {
OPT_END()
};

static const char *argv_submodule[] = {
"submodule", "update", "--init", "--recursive", NULL
};

static char *get_repo_path(const char *repo, int *is_bundle)
{
static char *suffix[] = { "/.git", ".git", "" };
Expand Down Expand Up @@ -608,6 +614,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)

err |= run_hook(NULL, "post-checkout", sha1_to_hex(null_sha1),
sha1_to_hex(remote_head->old_sha1), "1", NULL);

if (!err && option_recursive)
err = run_command_v_opt(argv_submodule, RUN_GIT_CMD);
}

strbuf_release(&reflog_msg);
Expand Down
12 changes: 12 additions & 0 deletions t/t7407-submodule-foreach.sh
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,16 @@ test_expect_success 'test "status --recursive"' '
test_cmp expect actual
'

test_expect_success 'use "git clone --recursive" to checkout all submodules' '
git clone --recursive super clone4 &&
test -d clone4/.git &&
test -d clone4/sub1/.git &&
test -d clone4/sub2/.git &&
test -d clone4/sub3/.git &&
test -d clone4/nested1/.git &&
test -d clone4/nested1/nested2/.git &&
test -d clone4/nested1/nested2/nested3/.git &&
test -d clone4/nested1/nested2/nested3/submodule/.git
'

test_done

0 comments on commit e7fed18

Please sign in to comment.