{"thread":{"id":"16643","subject":"[PATCH] submodule: Allow tracking of the newest revision of a branch in a submodule","startedAt":"2008-12-09T00:57:41Z","lastAt":"2008-12-09T09:23:46Z","messageCount":2,"participants":["Fabian Franz","Lars Hjemli"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"97393","messageId":"1228784261-18637-1-git-send-email-git@fabian-franz.de","threadId":"16643","inReplyTo":null,"subject":"[PATCH] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Fabian Franz","fromEmail":"git@fabian-franz.de","sentAt":"2008-12-09T00:57:41Z","receivedAt":"2008-12-09T00:57:41Z","isPatch":true,"sender":{"key":"git@fabian-franz.de","avatar":null},"body":"Submodules currently only allow tracking a specific revision\nand each update in a submodule leads to a new commit in the\nmaster repository. However some users may want to always track\nthe newest revision of a specific (named) tag or branch or HEAD.\nFor example the user might want to track a staging branch in all\nsubmodules.\n\nTo allow this the \"--track|-t <branch>\" parameter was added to\ngit-submodule.sh, which is added to .gitmodules config file as\nwell as \"track\" parameter. This creates a new local branch on\ncheckout, which is tracking the remote branch in case the local\nbranch does not yet exist.\n\nTechnically the gitlink code was changed to read .git/HEAD.gitlink\nif it exists instead of the normal HEAD. If you add 0000* as sha1\nsum to .git/HEAD.gitlink the submodule code will always fetch HEAD.\n\nThe submodule code is creating this HEAD.gitlink file with 0000* on\n\"init\" and \"add\".\n\nSigned-off-by: Fabian Franz <git@fabian-franz.de>\n---\n Documentation/git-submodule.txt |   10 +++++++++-\n git-submodule.sh                |   31 ++++++++++++++++++++++++++++++-\n refs.c                          |    6 ++++++\n 3 files changed, 45 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex babaa9b..9c29678 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -9,7 +9,7 @@ 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] [-t|--track <branch>] [--] <repository> <path>\n 'git submodule' [--quiet] status [--cached] [--] [<path>...]\n 'git submodule' [--quiet] init [--] [<path>...]\n 'git submodule' [--quiet] update [--init] [--] [<path>...]\n@@ -118,6 +118,10 @@ update::\n If the submodule is not yet initialized, and you just want to use the\n setting as stored in .gitmodules, you can automatically initialize the\n submodule with the --init option.\n++\n+If you used --track or set the \"track\" option in .gitmodules this will\n+automatically pull the newest updates from remote instead of tracking a\n+specific revision.\n \n summary::\n \tShow commit summary between the given commit (defaults to HEAD) and\n@@ -159,6 +163,10 @@ OPTIONS\n --branch::\n \tBranch of repository to add as submodule.\n \n+-t::\n+--track::\n+\tBranch/Tag/HEAD of repository to track in a submodule.\n+\n --cached::\n \tThis option is only valid for status and summary commands.  These\n \tcommands typically use the commit found in the submodule HEAD, but\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 2f47e06..9468d81 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -5,7 +5,7 @@\n # Copyright (c) 2007 Lars Hjemli\n \n USAGE=\"[--quiet] [--cached] \\\n-[add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \\\n+[add <repo> [-b branch] [--track|-t <branch>] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \\\n [--] [<path>...]|[foreach <command>]|[sync [--] [<path>...]]\"\n OPTIONS_SPEC=\n . git-sh-setup\n@@ -16,6 +16,7 @@ command=\n branch=\n quiet=\n cached=\n+track=\n \n #\n # print stuff on stdout unless -q was specified\n@@ -130,6 +131,11 @@ cmd_add()\n \t\t-q|--quiet)\n \t\t\tquiet=1\n \t\t\t;;\n+\t\t-t|--track)\n+\t\t\tcase \"$2\" in '') usage ;; esac\n+\t\t\ttrack=$2\n+\t\t\tshift\n+\t\t\t;;\n \t\t--)\n \t\t\tshift\n \t\t\tbreak\n@@ -197,12 +203,14 @@ cmd_add()\n \t\t(unset GIT_DIR; cd \"$path\" && git checkout -f -q ${branch:+-b \"$branch\" \"origin/$branch\"}) ||\n \t\tdie \"Unable to checkout submodule '$path'\"\n \tfi\n+\t[ -n \"$track\" ] && echo \"0000000000000000000000000000000000000000\" > $path/.git/HEAD.gitlink\n \n \tgit add \"$path\" ||\n \tdie \"Failed to add submodule '$path'\"\n \n \tgit config -f .gitmodules submodule.\"$path\".path \"$path\" &&\n \tgit config -f .gitmodules submodule.\"$path\".url \"$repo\" &&\n+\tgit config -f .gitmodules submodule.\"$path\".track \"$track\" &&\n \tgit add .gitmodules ||\n \tdie \"Failed to register submodule '$path'\"\n }\n@@ -327,10 +335,14 @@ cmd_update()\n \t\t\tsay \"Maybe you want to use 'update --init'?\"\n \t\t\tcontinue\n \t\tfi\n+\t\ttrack=$(git config -f .gitmodules submodule.\"$name\".track)\n \n \t\tif ! test -d \"$path\"/.git -o -f \"$path\"/.git\n \t\tthen\n \t\t\tmodule_clone \"$path\" \"$url\" || exit\n+\n+\t\t\t[ -n \"$track\" ] && echo \"0000000000000000000000000000000000000000\" > $path/.git/HEAD.gitlink\n+\n \t\t\tsubsha1=\n \t\telse\n \t\t\tsubsha1=$(unset GIT_DIR; cd \"$path\" &&\n@@ -345,11 +357,28 @@ cmd_update()\n \t\t\tthen\n \t\t\t\tforce=\"-f\"\n \t\t\tfi\n+\t\t\tpull=\n+\t\t\tif [ \"$sha1\" = \"0000000000000000000000000000000000000000\" ]\n+\t\t\tthen\n+\t\t\t\t[ -z \"$track\" ] && track=\"HEAD\"\n+\t\t\t\t# if the local branch does not yet exist, create it\n+\t\t\t\t( unset GIT_DIR; cd \"$path\"; git-show-ref --heads --tags -q \"$track\" || git branch --track \"$track\" \"origin/$track\" )\n+\t\t\t\tsha1=\"$track\"\n+\t\t\t\tpull=1\n+\t\t\tfi\n+\n \t\t\t(unset GIT_DIR; cd \"$path\" && git-fetch &&\n \t\t\t\tgit-checkout $force -q \"$sha1\") ||\n \t\t\tdie \"Unable to checkout '$sha1' in submodule path '$path'\"\n \n \t\t\tsay \"Submodule path '$path': checked out '$sha1'\"\n+\n+\t\t\tif [ \"$pull\" = \"1\" ]\n+\t\t\tthen\n+\t\t\t\t# Now pull new updates from origin\n+\t\t\t\t( unset GIT_DIR; cd \"$path\"; git-pull )\n+\t\t\tfi\n+\n \t\tfi\n \tdone\n }\ndiff --git a/refs.c b/refs.c\nindex 33ced65..8246023 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -385,6 +385,12 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re\n \t}\n \tgitdir[len] = '/';\n \tgitdir[++len] = '\\0';\n+\n+\t// Do not update submodule if HEAD.gitlink exists\n+\tretval = resolve_gitlink_ref_recursive(gitdir, len, \"HEAD.gitlink\", result, 0);\n+\tif (retval == 0)\n+\t\treturn retval;\n+\n \tretval = resolve_gitlink_ref_recursive(gitdir, len, refname, result, 0);\n \tfree(gitdir);\n \treturn retval;\n-- \n1.6.1.rc2.1.g363fe\n"},{"id":"97411","messageId":"8c5c35580812090123k2c6ed479odf8b625177a07005@mail.gmail.com","threadId":"16643","inReplyTo":"1228784261-18637-1-git-send-email-git@fabian-franz.de","subject":"Re: [PATCH] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2008-12-09T09:23:46Z","receivedAt":"2008-12-09T09:23:46Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On Tue, Dec 9, 2008 at 01:57, Fabian Franz <git@fabian-franz.de> wrote:\n> Technically the gitlink code was changed to read .git/HEAD.gitlink\n> if it exists instead of the normal HEAD. If you add 0000* as sha1\n> sum to .git/HEAD.gitlink the submodule code will always fetch HEAD.\n\nThis feels like the porcelain \"fooling\" the plumbing. How about\nsomething like this instead:\n\ndiff --git a/read-cache.c b/read-cache.c\nindex 8579663..cfacea7 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -137,6 +137,8 @@ static int ce_compare_gitlink(struct cache_entry *ce)\n         */\n        if (resolve_gitlink_ref(ce->name, \"HEAD\", sha1) < 0)\n                return 0;\n+       if (is_null_sha1(ce->sha1))\n+               return 0;\n        return hashcmp(sha1, ce->sha1);\n }\n\nThis should make the plumbing happy no matter which commit is actually\nchecked out in the submodule (not actually tested...). Then,\ncmd_update() can check if the requested sha1 is all '0' and\nfetch+checkout latest HEAD (or some branch) without playing games with\n.git/HEAD.gitlink. Finally, cmd_add() needs to update the index in the\ncontaining repository with the magic '0*' sha1 if '--track' is\nspecifed. This can be achieved by replacing 'git add $path' with 'echo\n$mode $sha1\\t$path | git update-index --index-info'.\n\nWhat do you think?\n\n> @@ -327,10 +335,14 @@ cmd_update()\n>                        say \"Maybe you want to use 'update --init'?\"\n>                        continue\n>                fi\n> +               track=$(git config -f .gitmodules submodule.\"$name\".track)\n\nI'm pretty certain that we don't want to use info from .gitmodules in\ncmd_update(). Instead, cmd_init() probably should move the info from\n.gitmodules into .git/config and cmd_update() should check the latter.\n\nBtw: cmd_status() probably also needs some modifications to handle\nthis special case.\n\n--\nlarsh\n"}]}