{"thread":{"id":"17101","subject":"[RFC/PATCH 0/3] Enable in-process submodule traversal","startedAt":"2009-01-11T23:45:52Z","lastAt":"2009-01-12T10:59:32Z","messageCount":9,"participants":["Lars Hjemli","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"100037","messageId":"1231717555-10559-1-git-send-email-hjemli@gmail.com","threadId":"17101","inReplyTo":null,"subject":"[RFC/PATCH 0/3] Enable in-process submodule traversal","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-01-11T23:45:52Z","receivedAt":"2009-01-11T23:45:52Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"This patch series implements basic support for traversing the tree objects\nin submodules when the linked commit object is reachable. Normally such\nlinked commit objects will not be reachable in the containing repository,\nbut adding local copies of submodule repositories as alternate object\ndatabases for the containing repo solves this issue.\n\nThe first patch in the series does all the 'hard work' required for the\ntraversal to work, while the next two patches adds a '--submodules' flag\nto git-archive and git-ls-tree as proof of concept.\n\nLars Hjemli (3):\n  tree.c: add support for traversal of submodules\n  archive.c: enable traversal of submodules\n  builtin-ls-tree: enable traversal of submodules\n\n archive.c         |    2 ++\n builtin-ls-tree.c |   23 ++++++++---------------\n tree.c            |   20 +++++++++++++++++---\n tree.h            |    1 +\n 4 files changed, 28 insertions(+), 18 deletions(-)\n"},{"id":"100054","messageId":"1231717555-10559-2-git-send-email-hjemli@gmail.com","threadId":"17101","inReplyTo":"1231717555-10559-1-git-send-email-hjemli@gmail.com","subject":"[RFC/PATCH 1/3] tree.c: add support for traversal of submodules","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-01-11T23:45:53Z","receivedAt":"2009-01-11T23:45:53Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"If the commit referenced by a gitlink is available in the (possibly\nalternate) object database, read_tree_recursive() is now able to descend\ninto the tree of the linked commit if the flag 'traverse_gitlinks' is\nturned on.\n\nSigned-off-by: Lars Hjemli <hjemli@gmail.com>\n---\n tree.c |   20 +++++++++++++++++---\n tree.h |    1 +\n 2 files changed, 18 insertions(+), 3 deletions(-)\n\ndiff --git a/tree.c b/tree.c\nindex 03e782a..1468e10 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -7,6 +7,7 @@\n #include \"tree-walk.h\"\n \n const char *tree_type = \"tree\";\n+int traverse_gitlinks = 0;\n \n static int read_one_entry_opt(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, int opt)\n {\n@@ -114,16 +115,29 @@ int read_tree_recursive(struct tree *tree,\n \t\tdefault:\n \t\t\treturn -1;\n \t\t}\n-\t\tif (S_ISDIR(entry.mode)) {\n+\t\tif (S_ISDIR(entry.mode) || (traverse_gitlinks && S_ISGITLINK(entry.mode))) {\n \t\t\tint retval;\n \t\t\tchar *newbase;\n \t\t\tunsigned int pathlen = tree_entry_len(entry.path, entry.sha1);\n-\n+\t\t\tstruct commit *commit;\n+\t\t\tstruct tree *node;\n+\n+\t\t\tif (S_ISDIR(entry.mode)) {\n+\t\t\t\tnode = lookup_tree(entry.sha1);\n+\t\t\t} else {\n+\t\t\t\tcommit = lookup_commit_reference_gently(entry.sha1, 1);\n+\t\t\t\tif (!commit)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tif (parse_commit(commit))\n+\t\t\t\t\tdie(\"parse_commit(%s) failed\",\n+\t\t\t\t\t    sha1_to_hex(entry.sha1));\n+\t\t\t\tnode = commit->tree;\n+\t\t\t}\n \t\t\tnewbase = xmalloc(baselen + 1 + pathlen);\n \t\t\tmemcpy(newbase, base, baselen);\n \t\t\tmemcpy(newbase + baselen, entry.path, pathlen);\n \t\t\tnewbase[baselen + pathlen] = '/';\n-\t\t\tretval = read_tree_recursive(lookup_tree(entry.sha1),\n+\t\t\tretval = read_tree_recursive(node,\n \t\t\t\t\t\t     newbase,\n \t\t\t\t\t\t     baselen + pathlen + 1,\n \t\t\t\t\t\t     stage, match, fn, context);\ndiff --git a/tree.h b/tree.h\nindex 2ff01a4..b6b938f 100644\n--- a/tree.h\n+++ b/tree.h\n@@ -4,6 +4,7 @@\n #include \"object.h\"\n \n extern const char *tree_type;\n+extern int traverse_gitlinks;\n \n struct tree {\n \tstruct object object;\n-- \n1.6.1.81.g1df1.dirty\n"},{"id":"100039","messageId":"1231717555-10559-3-git-send-email-hjemli@gmail.com","threadId":"17101","inReplyTo":"1231717555-10559-2-git-send-email-hjemli@gmail.com","subject":"[RFC/PATCH 2/3] archive.c: enable traversal of submodules","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-01-11T23:45:54Z","receivedAt":"2009-01-11T23:45:54Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"The option --submodules can be used to activate traversal of sub-\nmodules when creating archives.\n\nSigned-off-by: Lars Hjemli <hjemli@gmail.com>\n---\n archive.c |    2 ++\n 1 files changed, 2 insertions(+), 0 deletions(-)\n\ndiff --git a/archive.c b/archive.c\nindex 9ac455d..973dde4 100644\n--- a/archive.c\n+++ b/archive.c\n@@ -262,6 +262,8 @@ static int parse_archive_args(int argc, const char **argv,\n \t\tOPT_STRING(0, \"format\", &format, \"fmt\", \"archive format\"),\n \t\tOPT_STRING(0, \"prefix\", &base, \"prefix\",\n \t\t\t\"prepend prefix to each pathname in the archive\"),\n+\t\tOPT_BOOLEAN(0, \"submodules\", &traverse_gitlinks,\n+\t\t\t\"include reacheable submodules\"),\n \t\tOPT__VERBOSE(&verbose),\n \t\tOPT__COMPR('0', &compression_level, \"store only\", 0),\n \t\tOPT__COMPR('1', &compression_level, \"compress faster\", 1),\n-- \n1.6.1.81.g1df1.dirty\n"},{"id":"100040","messageId":"1231717555-10559-4-git-send-email-hjemli@gmail.com","threadId":"17101","inReplyTo":"1231717555-10559-3-git-send-email-hjemli@gmail.com","subject":"[RFC/PATCH 3/3] builtin-ls-tree: enable traversal of submodules","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-01-11T23:45:55Z","receivedAt":"2009-01-11T23:45:55Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"The option '--submodules', which implies '-r', activates the traversal\nof all submodules for which the linked commit is reachable.\n\nSigned-off-by: Lars Hjemli <hjemli@gmail.com>\n---\n builtin-ls-tree.c |   23 ++++++++---------------\n 1 files changed, 8 insertions(+), 15 deletions(-)\n\ndiff --git a/builtin-ls-tree.c b/builtin-ls-tree.c\nindex cb61717..8a1db54 100644\n--- a/builtin-ls-tree.c\n+++ b/builtin-ls-tree.c\n@@ -23,7 +23,7 @@ static int chomp_prefix;\n static const char *ls_tree_prefix;\n \n static const char ls_tree_usage[] =\n-\t\"git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]\";\n+\t\"git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] [--submodules] <tree-ish> [path...]\";\n \n static int show_recursive(const char *base, int baselen, const char *pathname)\n {\n@@ -63,20 +63,8 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,\n \tunsigned long size;\n \n \tif (S_ISGITLINK(mode)) {\n-\t\t/*\n-\t\t * Maybe we want to have some recursive version here?\n-\t\t *\n-\t\t * Something similar to this incomplete example:\n-\t\t *\n-\t\tif (show_subprojects(base, baselen, pathname)) {\n-\t\t\tstruct child_process ls_tree;\n-\n-\t\t\tls_tree.dir = base;\n-\t\t\tls_tree.argv = ls-tree;\n-\t\t\tstart_command(&ls_tree);\n-\t\t}\n-\t\t *\n-\t\t */\n+\t\tif (show_recursive(base, baselen, pathname))\n+\t\t\tretval = READ_TREE_RECURSIVE;\n \t\ttype = commit_type;\n \t} else if (S_ISDIR(mode)) {\n \t\tif (show_recursive(base, baselen, pathname)) {\n@@ -168,6 +156,11 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)\n \t\t\t\tabbrev = DEFAULT_ABBREV;\n \t\t\t\tbreak;\n \t\t\t}\n+\t\t\tif (!strcmp(argv[1]+2, \"submodules\")) {\n+\t\t\t\tls_options |= LS_RECURSIVE;\n+\t\t\t\ttraverse_gitlinks = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n \t\t\t/* otherwise fallthru */\n \t\tdefault:\n \t\t\tusage(ls_tree_usage);\n-- \n1.6.1.81.g1df1.dirty\n"},{"id":"100057","messageId":"7v3afpmg41.fsf@gitster.siamese.dyndns.org","threadId":"17101","inReplyTo":"1231717555-10559-1-git-send-email-hjemli@gmail.com","subject":"Re: [RFC/PATCH 0/3] Enable in-process submodule traversal","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-12T02:07:42Z","receivedAt":"2009-01-12T02:07:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sounds interesting except 1/3 didn't seem to reach the list...\n"},{"id":"100063","messageId":"7vr639kyf0.fsf@gitster.siamese.dyndns.org","threadId":"17101","inReplyTo":"1231717555-10559-2-git-send-email-hjemli@gmail.com","subject":"Re: [RFC/PATCH 1/3] tree.c: add support for traversal of submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-12T03:15:15Z","receivedAt":"2009-01-12T03:15:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lars Hjemli <hjemli@gmail.com> writes:\n\n> If the commit referenced by a gitlink is available in the (possibly\n> alternate) object database, read_tree_recursive() is now able to descend\n> into the tree of the linked commit if the flag 'traverse_gitlinks' is\n> turned on.\n>\n> Signed-off-by: Lars Hjemli <hjemli@gmail.com>\n> ---\n>  tree.c |   20 +++++++++++++++++---\n>  tree.h |    1 +\n>  2 files changed, 18 insertions(+), 3 deletions(-)\n>\n> diff --git a/tree.c b/tree.c\n> index 03e782a..1468e10 100644\n> --- a/tree.c\n> +++ b/tree.c\n> @@ -7,6 +7,7 @@\n>  #include \"tree-walk.h\"\n>  \n>  const char *tree_type = \"tree\";\n> +int traverse_gitlinks = 0;\n\nI think we tend to put these global settings that will affect everybody in\nenvironment.c.  You do not have to initialize variable to zero; BSS will\ntake care of it.\n\nWhen the user explicitly asks you to traverse into submodules and the\nnecessary commit is not available in a submodule, the code goes on without\ncomplaining.  I am not saying it is bad, but I wonder if we would want to\ndistinguish these three cases:\n\n (1) the submodule is initialized and the necessary commit is there.\n\n (2) the submodule is initialized, but the necessary commit is missing.\n\n (3) the submodule is not even initialized (aka \"the user is not\n     interested in it\"); there is only an empty directory.\n\nI think it is perfectly fine not to say anything for (3) but I am unsure\nabout the second case.\n"},{"id":"100086","messageId":"8c5c35580901120104u418d8d73mad4ab7d71fe8c3f8@mail.gmail.com","threadId":"17101","inReplyTo":"7vr639kyf0.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCH 1/3] tree.c: add support for traversal of submodules","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-01-12T09:04:29Z","receivedAt":"2009-01-12T09:04:29Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On Mon, Jan 12, 2009 at 04:15, Junio C Hamano <gitster@pobox.com> wrote:\n> Lars Hjemli <hjemli@gmail.com> writes:\n>\n>> If the commit referenced by a gitlink is available in the (possibly\n>> alternate) object database, read_tree_recursive() is now able to descend\n>> into the tree of the linked commit if the flag 'traverse_gitlinks' is\n>> turned on.\n>>\n>> Signed-off-by: Lars Hjemli <hjemli@gmail.com>\n>> ---\n>>  tree.c |   20 +++++++++++++++++---\n>>  tree.h |    1 +\n>>  2 files changed, 18 insertions(+), 3 deletions(-)\n>>\n>> diff --git a/tree.c b/tree.c\n>> index 03e782a..1468e10 100644\n>> --- a/tree.c\n>> +++ b/tree.c\n>> @@ -7,6 +7,7 @@\n>>  #include \"tree-walk.h\"\n>>\n>>  const char *tree_type = \"tree\";\n>> +int traverse_gitlinks = 0;\n>\n> I think we tend to put these global settings that will affect everybody in\n> environment.c.  You do not have to initialize variable to zero; BSS will\n> take care of it.\n\nOk, I'll add a proper interface in environment.c for this setting.\n\n\n> When the user explicitly asks you to traverse into submodules and the\n> necessary commit is not available in a submodule, the code goes on without\n> complaining.  I am not saying it is bad, but I wonder if we would want to\n> distinguish these three cases:\n>\n>  (1) the submodule is initialized and the necessary commit is there.\n>\n>  (2) the submodule is initialized, but the necessary commit is missing.\n>\n>  (3) the submodule is not even initialized (aka \"the user is not\n>     interested in it\"); there is only an empty directory.\n>\n> I think it is perfectly fine not to say anything for (3) but I am unsure\n> about the second case.\n\nDo we want to impose the porcelainish rules of git-submodule\n(.gitmodules, .git/config) in read_tree_recursive()?\n\nIf so, I guess a new submodule.h might provide something like this\n(disclaimer: coded in gmail):\n\n\tstruct submodule {\n\t\tint interesting:1;\n\t\tchar *name;\n\t\tchar *url;\n\t\tchar **objectdirs;\n\t\tchar **paths;\n\t}\n\n\ttypedef int (*submodule_cb)(struct submodule *submodule, void *data);\n\n\tint load_submodule_config();\n\tstruct submodule *get_submodule_from_path(char *path);\n\tint add_submodule_objectdb(struct submodule *item);\n\tint for_each_submodule(submodule_cb cb, void *data);\n\n\n\nThen, in read_tree_recursive(), we could check submodule->interesting\nto decide if we should follow the gitlink. Also, for bare\nrepositories, we'd need to support something like\n'submodule.<name>.objectdir' in the config file (and .gitmodules must\nobviously be read from the objectdb).\n\nIf we don't want to impose these rules, the current patch should be\nminimally sufficient (the user has to edit\n.git/objects/info/alternates by hand and missing submodule commits are\ntreated as if the submodule is not interesting).\n\n-- \nlarsh\n"},{"id":"100101","messageId":"7vab9wj0rs.fsf@gitster.siamese.dyndns.org","threadId":"17101","inReplyTo":"8c5c35580901120104u418d8d73mad4ab7d71fe8c3f8@mail.gmail.com","subject":"Re: [RFC/PATCH 1/3] tree.c: add support for traversal of submodules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-12T10:07:19Z","receivedAt":"2009-01-12T10:07:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lars Hjemli <hjemli@gmail.com> writes:\n\n> On Mon, Jan 12, 2009 at 04:15, Junio C Hamano <gitster@pobox.com> wrote:\n> ...\n>> When the user explicitly asks you to traverse into submodules and the\n>> necessary commit is not available in a submodule, the code goes on without\n>> complaining.  I am not saying it is bad, but I wonder if we would want to\n>> distinguish these three cases:\n>>\n>>  (1) the submodule is initialized and the necessary commit is there.\n>>\n>>  (2) the submodule is initialized, but the necessary commit is missing.\n>>\n>>  (3) the submodule is not even initialized (aka \"the user is not\n>>     interested in it\"); there is only an empty directory.\n>>\n>> I think it is perfectly fine not to say anything for (3) but I am unsure\n>> about the second case.\n>\n> Do we want to impose the porcelainish rules of git-submodule\n> (.gitmodules, .git/config) in read_tree_recursive()?\n>\n> If so, I guess a new submodule.h might provide something like this\n> (disclaimer: coded in gmail):\n\nI do not see why you would need anything more than we already have to tell\n(3) from (1) and (2).  And I do not see why you need to have the Porcelain\npolicy in the picture for telling these three cases apart, either.\n\nFor example, there is this code in read-cache.c::ce_compare_gitlink():\n\n        static int ce_compare_gitlink(struct cache_entry *ce)\n        {\n                unsigned char sha1[20];\n\n                /*\n                 * We don't actually require that the .git directory\n                 * under GITLINK directory be a valid git directory. It\n                 * might even be missing (in case nobody populated that\n                 * sub-project).\n                 *\n                 * If so, we consider it always to match.\n                 */\n                if (resolve_gitlink_ref(ce->name, \"HEAD\", sha1) < 0)\n                        return 0;\n                return hashcmp(sha1, ce->sha1);\n        }\n\nIt asks resolve_gitlink_ref() to see if the directory (where the submodule\ncheckout _might_ be present if the user is interested in it) has .git/HEAD\nthat resolves.  If so, the user has a checkout and is interested in it.\nOtherwise, there is no checkout, in other words, we have case (3) above.\n\nWhether you force the user to link the submodule object store to the\nprimary one as alternates, or do that for the user temporarily inside the\nprocess [*1*], you would then be able to tell (1) and (2) apart by asking\nhas_sha1_file() if you can see the commit.\n\nOne thing that is unclear is to me is for whom the commit is missing (or\npresent).  I think the outline I gave above follows the design of your\npatch to assume that the commit may (or may not) be available to the\nsuperproject and traverse into the commit when that is the case.  It does\nnot mean the commit is available to the submodule itself (the commit may\nhave found in the primary project itself, not via the alternates), but\nsuch an arrangement makes it somewhat useless.\n\nWhat's the typical direction of using alternates in a setting with\nsuperproject with a submodule?  Do people have alternates in the submodule\nrepository that borrows from the superproject repository?  Or the other\nway around?  What's the rationale for having such alternates for normal\nuse case?  I am suspecting that there is no reason (other than this\n\"recursive tree traversal\") to have an alternates file in either\ndirection, but I also strongly suspect that I am missing some unwritten\nassumption you are making.\n\n[Footnote]\n\n*1* If you want to recurse seemlessly, it might make sense to add (during\nthe course of this \"recursive tree traversal\") the object store of the\nsubmodule repository to the process'es list of alternate object databases\nyourself, instead of forcing the user to do so permanently by mucking with\nthe alternates list of the primary project repository.  But that is an\nindependent issue.\n"},{"id":"100103","messageId":"8c5c35580901120259scee7c82k8917a2909bbb73de@mail.gmail.com","threadId":"17101","inReplyTo":"7vab9wj0rs.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCH 1/3] tree.c: add support for traversal of submodules","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-01-12T10:59:32Z","receivedAt":"2009-01-12T10:59:32Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On Mon, Jan 12, 2009 at 11:07, Junio C Hamano <gitster@pobox.com> wrote:\n> Lars Hjemli <hjemli@gmail.com> writes:\n>\n>> On Mon, Jan 12, 2009 at 04:15, Junio C Hamano <gitster@pobox.com> wrote:\n>> ...\n>>> When the user explicitly asks you to traverse into submodules and the\n>>> necessary commit is not available in a submodule, the code goes on without\n>>> complaining.  I am not saying it is bad, but I wonder if we would want to\n>>> distinguish these three cases:\n>>>\n>>>  (1) the submodule is initialized and the necessary commit is there.\n>>>\n>>>  (2) the submodule is initialized, but the necessary commit is missing.\n>>>\n>>>  (3) the submodule is not even initialized (aka \"the user is not\n>>>     interested in it\"); there is only an empty directory.\n>>>\n>>> I think it is perfectly fine not to say anything for (3) but I am unsure\n>>> about the second case.\n>>\n>> Do we want to impose the porcelainish rules of git-submodule\n>> (.gitmodules, .git/config) in read_tree_recursive()?\n>>\n>> If so, I guess a new submodule.h might provide something like this\n>> (disclaimer: coded in gmail):\n>\n> I do not see why you would need anything more than we already have to tell\n> (3) from (1) and (2).  And I do not see why you need to have the Porcelain\n> policy in the picture for telling these three cases apart, either.\n>\n> For example, there is this code in read-cache.c::ce_compare_gitlink():\n>\n>        static int ce_compare_gitlink(struct cache_entry *ce)\n>        {\n>                unsigned char sha1[20];\n>\n>                /*\n>                 * We don't actually require that the .git directory\n>                 * under GITLINK directory be a valid git directory. It\n>                 * might even be missing (in case nobody populated that\n>                 * sub-project).\n>                 *\n>                 * If so, we consider it always to match.\n>                 */\n>                if (resolve_gitlink_ref(ce->name, \"HEAD\", sha1) < 0)\n>                        return 0;\n>                return hashcmp(sha1, ce->sha1);\n>        }\n>\n> It asks resolve_gitlink_ref() to see if the directory (where the submodule\n> checkout _might_ be present if the user is interested in it) has .git/HEAD\n> that resolves.  If so, the user has a checkout and is interested in it.\n> Otherwise, there is no checkout, in other words, we have case (3) above.\n\nAh, yes, this makes sense. Thanks.\n\n\n> Whether you force the user to link the submodule object store to the\n> primary one as alternates, or do that for the user temporarily inside the\n> process [*1*],\n\nIf resolve_gitlink_ref() returns 0, I think we should automatically\ninsert the objectdir of the submodule as a tempory alternate.\n\n\n> you would then be able to tell (1) and (2) apart by asking\n> has_sha1_file() if you can see the commit.\n\nYes (I've also got a use-case for this with bare repositories [*1*],\nbut in that setting I guess it's ok to force the user to link the\nalternates manually).\n\n\n> One thing that is unclear is to me is for whom the commit is missing (or\n> present).  I think the outline I gave above follows the design of your\n> patch to assume that the commit may (or may not) be available to the\n> superproject and traverse into the commit when that is the case.  It does\n> not mean the commit is available to the submodule itself (the commit may\n> have found in the primary project itself, not via the alternates), but\n> such an arrangement makes it somewhat useless.\n\nI think we can ignore this issue; if someone has added the\nsuperproject as an alternate for the submodule and then done a\ncheckout of a superproject commit in the submodule followed by\ncommitting this gitlink in the superproject, we can only hope the user\nreally knew what he was doing...\n\n\n> What's the typical direction of using alternates in a setting with\n> superproject with a submodule?  Do people have alternates in the submodule\n> repository that borrows from the superproject repository?  Or the other\n> way around?  What's the rationale for having such alternates for normal\n> use case?  I am suspecting that there is no reason (other than this\n> \"recursive tree traversal\") to have an alternates file in either\n> direction,\n\nLikewise.\n\n\n> but I also strongly suspect that I am missing some unwritten\n> assumption you are making.\n\nI'm only assuming that we want to support traversal into the\nsubmodules from core git.\n\n\n*1* This will be (ab)used by cgit to support downloading of 'complete'\ntarballs, as outlined in\nhttp://thread.gmane.org/gmane.comp.version-control.git/102827.\n\n--\nlarsh\n"}]}