{"thread":{"id":"11992","subject":"[PATCH 1/3] git-submodule - Follow top-level remote on init/update/clone","startedAt":"2008-02-09T16:57:23Z","lastAt":"2008-03-03T13:14:17Z","messageCount":8,"participants":["Mark Levedahl","Johannes Schindelin","Ping Yin"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"68097","messageId":"1202576245-284-1-git-send-email-mlevedahl@gmail.com","threadId":"11992","inReplyTo":null,"subject":"[PATCH 1/3] git-submodule - Follow top-level remote on init/update/clone","fromName":"Mark Levedahl","fromEmail":"mlevedahl@gmail.com","sentAt":"2008-02-09T16:57:23Z","receivedAt":"2008-02-09T16:57:23Z","isPatch":true,"sender":{"key":"mdl123@verizon.net","avatar":"https://avatars.githubusercontent.com/u/5302462?v=4"},"body":"This change allows the remote used for relative submodules (those defined\nusing a url that is relative to their parent) to be defined by explicit\ndefinition on the command line or through the top-level project's\nbranch.<name>.remote configuration.  This override is applied *only* to\nsubmodules defined using a url relative to the top-level project's url,\nunder the assumption that such modules are logically part of the same\nproject and managed as a unit.  For relative submodules, the given remote\nwill be defined in each submodule using the relative url applied to the\ntop-level's url the first time the remote is used.  Any existing remote\ndefinition is unaffected, so this can be changed manually by the user at\nany time.\n\nSubmodules defined using an absolute url are unaffected.\n\nSigned-off-by: Mark Levedahl <mlevedahl@gmail.com>\n---\n Documentation/git-submodule.txt |   16 +++++++-\n git-submodule.sh                |   76 ++++++++++++++++++++++++++++++++-------\n 2 files changed, 77 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex e818e6e..4fc17f6 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -9,9 +9,9 @@ git-submodule - Initialize, update or inspect submodules\n SYNOPSIS\n --------\n [verse]\n-'git-submodule' [--quiet] add [-b branch] [--] <repository> [<path>]\n+'git-submodule' [--quiet] add [-b branch] [-r <remote>] [--] <repository> [<path>]\n 'git-submodule' [--quiet] status [--cached] [--] [<path>...]\n-'git-submodule' [--quiet] [init|update] [--] [<path>...]\n+'git-submodule' [--quiet] [init|update] [-r <remote>] [--] [<path>...]\n \n \n COMMANDS\n@@ -55,6 +55,18 @@ OPTIONS\n -b, --branch::\n \tBranch of repository to add as submodule.\n \n+-r remote::\n+\tName of remote to use or define when working with relative submodules\n+\t(i.e., submodules whose url is given relative to the top-level\n+\tproject). If this value is undefined, the top-level project's\n+\tbranch.<name>.remote is used, and if that is undefined the default\n+\t\"origin\" is used. The remote will be defined in each relative\n+\tsubmodule as needed by appending the relative url to the top level\n+\tproject's url. This option has no effect upon submodules defined\n+\tusing an absolute url: such project's are cloned using the default\n+\t\"origin,\" and are updated using the submodule's branch.<name>.remote\n+\tmachinery and defaulting to \"origin.\"\n+\n --cached::\n \tDisplay the SHA-1 stored in the index, not the SHA-1 of the currently\n \tchecked out submodule commit. This option is only valid for the\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex a6aaf40..b97bf18 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -4,15 +4,17 @@\n #\n # Copyright (c) 2007 Lars Hjemli\n \n-USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]'\n+USAGE='[--quiet] [--cached] [add [-r remote] <repo> [-b branch]|status|init [-r remote]|update [-r remote]] [--] [<path>...]'\n OPTIONS_SPEC=\n . git-sh-setup\n+. git-parse-remote\n require_work_tree\n \n command=\n branch=\n quiet=\n cached=\n+remote=\n \n #\n # print stuff on stdout unless -q was specified\n@@ -40,11 +42,13 @@ get_repo_base() {\n # Resolve relative url by appending to parent's url\n resolve_relative_url ()\n {\n-\tbranch=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n-\tremote=\"$(git config branch.${branch#refs/heads/}.remote)\"\n-\tremote=\"${remote:-origin}\"\n-\tremoteurl=\"$(git config remote.$remote.url)\" ||\n-\t\tdie \"remote ($remote) does not have a url in .git/config\"\n+\tremote=\"${remote:-$(get_default_remote)}\"\n+\tremoteurl=$(git config remote.$remote.url)\n+\tif test -z \"$remoteurl\" ; then\n+\t\techo >&2 \"remote ($remote) does not have a url defined in .git/config\"\n+\t\treturn 1\n+\tfi\n+\tremoteurl=\"${remoteurl%/.git}\"\n \turl=\"$1\"\n \twhile test -n \"$url\"\n \tdo\n@@ -92,6 +96,7 @@ module_clone()\n {\n \tpath=$1\n \turl=$2\n+\tremote=$3\n \n \t# If there already is a directory at the submodule path,\n \t# expect it to be empty (since that is the default checkout\n@@ -107,7 +112,7 @@ module_clone()\n \ttest -e \"$path\" &&\n \tdie \"A file already exist at path '$path'\"\n \n-\tgit-clone -n \"$url\" \"$path\" ||\n+\tgit-clone -n -o \"$remote\" \"$url\" \"$path\" ||\n \tdie \"Clone of '$url' into submodule path '$path' failed\"\n }\n \n@@ -129,6 +134,14 @@ cmd_add()\n \t\t\tbranch=$2\n \t\t\tshift\n \t\t\t;;\n+\t\t-r)\n+\t\t\tcase \"$2\" in\n+\t\t\t'')\n+\t\t\t\tusage\n+\t\t\t\t;;\n+\t\t\tesac\n+\t\t\tremote=\"$2\"; shift\n+\t\t\t;;\n \t\t-q|--quiet)\n \t\t\tquiet=1\n \t\t\t;;\n@@ -156,13 +169,16 @@ cmd_add()\n \tcase \"$repo\" in\n \t./*|../*)\n \t\t# dereference source url relative to parent's url\n-\t\trealrepo=\"$(resolve_relative_url $repo)\" ;;\n+\t\trealremote=${remote:-$(get_default_remote)}\n+\t\trealrepo=$(resolve_relative_url $repo) || exit 1\n+\t\t;;\n \t*)\n \t\t# Turn the source into an absolute path if\n \t\t# it is local\n \t\tif base=$(get_repo_base \"$repo\"); then\n \t\t\trepo=\"$base\"\n \t\tfi\n+\t\trealremote=origin\n \t\trealrepo=$repo\n \t\t;;\n \tesac\n@@ -180,8 +196,8 @@ cmd_add()\n \tgit ls-files --error-unmatch \"$path\" > /dev/null 2>&1 &&\n \tdie \"'$path' already exists in the index\"\n \n-\tmodule_clone \"$path\" \"$realrepo\" || exit\n-\t(unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"origin/$branch\"}) ||\n+\tmodule_clone \"$path\" \"$realrepo\" \"$realremote\" || exit\n+\t(unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"$realremote/$branch\"}) ||\n \tdie \"Unable to checkout submodule '$path'\"\n \tgit add \"$path\" ||\n \tdie \"Failed to add submodule '$path'\"\n@@ -206,6 +222,14 @@ cmd_init()\n \t\t-q|--quiet)\n \t\t\tquiet=1\n \t\t\t;;\n+\t\t-r)\n+\t\t\tcase \"$2\" in\n+\t\t\t'')\n+\t\t\t\tusage\n+\t\t\t\t;;\n+\t\t\tesac\n+\t\t\tremote=\"$2\"; shift\n+\t\t\t;;\n \t\t--)\n \t\t\tshift\n \t\t\tbreak\n@@ -235,7 +259,7 @@ cmd_init()\n \t\t# Possibly a url relative to parent\n \t\tcase \"$url\" in\n \t\t./*|../*)\n-\t\t\turl=\"$(resolve_relative_url \"$url\")\"\n+\t\t\turl=$(resolve_relative_url \"$url\") || exit 1\n \t\t\t;;\n \t\tesac\n \n@@ -248,6 +272,8 @@ cmd_init()\n \n #\n # Update each submodule path to correct revision, using clone and checkout as needed\n+# For relative submodules (defined using relative url), we use master project's remote\n+# and define that in each submodule if not already there\n #\n # $@ = requested paths (default to all)\n #\n@@ -260,6 +286,14 @@ cmd_update()\n \t\t-q|--quiet)\n \t\t\tquiet=1\n \t\t\t;;\n+\t\t-r)\n+\t\t\tcase \"$2\" in\n+\t\t\t'')\n+\t\t\t\tusage\n+\t\t\t\t;;\n+\t\t\tesac\n+\t\t\tremote=\"$2\"; shift\n+\t\t\t;;\n \t\t--)\n \t\t\tshift\n \t\t\tbreak\n@@ -274,6 +308,7 @@ cmd_update()\n \t\tshift\n \tdone\n \n+\tremote=${remote:-$(get_default_remote)}\n \tgit ls-files --stage -- \"$@\" | grep -e '^160000 ' |\n \twhile read mode sha1 stage path\n \tdo\n@@ -290,7 +325,7 @@ cmd_update()\n \n \t\tif ! test -d \"$path\"/.git\n \t\tthen\n-\t\t\tmodule_clone \"$path\" \"$url\" || exit\n+\t\t\tmodule_clone \"$path\" \"$url\" \"$remote\" || exit\n \t\t\tsubsha1=\n \t\telse\n \t\t\tsubsha1=$(unset GIT_DIR; cd \"$path\" &&\n@@ -298,9 +333,24 @@ cmd_update()\n \t\t\tdie \"Unable to find current revision in submodule path '$path'\"\n \t\tfi\n \n+\t\tbaseurl=\"$(GIT_CONFIG=.gitmodules git config submodule.\"$name\".url)\"\n+\t\tcase \"$baseurl\" in\n+\t\t./*|../*)\n+\t\t\tfetch_remote=$remote\n+\t\t\tabsurl=$(resolve_relative_url $baseurl) || exit 1\n+\t\t\t(unset GIT_DIR ; cd \"$path\" && git config remote.\"$fetch_remote\".url > /dev/null) ||\n+\t\t\t(\n+\t\t\t\tunset GIT_DIR; cd \"$path\" && git remote add \"$fetch_remote\" \"$absurl\"\n+\t\t\t) || die \"Unable to define remote '$fetch_remote' in submodule path '$path'\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\tfetch_remote=\n+\t\t\t;;\n+\t\tesac\n+\n \t\tif test \"$subsha1\" != \"$sha1\"\n \t\tthen\n-\t\t\t(unset GIT_DIR; cd \"$path\" && git-fetch &&\n+\t\t\t(unset GIT_DIR; cd \"$path\" && git-fetch $fetch_remote &&\n \t\t\t\tgit-checkout -q \"$sha1\") ||\n \t\t\tdie \"Unable to checkout '$sha1' in submodule path '$path'\"\n \n-- \n1.5.4.47.gcca7b3\n"},{"id":"68099","messageId":"1202576245-284-2-git-send-email-mlevedahl@gmail.com","threadId":"11992","inReplyTo":"1202576245-284-1-git-send-email-mlevedahl@gmail.com","subject":"[PATCH 2/3] git-submodule - Allow adding a submodule in-place","fromName":"Mark Levedahl","fromEmail":"mlevedahl@gmail.com","sentAt":"2008-02-09T16:57:24Z","receivedAt":"2008-02-09T16:57:24Z","isPatch":true,"sender":{"key":"mdl123@verizon.net","avatar":"https://avatars.githubusercontent.com/u/5302462?v=4"},"body":"When working in top-level project, it is useful to create a new submodule\nas a git repo in a subdirectory, then add that submodule to top-level in\nplace.  This allows \"git submodule add <intended url> subdir\" to add the\nexisting subdir to the current project.  The presumption is the user will\nlater push / clone the subdir to the <intended url> so that future\nsubmodule init / updates will work.\n\nAbsent this patch, \"git submodule add\" insists upon cloning the subdir\nfrom a repository at the given url, which is fine for adding an existing\nproject in but less useful when adding a new submodule from scratch to an\nexisting project.  The former functionality remains, and the clone is\nattempted if the subdir does not already exist as a valid git repo.\n\nSigned-off-by: Mark Levedahl <mlevedahl@gmail.com>\n---\n Documentation/git-submodule.txt |    5 ++-\n git-submodule.sh                |   57 +++++++++++++++++++++++---------------\n 2 files changed, 37 insertions(+), 25 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 4fc17f6..85d7dd3 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -18,8 +18,9 @@ COMMANDS\n --------\n add::\n \tAdd the given repository as a submodule at the given path\n-\tto the changeset to be committed next.  In particular, the\n-\trepository is cloned at the specified path, added to the\n+\tto the changeset to be committed next.  If path is a valid\n+\trepository within the project, it is added as is. Otherwise,\n+\trepository is cloned at the specified path. path is added to the\n \tchangeset and registered in .gitmodules.   If no path is\n \tspecified, the path is deduced from the repository specification.\n \tIf the repository url begins with ./ or ../, it is stored as\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex b97bf18..4c86a3c 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -166,23 +166,6 @@ cmd_add()\n \t\tusage\n \tfi\n \n-\tcase \"$repo\" in\n-\t./*|../*)\n-\t\t# dereference source url relative to parent's url\n-\t\trealremote=${remote:-$(get_default_remote)}\n-\t\trealrepo=$(resolve_relative_url $repo) || exit 1\n-\t\t;;\n-\t*)\n-\t\t# Turn the source into an absolute path if\n-\t\t# it is local\n-\t\tif base=$(get_repo_base \"$repo\"); then\n-\t\t\trepo=\"$base\"\n-\t\tfi\n-\t\trealremote=origin\n-\t\trealrepo=$repo\n-\t\t;;\n-\tesac\n-\n \t# Guess path from repo if not specified or strip trailing slashes\n \tif test -z \"$path\"; then\n \t\tpath=$(echo \"$repo\" | sed -e 's|/*$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n@@ -190,15 +173,43 @@ cmd_add()\n \t\tpath=$(echo \"$path\" | sed -e 's|/*$||')\n \tfi\n \n-\ttest -e \"$path\" &&\n-\tdie \"'$path' already exists\"\n-\n \tgit ls-files --error-unmatch \"$path\" > /dev/null 2>&1 &&\n \tdie \"'$path' already exists in the index\"\n \n-\tmodule_clone \"$path\" \"$realrepo\" \"$realremote\" || exit\n-\t(unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"$realremote/$branch\"}) ||\n-\tdie \"Unable to checkout submodule '$path'\"\n+\t# perhaps the path exists and is already a git repo, else clone it\n+\tif test -e \"$path\"\n+\tthen\n+\t\tif test -d \"$path/.git\" &&\n+\t\ttest \"$(unset GIT_DIR; cd $path; git rev-parse --git-dir)\" = \".git\"\n+\t\tthen\n+\t\t\techo \"Adding existing repo at '$path' to the index\"\n+\t\telse\n+\t\t\tdie \"'$path' already exists and is not a valid git repo\"\n+\t\tfi\n+\telse\n+\t\tcase \"$repo\" in\n+\t\t./*|../*)\n+\t\t\t# dereference source url relative to parent's url\n+\t\t\trealremote=${remote:-$(get_default_remote)}\n+\t\t\trealrepo=$(resolve_relative_url $repo) || exit 1\n+\t\t\t;;\n+\t\t*)\n+\t\t\t# Turn the source into an absolute path if\n+\t\t\t# it is local\n+\t\t\tif base=$(get_repo_base \"$repo\")\n+\t\t\tthen\n+\t\t\t\trepo=\"$base\"\n+\t\t\tfi\n+\t\t\trealremote=origin\n+\t\t\trealrepo=$repo\n+\t\t\t;;\n+\t\tesac\n+\n+\t\tmodule_clone \"$path\" \"$realrepo\" \"$realremote\" || exit\n+\t\t(unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"$realremote/$branch\"}) ||\n+\t\tdie \"Unable to checkout submodule '$path'\"\n+\tfi\n+\n \tgit add \"$path\" ||\n \tdie \"Failed to add submodule '$path'\"\n \n-- \n1.5.4.47.gcca7b3\n"},{"id":"68098","messageId":"1202576245-284-3-git-send-email-mlevedahl@gmail.com","threadId":"11992","inReplyTo":"1202576245-284-2-git-send-email-mlevedahl@gmail.com","subject":"[PATCH 3/3] Add t/t7401 - test submodule interaction with remotes machinery","fromName":"Mark Levedahl","fromEmail":"mlevedahl@gmail.com","sentAt":"2008-02-09T16:57:25Z","receivedAt":"2008-02-09T16:57:25Z","isPatch":true,"sender":{"key":"mdl123@verizon.net","avatar":"https://avatars.githubusercontent.com/u/5302462?v=4"},"body":"This adds a sequence of tests to assure that the following two sequences\nwork:\n\n\tgit clone -o frotz <someurl> foo\n\tcd foo\n\tgit submodule init\n\tgit submodule update\n\nThis should result in the top-level project and subproject having \"frotz\"\nas the only defined remote, and should succeed with the\nbranch.<name>.remote mechanism supplying frotz as the remote.\n\nThen, in the same working directory\n\tgit remote add fork <some url>\n\tgit fetch fork\n\tgit checkout --track -b fork fork/<somebranch>\n\tgit submodule init\n\tgit submodule update\n\nwill retrive new submodules from remote \"fork\", and define fork in the\nexisting modules.\n\nSigned-off-by: Mark Levedahl <mlevedahl@gmail.com>\n---\n t/t7401-submodule-remote.sh |  118 +++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 118 insertions(+), 0 deletions(-)\n create mode 100755 t/t7401-submodule-remote.sh\n\ndiff --git a/t/t7401-submodule-remote.sh b/t/t7401-submodule-remote.sh\nnew file mode 100755\nindex 0000000..e5bef27\n--- /dev/null\n+++ b/t/t7401-submodule-remote.sh\n@@ -0,0 +1,118 @@\n+#!/bin/sh\n+\n+test_description='Porcelain support for submodules with multiple remotes\n+\n+This test verifies operation of submodules using multiple remotes and\n+differing remote per top-level branch.  This includes ability to follow\n+the top-level remote.<branch>, and to propagate definition of new remotes\n+down to submodules as needed.'\n+\n+. ./test-lib.sh\n+\n+# the standard tests all work with one repo, but we need several..\n+rm -rf .git\n+\n+test_expect_success 'Prepare master repository with 1 submodule' '\n+\t(\n+\tmkdir master &&\n+\tcd master &&\n+\tgit init &&\n+\techo \"on master\" > master.txt &&\n+\tgit add master.txt &&\n+\tgit commit -m \"Add master.txt\" &&\n+\tmkdir submod1 &&\n+\tcd submod1 &&\n+\tgit init &&\n+\techo \"submod1\" > submod1.txt &&\n+\tgit add submod1.txt &&\n+\tgit commit -m \"Added submod1.txt\" &&\n+\tcd .. &&\n+\tgit submodule add ./submod1 submod1 &&\n+\tgit commit -m \"Added submodule submod1\"\n+\t)\n+'\n+\n+test_expect_success 'Clone master as fork' '\n+\t(\n+\tgit clone master fork &&\n+\tcd fork &&\n+\ttest \"$(git remote)\" = \"origin\" &&\n+\tgit submodule init &&\n+\tgit submodule update &&\n+\ttest -e submod1/.git\n+\t)\n+'\n+\n+test_expect_success 'Add second submodule in fork' '\n+\t(\n+\tcd fork &&\n+\tmkdir submod2 &&\n+\tcd submod2 &&\n+\tgit init &&\n+\techo \"submod2\" > submod2.txt &&\n+\tgit add submod2.txt &&\n+\tgit commit -m \"Added submod2.txt\" &&\n+\tcd .. &&\n+\tgit submodule add ./submod2 submod2 &&\n+\tgit commit -m \"Added submodule submod2 on fork\"\n+\t)\n+'\n+\n+test_expect_success 'Clone master using frotz instead of origin' '\n+\t(\n+\tgit clone -o frotz master worker &&\n+\tcd worker &&\n+\ttest \"$(git remote)\" = \"frotz\"\n+\t)\n+'\n+\n+test_expect_success 'Get submodules using frotz instead of origin' '\n+\t(\n+\tcd worker &&\n+\tgit submodule init &&\n+\tgit submodule update &&\n+\ttest -e submod1/.git &&\n+\tcd submod1 &&\n+\ttest \"$(git remote)\" = \"frotz\"\n+\t)\n+'\n+\n+test_expect_success 'submodule update fails on detached head' '\n+\t(\n+\tcd worker &&\n+\tgit checkout $(git rev-parse HEAD) &&\n+\t! git submodule update\n+\t)\n+'\n+\n+test_expect_success 'submodule update -r remote succeeds on detached head' '\n+\t(\n+\tcd worker &&\n+\tgit checkout $(git rev-parse HEAD) &&\n+\tgit submodule update -r frotz\n+\t)\n+'\n+\n+test_expect_success 'Update using fork to get additional submodule' '\n+\t(\n+\tcd worker &&\n+\tgit remote add fork $(pwd)/../fork &&\n+\tgit fetch fork &&\n+\tgit checkout --track -b fork_master fork/master &&\n+\tgit submodule init &&\n+\tgit submodule update &&\n+\ttest -e submod2/.git &&\n+\tcd submod2 &&\n+\ttest \"$(git remote)\" = \"fork\" &&\n+\tcd ../submod1 &&\n+\tremotes1=$(git remote) &&\n+\tcase $remotes1 in\n+\t\tfork*frotz|frotz*fork)\n+\t\t\ttrue ;;\n+\t\t*)\n+\t\t\tfalse ;;\n+\tesac\n+\t)\n+'\n+\n+test_done\n-- \n1.5.4.47.gcca7b3\n"},{"id":"68451","messageId":"alpine.LSU.1.00.0802112152050.3870@racer.site","threadId":"11992","inReplyTo":"1202576245-284-1-git-send-email-mlevedahl@gmail.com","subject":"Re: [PATCH 1/3] git-submodule - Follow top-level remote on init/update/clone","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-11T22:09:20Z","receivedAt":"2008-02-11T22:09:20Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 9 Feb 2008, Mark Levedahl wrote:\n\n> This change allows the remote used for relative submodules (those defined\n> using a url that is relative to their parent) to be defined by explicit\n> definition on the command line or through the top-level project's\n> branch.<name>.remote configuration.  This override is applied *only* to\n> submodules defined using a url relative to the top-level project's url,\n> under the assumption that such modules are logically part of the same\n> project and managed as a unit.\n\nThat makes sense.\n\n> @@ -40,11 +42,13 @@ get_repo_base() {\n>  # Resolve relative url by appending to parent's url\n>  resolve_relative_url ()\n>  {\n> -\tbranch=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n> -\tremote=\"$(git config branch.${branch#refs/heads/}.remote)\"\n> -\tremote=\"${remote:-origin}\"\n> -\tremoteurl=\"$(git config remote.$remote.url)\" ||\n> -\t\tdie \"remote ($remote) does not have a url in .git/config\"\n\nI did not really look at this code before, but does that not mean that \ngit-submodule does already what you want?\n\nBecause usually, you clone the superproject from the URL that you actually \nwant to use, and in that case, the initial branch's default remote will \nhave exactly that URL.\n\nSo I have to admit that I do not see the reason why you remove that code, \nreplace it with another (that I think does the same), and claim that you \nintroduce that behaviour.\n\nYour patch seems to change only one thing: you can specify \"-r <remote>\" \nwith \"git submodule add/init/update\" -- except for some peculiarity; see \nbelow.\n\n> @@ -107,7 +112,7 @@ module_clone()\n>  \ttest -e \"$path\" &&\n>  \tdie \"A file already exist at path '$path'\"\n>  \n> -\tgit-clone -n \"$url\" \"$path\" ||\n> +\tgit-clone -n -o \"$remote\" \"$url\" \"$path\" ||\n>  \tdie \"Clone of '$url' into submodule path '$path' failed\"\n>  }\n>  \n\nIf you do _that_, you will _force_ the submodule to have no \"origin\" \nremote.  As discussed _at length_, this is not what you should do.  The \nonly reason to use \"-o <other-nick-name>\" is if you plan _not_ to use the \nsame URL for the default remote.\n\nIOW I do not like this hunk _at_ _all_.  Because I get the impression that \nI really wasted my time explaining the same issue over and over and over \nagain.\n\n> @@ -156,13 +169,16 @@ cmd_add()\n>  \tcase \"$repo\" in\n>  \t./*|../*)\n>  \t\t# dereference source url relative to parent's url\n> -\t\trealrepo=\"$(resolve_relative_url $repo)\" ;;\n> +\t\trealremote=${remote:-$(get_default_remote)}\n> +\t\trealrepo=$(resolve_relative_url $repo) || exit 1\n> +\t\t;;\n\nWhy do you need the \"realremote\" here?  Why is \"$remote\" not enough?\n\n> @@ -235,7 +259,7 @@ cmd_init()\n>  \t\t# Possibly a url relative to parent\n>  \t\tcase \"$url\" in\n>  \t\t./*|../*)\n> -\t\t\turl=\"$(resolve_relative_url \"$url\")\"\n> +\t\t\turl=$(resolve_relative_url \"$url\") || exit 1\n\nYes for the \"|| exit 1\".  No for the removal of the quotes: keep in mind: \nyou are possibly getting a url from the _config_, which is supposed to be \nuser-editable.\n\n> @@ -274,6 +308,7 @@ cmd_update()\n>  \t\tshift\n>  \tdone\n>  \n> +\tremote=${remote:-$(get_default_remote)}\n\nYou have this paradigm so often, but AFAICS you only use it for the call \nto module_clone.  Why not let module_clone figure it out, if $remote is \nempty?\n\n> @@ -298,9 +333,24 @@ cmd_update()\n>  \t\t\tdie \"Unable to find current revision in submodule path '$path'\"\n\n>  \t\tfi\n>  \n> +\t\tbaseurl=\"$(GIT_CONFIG=.gitmodules git config submodule.\"$name\".url)\"\n> +\t\tcase \"$baseurl\" in\n> +\t\t./*|../*)\n> +\t\t\tfetch_remote=$remote\n> +\t\t\tabsurl=$(resolve_relative_url $baseurl) || exit 1\n> +\t\t\t(unset GIT_DIR ; cd \"$path\" && git config remote.\"$fetch_remote\".url > /dev/null) ||\n> +\t\t\t(\n> +\t\t\t\tunset GIT_DIR; cd \"$path\" && git remote add \"$fetch_remote\" \"$absurl\"\n> +\t\t\t) || die \"Unable to define remote '$fetch_remote' in submodule path '$path'\"\n> +\t\t\t;;\n> +\t\t*)\n> +\t\t\tfetch_remote=\n> +\t\t\t;;\n> +\t\tesac\n> +\n>  \t\tif test \"$subsha1\" != \"$sha1\"\n>  \t\tthen\n> -\t\t\t(unset GIT_DIR; cd \"$path\" && git-fetch &&\n> +\t\t\t(unset GIT_DIR; cd \"$path\" && git-fetch $fetch_remote &&\n\nWasn't the whole _point_ of having a two-stage init/update that you could \n_change_ the remote in the config?\n\nNow you override those settings if .gitmodules says that the path is \nrelative?  Shouldn't you respect the setting in the config (which the user \ncan change freely), rather than .gitmodules (which the user cannot change \nwithout either committing it or having a permanently dirty working \ndirectory)?\n\nCiao,\nDscho\n"},{"id":"68472","messageId":"47B0EFA2.9070903@gmail.com","threadId":"11992","inReplyTo":"alpine.LSU.1.00.0802112152050.3870@racer.site","subject":"Re: [PATCH 1/3] git-submodule - Follow top-level remote on init/update/clone","fromName":"Mark Levedahl","fromEmail":"mlevedahl@gmail.com","sentAt":"2008-02-12T01:00:18Z","receivedAt":"2008-02-12T01:00:18Z","isPatch":true,"sender":{"key":"mdl123@verizon.net","avatar":"https://avatars.githubusercontent.com/u/5302462?v=4"},"body":"Johannes Schindelin wrote:\n>> @@ -40,11 +42,13 @@ get_repo_base() {\n>>  # Resolve relative url by appending to parent's url\n>>  resolve_relative_url ()\n>>  {\n>> -\tbranch=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n>> -\tremote=\"$(git config branch.${branch#refs/heads/}.remote)\"\n>> -\tremote=\"${remote:-origin}\"\n>> -\tremoteurl=\"$(git config remote.$remote.url)\" ||\n>> -\t\tdie \"remote ($remote) does not have a url in .git/config\"\n>>     \n>\n> I did not really look at this code before, but does that not mean that \n> git-submodule does already what you want?\n>\n> Because usually, you clone the superproject from the URL that you actually \n> want to use, and in that case, the initial branch's default remote will \n> have exactly that URL.\n>\n> So I have to admit that I do not see the reason why you remove that code, \n> replace it with another (that I think does the same), and claim that you \n> introduce that behaviour.\n>\n>   \nThere were three changes:\n1) Eliminate die() in a subshell - it doesn't work. Instead, must have a \nreturn code and pass that up to top-level shell before exit can be done.\n2) Eliminated duplication of get_default_remote(), instead using the \ndefinition in git-parse-remote.\nSuggestions? (Separate patches, don't do 2)?\n3) Use the user specified $remote if given.\n\n>> @@ -107,7 +112,7 @@ module_clone()\n>>  \ttest -e \"$path\" &&\n>>  \tdie \"A file already exist at path '$path'\"\n>>  \n>> -\tgit-clone -n \"$url\" \"$path\" ||\n>> +\tgit-clone -n -o \"$remote\" \"$url\" \"$path\" ||\n>>  \tdie \"Clone of '$url' into submodule path '$path' failed\"\n>>  }\n>>  \n>>     \n>\n> If you do _that_, you will _force_ the submodule to have no \"origin\" \n> remote.  As discussed _at length_, this is not what you should do.  The \n> only reason to use \"-o <other-nick-name>\" is if you plan _not_ to use the \n> same URL for the default remote.\n>   \nThis *must* define the remote using the same name as flowed down from \ntop-level, whatever that name is. Otherwise, subsequent fetch / update \nfollowing top-level just won't work. Consider if top-level \nbranch.<name>.remote = frotz and we define not frotz but origin in the \nsubmodule. Later, on different branch, top-level branch.<name>.remote  = \norigin. The submodule has origin defined but it points to a server \ndifferent than top-level's origin. Now what?\n\nThe same holds true if user gave -r frotz: ignoring that and defining \norigin instead is an outright bug.\n\n>\n> Why do you need the \"realremote\" here?  Why is \"$remote\" not enough?\n>   \nGood catch - there was a reason in an earlier version of this, no longer \nrelevant.\n>   \n>> @@ -235,7 +259,7 @@ cmd_init()\n>>  \t\t# Possibly a url relative to parent\n>>  \t\tcase \"$url\" in\n>>  \t\t./*|../*)\n>> -\t\t\turl=\"$(resolve_relative_url \"$url\")\"\n>> +\t\t\turl=$(resolve_relative_url \"$url\") || exit 1\n>>     \n>\n> Yes for the \"|| exit 1\".  No for the removal of the quotes: keep in mind: \n> you are possibly getting a url from the _config_, which is supposed to be \n> user-editable.\n>   \nWorks fine as is (You need the quotes when using the variable, not when \ndefining it):\n\ngit>git config foo.name \"some string\n > with cr\"\ngit>z=$(git config foo.name)\ngit>echo \"$z\"\nsome string\nwith cr\n\nAs written, the old code had the perverse effect of *not* quoting $url, \nand that was the part that needed to be quoted.\n\n>> @@ -274,6 +308,7 @@ cmd_update()\n>>  \t\tshift\n>>  \tdone\n>>  \n>> +\tremote=${remote:-$(get_default_remote)}\n>>     \n>\n> You have this paradigm so often, but AFAICS you only use it for the call \n> to module_clone.  Why not let module_clone figure it out, if $remote is \n> empty?\n>\n>   \nWill do.\n>> @@ -298,9 +333,24 @@ cmd_update()\n>>  \t\t\tdie \"Unable to find current revision in submodule path '$path'\"\n>>     \n> Wasn't the whole _point_ of having a two-stage init/update that you could \n> _change_ the remote in the config?\n>\n> Now you override those settings if .gitmodules says that the path is \n> relative?  Shouldn't you respect the setting in the config (which the user \n> can change freely), rather than .gitmodules (which the user cannot change \n> without either committing it or having a permanently dirty working \n> directory)?\n>   \nOk, I was trying to avoid defining another config variable. The \n\"relativeness\" of a submodule is not knowable from  submodule.<path>.url \nas that is always absolute (if relative in .gitmodules, it is resolved \ninto an absolute url during git init). I see two choices:\n    1) define variable  submodule.<path>.isrelative during init, and use \nthat instead. The user would have to modify that and the url to override.\n    2) always resolve the relative url from .gitmodules, compare with \nsubmodule.<path>.url and decide it was relative if those two agree. More \noverhead, enough complexity that I fear for strange failure modes later on.\n\nAny preferences or other suggestions?\n\nMark\n"},{"id":"68473","messageId":"alpine.LSU.1.00.0802120109270.3870@racer.site","threadId":"11992","inReplyTo":"47B0EFA2.9070903@gmail.com","subject":"Re: [PATCH 1/3] git-submodule - Follow top-level remote on init/update/clone","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-12T01:10:08Z","receivedAt":"2008-02-12T01:10:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 11 Feb 2008, Mark Levedahl wrote:\n\n> Johannes Schindelin wrote:\n> \n> > > @@ -107,7 +112,7 @@ module_clone()\n> > >  \ttest -e \"$path\" &&\n> > >  \tdie \"A file already exist at path '$path'\"\n> > >  -\tgit-clone -n \"$url\" \"$path\" ||\n> > > +\tgit-clone -n -o \"$remote\" \"$url\" \"$path\" ||\n> > >  \tdie \"Clone of '$url' into submodule path '$path' failed\"\n> > >  }\n> > >      \n> > \n> > If you do _that_, you will _force_ the submodule to have no \"origin\" \n> > remote.  As discussed _at length_, this is not what you should do.  \n> > The only reason to use \"-o <other-nick-name>\" is if you plan _not_ to \n> > use the same URL for the default remote.\n>\n> This *must* define the remote using the same name as flowed down from \n> top-level, whatever that name is.\n\nAt this point, I give up my review in despair,\nDscho\n"},{"id":"68475","messageId":"47B0F78C.1050605@gmail.com","threadId":"11992","inReplyTo":"alpine.LSU.1.00.0802120109270.3870@racer.site","subject":"Re: [PATCH 1/3] git-submodule - Follow top-level remote on init/update/clone","fromName":"Mark Levedahl","fromEmail":"mlevedahl@gmail.com","sentAt":"2008-02-12T01:34:04Z","receivedAt":"2008-02-12T01:34:04Z","isPatch":true,"sender":{"key":"mdl123@verizon.net","avatar":"https://avatars.githubusercontent.com/u/5302462?v=4"},"body":"Johannes Schindelin wrote:\n> Hi,\n>\n> On Mon, 11 Feb 2008, Mark Levedahl wrote:\n>\n>   \n>> Johannes Schindelin wrote:\n>>\n>>     \n>>>> @@ -107,7 +112,7 @@ module_clone()\n>>>>  \ttest -e \"$path\" &&\n>>>>  \tdie \"A file already exist at path '$path'\"\n>>>>  -\tgit-clone -n \"$url\" \"$path\" ||\n>>>> +\tgit-clone -n -o \"$remote\" \"$url\" \"$path\" ||\n>>>>  \tdie \"Clone of '$url' into submodule path '$path' failed\"\n>>>>  }\n>>>>      \n>>>>         \n>>> If you do _that_, you will _force_ the submodule to have no \"origin\" \n>>> remote.  As discussed _at length_, this is not what you should do.  \n>>> The only reason to use \"-o <other-nick-name>\" is if you plan _not_ to \n>>> use the same URL for the default remote.\n>>>       \n>> This *must* define the remote using the same name as flowed down from \n>> top-level, whatever that name is.\n>>     \n>\n> At this point, I give up my review in despair,\n> Dscho\n>\n>   \nThe submodules must use the same remote name to refer to the same \nserver/repo-tree as top-level, or the coordinated fetch / update driven \nby top-level's branch.<name>.remote cannot work. It is always origin, or \nalways frotz, not mix and match. There are two ways to achieve this:\n\n1) Use the name given by top-level, as I did.\n2) Restrict git to only allow one remote name, *origin*, ever (or at \nleast if submodules are used). Not just the default remote, *any* \nremote. This removes branch.<name>.remote as that is defined to be origin.\n\nI infer you choose option 2? It is certainly simpler, though \nsignificantly more restrictive.\n\nMark\n"},{"id":"70781","messageId":"46dff0320803030514y3b7b1860h18094f99619ff671@mail.gmail.com","threadId":"11992","inReplyTo":"1202576245-284-2-git-send-email-mlevedahl@gmail.com","subject":"Re: [PATCH 2/3] git-submodule - Allow adding a submodule in-place","fromName":"Ping Yin","fromEmail":"pkufranky@gmail.com","sentAt":"2008-03-03T13:14:17Z","receivedAt":"2008-03-03T13:14:17Z","isPatch":true,"sender":{"key":"pkufranky@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5346?v=4"},"body":"On Sun, Feb 10, 2008 at 12:57 AM, Mark Levedahl <mlevedahl@gmail.com> wrote:\n> When working in top-level project, it is useful to create a new submodule\n>  as a git repo in a subdirectory, then add that submodule to top-level in\n>  place.  This allows \"git submodule add <intended url> subdir\" to add the\n>  existing subdir to the current project.  The presumption is the user will\n>  later push / clone the subdir to the <intended url> so that future\n>  submodule init / updates will work.\n>\n>  Absent this patch, \"git submodule add\" insists upon cloning the subdir\n>  from a repository at the given url, which is fine for adding an existing\n>  project in but less useful when adding a new submodule from scratch to an\n>  existing project.  The former functionality remains, and the clone is\n>  attempted if the subdir does not already exist as a valid git repo.\n>\n>  Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>\n>  ---\n>   Documentation/git-submodule.txt |    5 ++-\n>   git-submodule.sh                |   57 +++++++++++++++++++++++---------------\n>   2 files changed, 37 insertions(+), 25 deletions(-)\n>\n>  diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\n>  index 4fc17f6..85d7dd3 100644\n>  --- a/Documentation/git-submodule.txt\n>  +++ b/Documentation/git-submodule.txt\n>  @@ -18,8 +18,9 @@ COMMANDS\n>   --------\n>   add::\n>         Add the given repository as a submodule at the given path\n>  -       to the changeset to be committed next.  In particular, the\n>  -       repository is cloned at the specified path, added to the\n>  +       to the changeset to be committed next.  If path is a valid\n>  +       repository within the project, it is added as is. Otherwise,\n>  +       repository is cloned at the specified path. path is added to the\n>         changeset and registered in .gitmodules.   If no path is\n>         specified, the path is deduced from the repository specification.\n>         If the repository url begins with ./ or ../, it is stored as\n>  diff --git a/git-submodule.sh b/git-submodule.sh\n>  index b97bf18..4c86a3c 100755\n>  --- a/git-submodule.sh\n>  +++ b/git-submodule.sh\n>  @@ -166,23 +166,6 @@ cmd_add()\n>                 usage\n>         fi\n>\n>  -       case \"$repo\" in\n>  -       ./*|../*)\n>  -               # dereference source url relative to parent's url\n>  -               realremote=${remote:-$(get_default_remote)}\n>  -               realrepo=$(resolve_relative_url $repo) || exit 1\n>  -               ;;\n>  -       *)\n>  -               # Turn the source into an absolute path if\n>  -               # it is local\n>  -               if base=$(get_repo_base \"$repo\"); then\n>  -                       repo=\"$base\"\n>  -               fi\n>  -               realremote=origin\n>  -               realrepo=$repo\n>  -               ;;\n>  -       esac\n>  -\n>         # Guess path from repo if not specified or strip trailing slashes\n>         if test -z \"$path\"; then\n>                 path=$(echo \"$repo\" | sed -e 's|/*$||' -e 's|:*/*\\.git$||' -e 's|.*[/:]||g')\n>  @@ -190,15 +173,43 @@ cmd_add()\n>                 path=$(echo \"$path\" | sed -e 's|/*$||')\n>         fi\n>\n>  -       test -e \"$path\" &&\n>  -       die \"'$path' already exists\"\n>  -\n>         git ls-files --error-unmatch \"$path\" > /dev/null 2>&1 &&\n>         die \"'$path' already exists in the index\"\n>\n>  -       module_clone \"$path\" \"$realrepo\" \"$realremote\" || exit\n>  -       (unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"$realremote/$branch\"}) ||\n>  -       die \"Unable to checkout submodule '$path'\"\n>  +       # perhaps the path exists and is already a git repo, else clone it\n>  +       if test -e \"$path\"\n>  +       then\n>  +               if test -d \"$path/.git\" &&\n>  +               test \"$(unset GIT_DIR; cd $path; git rev-parse --git-dir)\" = \".git\"\n>  +               then\n>  +                       echo \"Adding existing repo at '$path' to the index\"\n>  +               else\n>  +                       die \"'$path' already exists and is not a valid git repo\"\n>  +               fi\n>  +       else\n>  +               case \"$repo\" in\n>  +               ./*|../*)\n>  +                       # dereference source url relative to parent's url\n>  +                       realremote=${remote:-$(get_default_remote)}\n>  +                       realrepo=$(resolve_relative_url $repo) || exit 1\n>  +                       ;;\n>  +               *)\n>  +                       # Turn the source into an absolute path if\n>  +                       # it is local\n>  +                       if base=$(get_repo_base \"$repo\")\n>  +                       then\n>  +                               repo=\"$base\"\n>  +                       fi\n>  +                       realremote=origin\n>  +                       realrepo=$repo\n>  +                       ;;\n>  +               esac\n>  +\n>  +               module_clone \"$path\" \"$realrepo\" \"$realremote\" || exit\n>  +               (unset GIT_DIR; cd \"$path\" && git checkout -q ${branch:+-b \"$branch\" \"$realremote/$branch\"}) ||\n>  +               die \"Unable to checkout submodule '$path'\"\n>  +       fi\n>  +\n>         git add \"$path\" ||\n>         die \"Failed to add submodule '$path'\"\n>\n>  --\n\nI think it's a very useful patch. But why has it sleeped for over one month?\n\n\n\n-- \nPing Yin\n"}]}