{"thread":{"id":"16684","subject":"[PATCH v3] submodule: Allow tracking of the newest revision of a branch in a submodule","startedAt":"2008-12-11T15:39:42Z","lastAt":"2008-12-12T01:17:57Z","messageCount":6,"participants":["Fabian Franz","Junio C Hamano","Lars Hjemli"],"isPatch":true,"patchVersion":3,"patchTotal":null},"messages":[{"id":"97599","messageId":"1229009982-2701-1-git-send-email-git@fabian-franz.de","threadId":"16684","inReplyTo":null,"subject":"[PATCH v3] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Fabian Franz","fromEmail":"git@fabian-franz.de","sentAt":"2008-12-11T15:39:42Z","receivedAt":"2008-12-11T15:39:42Z","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 always compare\nsuccessful (so no changes) in case the sha1 is null. In that\ncase no new commit is created when there are changes in the\nsubmodule.\n\nThe submodule code is adding the file with 0000* on\n\"add\".\n\nSigned-off-by: Fabian Franz <git@fabian-franz.de>\n---\n>\n>Fabian Franz schrieb:\n>> Submodules currently only allow tracking a specific revision\n>> and each update in a submodule leads to a new commit in the\n>> master repository. However some users may want to always track\n>> the newest revision of a specific (named) tag or branch or HEAD.\n>> For example the user might want to track a staging branch in all\n>> submodules.\n>\n>Personally, I don't particularly like this feature (but then, nobody\n>forces me to use it ;) In which situation do you need this?\n\nI have a development workflow in my company where we are independently\nworking on many components. And for some things I just always want to \nhave the newest revision without having to commit twice always.\n\n>\n>By tieing a project commit to a particular submodule commit the committer\n>gives the guarantee: \"I've tested this with this module version, and it\n>works; all is ok.\" With this new feature, this guarantee vanishes, because\n>the committer has no control over which version of the module will\n>ultimately be used; it could be newer or it could be older.\n\nI like this and because of that the --branch is optional. I also like that so much, that we have decided against Google Repo.\n\nHowever I have both cases: Stable development, where I need one special version and \"wild\" development, where I always want the newest published one.\n>\n>I've reviewed the patch just from a shell code writer's point of view.\n\nOkay, I added your suggestions.\n\nThanks for your feedback.\n\nBest Wishes,\n\nFabian\n\n Documentation/git-submodule.txt |   10 +++++++++-\n git-submodule.sh                |   35 +++++++++++++++++++++++++++++++++--\n read-cache.c                    |    5 +++++\n 3 files changed, 47 insertions(+), 3 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..16df528 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+\ttest -n \"$track\" && printf '160000 0000000000000000000000000000000000000000\\t%s\\n' \"$path\" | git update-index --index-info\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@@ -277,6 +285,10 @@ cmd_init()\n \t\tgit config submodule.\"$name\".url \"$url\" ||\n \t\tdie \"Failed to register url for submodule path '$path'\"\n \n+\t\ttrack=$(git config -f .gitmodules submodule.\"$name\".track)\n+\t\tgit config submodule.\"$name\".track \"$track\" ||\n+\t\tdie \"Failed to register track for submodule path '$path'\"\n+\n \t\tsay \"Submodule '$name' ($url) registered for path '$path'\"\n \tdone\n }\n@@ -345,11 +357,29 @@ 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\ttrack=$(git config submodule.\"$name\".track)\n+\t\t\t\t: ${track:=\"master\"}\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 ) || die \"Unable to pull in submodule path '$path'\"\n+\t\t\tfi\n+\n \t\tfi\n \tdone\n }\n@@ -596,7 +626,8 @@ cmd_status()\n \t\tset_name_rev \"$path\" \"$sha1\"\n \t\tif git diff-files --quiet -- \"$path\"\n \t\tthen\n-\t\t\tsay \" $sha1 $path$revname\"\n+\t\t\ttrack=$(git config submodule.\"$name\".track)\n+\t\t\tsay \" $sha1 $path$revname${track:+ (tracking \"$track\")}\"\n \t\telse\n \t\t\tif test -z \"$cached\"\n \t\t\tthen\ndiff --git a/read-cache.c b/read-cache.c\nindex 8579663..0c14b68 100644\n--- a/read-cache.c\n+++ b/read-cache.c\n@@ -137,6 +137,11 @@ static int ce_compare_gitlink(struct cache_entry *ce)\n \t */\n \tif (resolve_gitlink_ref(ce->name, \"HEAD\", sha1) < 0)\n \t\treturn 0;\n+\n+\t// To be able to track newest revision\n+\tif (is_null_sha1(ce->sha1))\n+\t\treturn 0;\n+\n \treturn hashcmp(sha1, ce->sha1);\n }\n \n-- \n1.5.3.6\n"},{"id":"97623","messageId":"7vbpvicuk2.fsf@gitster.siamese.dyndns.org","threadId":"16684","inReplyTo":"1229009982-2701-1-git-send-email-git@fabian-franz.de","subject":"Re: [PATCH v3] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-11T20:42:53Z","receivedAt":"2008-12-11T20:42:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Fabian Franz <git@fabian-franz.de> writes:\n\n> Submodules currently only allow tracking a specific revision\n> and each update in a submodule leads to a new commit in the\n> master repository. However some users may want to always track\n> the newest revision of a specific (named) tag or branch or HEAD.\n> For example the user might want to track a staging branch in all\n> submodules.\n\nI initially liked the direction this is going, but I think the above\nrationale and the change to use 0{40} have impedance mismatch.  Your\nchange is not a good way to go about \"some users may want\".  I'll discuss\nmore on this below.\n\n> To allow this the \"--track|-t <branch>\" parameter was added to\n> git-submodule.sh, which is added to .gitmodules config file as\n> well as \"track\" parameter. This creates a new local branch on\n> checkout, which is tracking the remote branch in case the local\n> branch does not yet exist.\n>\n> Technically the gitlink code was changed to always compare\n> successful (so no changes) in case the sha1 is null. In that\n> case no new commit is created when there are changes in the\n> submodule.\n\n\"Technically\" here sounds wrong.  I'd suggest dropping it, e.g. \"Update\nce_compare_gitlink() so that it always reports a match if the commit\nrecorded in the index is a null SHA-1.\"\n\nBecause I also do not see a direct connection between \"no new commit is\ncreated\" and \"there are changes in the submodule\", I think the last\nsentence in the above paragraph of yours is misleading.  The user _can_\ncreate A new commit in the superproject that records a different gitlink\nfrom its parent commit, if (and only if) the user wishes to bind the\nupdated subproject's branch state to the new state of the superproject,\nand that is done by adding the subproject status to the staging area with\n\"git add\" (or use \"git commit -a\").\n\nIt seems to me that what you are really after is to let you change the\nstate of the subproject checkout in whatever way and have \"git commit -a\"\nin the superproject ignore that change.\n\nI wonder if you can just set \"assume unchanged\" bit for the subproject\ngitlink in the index to achieve the same goal.\n\nOr is there more to it?\n\n> The submodule code is adding the file with 0000* on\n> \"add\".\n>\n> Signed-off-by: Fabian Franz <git@fabian-franz.de>\n> ---\n>\n> I like this and because of that the --branch is optional. I also like\n> that so much, that we have decided against Google Repo.\n>\n> However I have both cases: Stable development, where I need one special\n> version and \"wild\" development, where I always want the newest published\n> one.\n\nI do not think supporting both styles of development is a bad idea.\n\nHowever, use of 0{40} in the index and the resulting commit object in the\nsuperproject means that this is a project-wide decision, not your personal\npreference.  It is not implausible that you would want to do a wild\nexpeeriment in your own clone of a project that uses the \"Stable\ndevelopment\" approach (hence the upstream never would want to have 0{40}\ngitlink in its commits).\n\nFor example, suppose the project uses \"Stable development\" approach, and\nrecords the v1.0.0 of submodule at \"sub/\" in the superproject.  You are a\ncontributor to that project, and would want to help them futureproof the\nsuperproject code to be forward compatible with the upcoming v1.2.0\nrelease of the subproject.  What would you do?\n\n * have a clone of superproject, with v1.0.0 submodule bound at \"sub/\";\n\n * go to \"sub/\", fetch and checkout v1.2.0-rc2;\n\n * go up, build using the updated submodule, see many failures in\n   supermodule build;\n\n * fix them up in a way that can work with both v1.0.0 and v1.2.0 of the\n   submodule, while making commits in logical steps, in the supermodule.\n\nAnd you do not want to record the fact that you used v1.2.0-rc2 of the\nsubmodule at \"sub/\" in the commits you make in the supermodule, as you\nwould want to label these commits as \"futureproof for upcoming submodule\nv1.2.0\".\n\nBut you cannot use your 0{40} trick, as sending that to the upstream of\nthe superproject would break their \"Stable development\" policy.\n\nI wonder if you can just set \"assume unchanged\" bit for the subproject\ngitlink in the index to achieve the same goal.  That would be a local\noperation, the gitlink would still point at v1.0.0 version of submodule,\nand \"git commit -a\" in the superproject won't make commits that flips\neverybody else's copy to use v1.2.0-rc2 of submodule.\n\n>>I've reviewed the patch just from a shell code writer's point of view.\n>\n> Okay, I added your suggestions.\n\nIn the commentary section in your v2 patch, you said \"However I see\nproblems on remove\".  Has that issue been addressed?\n\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\"automatically pull\" in the sense that it always goes to the remote, fetch\nand merge?  That sounds horribly broken.  You can never work disconnected?\n\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\nHow does the branch parameter to the --track option interact with the\nbranch parameter to the --branch option?  Does an end user typically set\nthem to the same branch?  Or would these parameters almost always point at\ndifferent branchesof the remote repository?  What are the reasons for the\nend user to choose one parameter value for the --branch option and a\ndifferent parameter value for the --track option?\n\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index 2f47e06..16df528 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> ...\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> +\ttest -n \"$track\" && printf '160000 0000000000000000000000000000000000000000\\t%s\\n' \"$path\" | git update-index --index-info\n>  \n\nYou have many overlong lines due to the 0{40} constant string in your\npatch.  Have a\n\n\tnull_sha1=0000000000000000000000000000000000000000\n\nat the beginning of the script, and rewrite the above like this:\n\n\ttest -n \"$track\" &&\n                printf '160000 %s\\t%s\\n' \"$null_sha1\" \"$path\" |\n                git update-index --index-info\n\nor even like this:\n\n\tif test -n \"$track\"\n        then\n                printf '160000 %s\\t%s\\n' \"$null_sha1\" \"$path\" |\n                git update-index --index-info\n\tfi\n\nUse of $null_sha1 throughout the script will make things easier to read\nand at the same time make it less error prone as well for \"git submodule\"\ndevelopers.\n\n> @@ -345,11 +357,29 @@ 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\ttrack=$(git config submodule.\"$name\".track)\n> +\t\t\t\t: ${track:=\"master\"}\n\nIn the v2 patch this used to point at \"HEAD\".  What made you change your\nmind?\n\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\nNo error checking?\n\n\t(\n        \tunset GIT_DIR;\n                cd \"$path\" &&\n                git show-ref --heads --tags -q \"$track\" ||\n                git branch --track \"$track\" \"origin/$track\"\n\t) || barf\n\nThe ';' after unset is intentional; some shells reports failure when you\nunset an unset variable.\n\n> +\t\t\t\tsha1=\"$track\"\n> +\t\t\t\tpull=1\n\nI tend to prefer booleans in shell scripts spelled like boolean, e.g.\n\n\tpull=yes\n\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 ) || die \"Unable to pull in submodule path '$path'\"\n\nNo error checking?\n\n\n> +\t\t\tfi\n> +\n>  \t\tfi\n>  \tdone\n>  }\n> @@ -596,7 +626,8 @@ cmd_status()\n>  \t\tset_name_rev \"$path\" \"$sha1\"\n>  \t\tif git diff-files --quiet -- \"$path\"\n>  \t\tthen\n> -\t\t\tsay \" $sha1 $path$revname\"\n> +\t\t\ttrack=$(git config submodule.\"$name\".track)\n> +\t\t\tsay \" $sha1 $path$revname${track:+ (tracking \"$track\")}\"\n>  \t\telse\n>  \t\t\tif test -z \"$cached\"\n>  \t\t\tthen\n> diff --git a/read-cache.c b/read-cache.c\n> index 8579663..0c14b68 100644\n> --- a/read-cache.c\n> +++ b/read-cache.c\n> @@ -137,6 +137,11 @@ static int ce_compare_gitlink(struct cache_entry *ce)\n>  \t */\n>  \tif (resolve_gitlink_ref(ce->name, \"HEAD\", sha1) < 0)\n>  \t\treturn 0;\n> +\n> +\t// To be able to track newest revision\n> +\tif (is_null_sha1(ce->sha1))\n> +\t\treturn 0;\n> +\n\nI think the comment is wrong, as it is not about newness at all.\n\n\t/* ignore changes in the submodule path */\n\nwould be more appropriate.\n"},{"id":"97646","messageId":"20081212002101.292020@gmx.net","threadId":"16684","inReplyTo":"7vbpvicuk2.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v3] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Fabian Franz","fromEmail":"fabianfranz@gmx.de","sentAt":"2008-12-12T00:21:01Z","receivedAt":"2008-12-12T00:21:01Z","isPatch":true,"sender":{"key":"fabianfranz@gmx.de","avatar":null},"body":"> Fabian Franz <git@fabian-franz.de> writes:\n> \n> > Submodules currently only allow tracking a specific revision\n> > and each update in a submodule leads to a new commit in the\n> > master repository. However some users may want to always track\n> > the newest revision of a specific (named) tag or branch or HEAD.\n> > For example the user might want to track a staging branch in all\n> > submodules.\n> \n> I initially liked the direction this is going, but I think the above\n> rationale and the change to use 0{40} have impedance mismatch.  Your\n> change is not a good way to go about \"some users may want\".  I'll discuss\n> more on this below.\n\nI do agree. I did like the idea of HEAD.gitlink also better and I even more like the assume-unchanged version, which works.\n\n> It seems to me that what you are really after is to let you change the\n> state of the subproject checkout in whatever way and have \"git commit -a\"\n> in the superproject ignore that change.\n> \n> I wonder if you can just set \"assume unchanged\" bit for the subproject\n> gitlink in the index to achieve the same goal.\n> \n> Or is there more to it?\n\nNope, that is it. I just did not knew that flag.\n\n> > However I have both cases: Stable development, where I need one special\n> > version and \"wild\" development, where I always want the newest published\n> > one.\n> \n> I do not think supporting both styles of development is a bad idea.\n> \n> However, use of 0{40} in the index and the resulting commit object in the\n> superproject means that this is a project-wide decision, not your personal\n> preference.  It is not implausible that you would want to do a wild\n> expeeriment in your own clone of a project that uses the \"Stable\n> development\" approach (hence the upstream never would want to have 0{40}\n> gitlink in its commits).\n\nYes, but at the same time I might want to record it permanently as a project decision or play at my own with it ...\n\nSo both styles should be supported.\n\n> For example, suppose the project uses \"Stable development\" approach, and\n> records the v1.0.0 of submodule at \"sub/\" in the superproject.  You are a\n> contributor to that project, and would want to help them futureproof the\n> superproject code to be forward compatible with the upcoming v1.2.0\n> release of the subproject.  What would you do?\n> \n>  * have a clone of superproject, with v1.0.0 submodule bound at \"sub/\";\n> \n>  * go to \"sub/\", fetch and checkout v1.2.0-rc2;\n> \n>  * go up, build using the updated submodule, see many failures in\n>    supermodule build;\n> \n>  * fix them up in a way that can work with both v1.0.0 and v1.2.0 of the\n>    submodule, while making commits in logical steps, in the supermodule.\n> \n> And you do not want to record the fact that you used v1.2.0-rc2 of the\n> submodule at \"sub/\" in the commits you make in the supermodule, as you\n> would want to label these commits as \"futureproof for upcoming submodule\n> v1.2.0\".\n> \n> But you cannot use your 0{40} trick, as sending that to the upstream of\n> the superproject would break their \"Stable development\" policy.\n> \n> I wonder if you can just set \"assume unchanged\" bit for the subproject\n> gitlink in the index to achieve the same goal.  That would be a local\n> operation, the gitlink would still point at v1.0.0 version of submodule,\n> and \"git commit -a\" in the superproject won't make commits that flips\n> everybody else's copy to use v1.2.0-rc2 of submodule.\n\nYes, that works. I tried it. I am now gonna change the patch to use this new approach and also re-think the workflow I want to support.\n \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> \"automatically pull\" in the sense that it always goes to the remote, fetch\n> and merge?  That sounds horribly broken.  You can never work disconnected?\n\nUhm, the same is already true for git submodule update. Before it checkouts the new branch it always does a fetch.\n\nHowever I think what I really want (without) scripting via foreach is:\n\ngit checkout staging\n\nIn .gitmodules is from a personal (own branch) or project wide decision the fact documented that the submodules do track staging and one stable tag for example.\n\n[module1]\ntrack = staging\n[module2]\ntrack = staging\n[module3]\ntrack = stable-v1.0.0\n\nAnd now I just do git submodule update and it fetches and afterwards checks out my local branch of staging and fast-forwards it.\n\nHowever I do agree that in that workflow you always have to go online and that is not good.\n\nBut in my case I also want a developer to just be able to change to \n\n[module1]\ntrack = feature_1\n[module2]\ntrack = feature_1\n[module3]\ntrack = stable-v1.0.0\n\nto work in a feature branch in two submodules at once.\n\nSo I am gonna rethink this design.\n\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> \n> How does the branch parameter to the --track option interact with the\n> branch parameter to the --branch option?  Does an end user typically set\n> them to the same branch?  Or would these parameters almost always point at\n> different branchesof the remote repository?  What are the reasons for the\n> end user to choose one parameter value for the --branch option and a\n> different parameter value for the --track option?\n\n--branch is always checking out just the branch on the initial add and then the branch head is of course recorded as commit in the index.\n\nHowever I found that option just helpful for creating a first initial commit already in a branch.\n\nFor later submodule init or updates this has no effect.\n\n> > diff --git a/git-submodule.sh b/git-submodule.sh\n> > index 2f47e06..16df528 100755\n> > --- a/git-submodule.sh\n> > +++ b/git-submodule.sh\n> > ...\n> > @@ -197,12 +203,14 @@ cmd_add()\n> >  \t\t(unset GIT_DIR; cd \"$path\" && git checkout -f -q ${branch:+-b\n> \"$branch\" \"origin/$branch\"}) ||\n> >  \t\tdie \"Unable to checkout submodule '$path'\"\n> >  \tfi\n> > +\ttest -n \"$track\" && printf '160000\n> 0000000000000000000000000000000000000000\\t%s\\n' \"$path\" | git update-index --index-info\n> >  \n> \n> You have many overlong lines due to the 0{40} constant string in your\n> patch.  Have a\n> \n> \tnull_sha1=0000000000000000000000000000000000000000\n> \n> at the beginning of the script, and rewrite the above like this:\n> \n> \ttest -n \"$track\" &&\n>                 printf '160000 %s\\t%s\\n' \"$null_sha1\" \"$path\" |\n>                 git update-index --index-info\n> \n> or even like this:\n> \n> \tif test -n \"$track\"\n>         then\n>                 printf '160000 %s\\t%s\\n' \"$null_sha1\" \"$path\" |\n>                 git update-index --index-info\n> \tfi\n> \n> Use of $null_sha1 throughout the script will make things easier to read\n> and at the same time make it less error prone as well for \"git submodule\"\n> developers.\n\nOkay, thanks that is a good practice.\n\n> > @@ -345,11 +357,29 @@ 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\ttrack=$(git config submodule.\"$name\".track)\n> > +\t\t\t\t: ${track:=\"master\"}\n> \n> In the v2 patch this used to point at \"HEAD\".  What made you change your\n> mind?\n\nBecause at the moment HEAD would be created as local branhc, which is horribly broken.\n\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\n> \"$track\" || git branch --track \"$track\" \"origin/$track\" )\n> \n> No error checking?\n> \n> \t(\n>         \tunset GIT_DIR;\n>                 cd \"$path\" &&\n>                 git show-ref --heads --tags -q \"$track\" ||\n>                 git branch --track \"$track\" \"origin/$track\"\n> \t) || barf\n> \n> The ';' after unset is intentional; some shells reports failure when you\n> unset an unset variable.\n\nOkay, thanks. I didn't know that.\n\n> \n> > +\t\t\t\tsha1=\"$track\"\n> > +\t\t\t\tpull=1\n> \n> I tend to prefer booleans in shell scripts spelled like boolean, e.g.\n> \n> \tpull=yes\n\nGood idea.\n\n> \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 ) || die \"Unable to pull in\n> submodule path '$path'\"\n> \n> No error checking?\n\nIn v3 there should be ... And I even see error checking in the above ...\n\n> \n> > +\t\t\tfi\n> > +\n> >  \t\tfi\n> >  \tdone\n> >  }\n> > @@ -596,7 +626,8 @@ cmd_status()\n> >  \t\tset_name_rev \"$path\" \"$sha1\"\n> >  \t\tif git diff-files --quiet -- \"$path\"\n> >  \t\tthen\n> > -\t\t\tsay \" $sha1 $path$revname\"\n> > +\t\t\ttrack=$(git config submodule.\"$name\".track)\n> > +\t\t\tsay \" $sha1 $path$revname${track:+ (tracking \"$track\")}\"\n> >  \t\telse\n> >  \t\t\tif test -z \"$cached\"\n> >  \t\t\tthen\n> > diff --git a/read-cache.c b/read-cache.c\n> > index 8579663..0c14b68 100644\n> > --- a/read-cache.c\n> > +++ b/read-cache.c\n> > @@ -137,6 +137,11 @@ static int ce_compare_gitlink(struct cache_entry\n> *ce)\n> >  \t */\n> >  \tif (resolve_gitlink_ref(ce->name, \"HEAD\", sha1) < 0)\n> >  \t\treturn 0;\n> > +\n> > +\t// To be able to track newest revision\n> > +\tif (is_null_sha1(ce->sha1))\n> > +\t\treturn 0;\n> > +\n> \n> I think the comment is wrong, as it is not about newness at all.\n> \n> \t/* ignore changes in the submodule path */\n> \n> would be more appropriate.\n\nYes, I do agree. I am now changing first to --assume-unchanged so this is made unnecessary.\n\nI'll write a PATCH/RFC next.\n\nThank you for your detailed feedback,\n\nBest Wishes,\n\nFabian\n"},{"id":"97647","messageId":"8c5c35580812111631k54657bdcme8f048c77b6765eb@mail.gmail.com","threadId":"16684","inReplyTo":"7vbpvicuk2.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH v3] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2008-12-12T00:31:31Z","receivedAt":"2008-12-12T00:31:31Z","isPatch":true,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On Thu, Dec 11, 2008 at 21:42, Junio C Hamano <gitster@pobox.com> wrote:\n> I wonder if you can just set \"assume unchanged\" bit for the subproject\n> gitlink in the index to achieve the same goal.\n\nUsing assume-unchanged works, in the sense that the modification to\nthe submodule is not detected in the containing repo. But running `git\nsubmodule update` will checkout the sha1 recorded in HEAD, and I\nsuspect Fabian wants something like the hypothetical command `git\nsubmodule update -b [branch]` which could do `(cd sub && git fetch &&\ngit reset --hard origin/$branch)`.\n\n\n>\n> Or is there more to it?\n>\n\nSomething like this (probably mangled) patch is needed for 'submodule\nstatus' to behave sensibly when the assume-unchanged bit is turned on\nfor a submodule path.\n\n\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 2f47e06..375dfbf 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -588,21 +588,21 @@ cmd_status()\n        do\n                name=$(module_name \"$path\") || exit\n                url=$(git config submodule.\"$name\".url)\n+               orgsha1=$(git ls-tree HEAD \"$path\" | cut -d ' ' -f 3 | cut -f 1)\n                if test -z \"$url\" || ! test -d \"$path\"/.git -o -f \"$path\"/.git\n                then\n                        say \"-$sha1 $path\"\n                        continue;\n                fi\n+               if test -z \"$cached\"\n+               then\n+                       sha1=$(unset GIT_DIR; cd \"$path\" && git\nrev-parse --verify HEAD)\n+               fi\n                set_name_rev \"$path\" \"$sha1\"\n-               if git diff-files --quiet -- \"$path\"\n+               if test \"$sha1\" = \"$orgsha1\"\n                then\n                        say \" $sha1 $path$revname\"\n                else\n-                       if test -z \"$cached\"\n-                       then\n-                               sha1=$(unset GIT_DIR; cd \"$path\" &&\ngit rev-parse --verify HEAD)\n-                               set_name_rev \"$path\" \"$sha1\"\n-                       fi\n                        say \"+$sha1 $path$revname\"\n                fi\n        done\n"},{"id":"97650","messageId":"7v8wqmb44l.fsf@gitster.siamese.dyndns.org","threadId":"16684","inReplyTo":"8c5c35580812111631k54657bdcme8f048c77b6765eb@mail.gmail.com","subject":"Re: [PATCH v3] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-12T00:59:06Z","receivedAt":"2008-12-12T00:59:06Z","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 Thu, Dec 11, 2008 at 21:42, Junio C Hamano <gitster@pobox.com> wrote:\n>> I wonder if you can just set \"assume unchanged\" bit for the subproject\n>> gitlink in the index to achieve the same goal.\n>\n> Using assume-unchanged works, in the sense that the modification to\n> the submodule is not detected in the containing repo. But running `git\n> submodule update` will checkout the sha1 recorded in HEAD, and I\n> suspect Fabian wants something like the hypothetical command `git\n> submodule update -b [branch]` which could do `(cd sub && git fetch &&\n> git reset --hard origin/$branch)`.\n\nYeah, that would *also* make sense, but I think that is orthogonal issue.\n\nYou can update the state of the checkouts of subproject repositories in\nany way you want.  Doing so however makes \"git commit -a\" inconvenient to\nuse without assume-unchanged.  The magic 0{40} which Fabian's patch\naddresses the same issue in a different way.\n\nAlthough I would probably detach the head at that point, rather than\nresetting whatever branch happens to be checked out:\n\n\t( cd sub && git fetch && git checkout origin/$branch^0 )\n\nWe also need to make sure that whatever we do we should not break\nworkflows that do not check out submodules that are uninteresting.  So\ndoing the above unconditionally to all the submodules is out.  In such a\nsparsely populated superproject, \"cd sub\" would go to an empty directory,\nand \"git fetch\" step would error out.\n\nI did not read Fabian's patch too deeply, and do not remember what checks\nit did before running \"git pull\".  Perhaps it pulled unconditionally?\n"},{"id":"97651","messageId":"7v3agub396.fsf@gitster.siamese.dyndns.org","threadId":"16684","inReplyTo":"20081212002101.292020@gmx.net","subject":"Re: [PATCH v3] submodule: Allow tracking of the newest revision of a branch in a submodule","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-12T01:17:57Z","receivedAt":"2008-12-12T01:17:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Fabian Franz\" <FabianFranz@gmx.de> writes:\n\n>> Fabian Franz <git@fabian-franz.de> writes:\n>> \n>> > However I have both cases: Stable development, where I need one special\n>> > version and \"wild\" development, where I always want the newest published\n>> > one.\n>> \n>> I do not think supporting both styles of development is a bad idea.\n>> \n>> However, use of 0{40} in the index and the resulting commit object in the\n>> superproject means that this is a project-wide decision, not your personal\n>> preference.  It is not implausible that you would want to do a wild\n>> expeeriment in your own clone of a project that uses the \"Stable\n>> development\" approach (hence the upstream never would want to have 0{40}\n>> gitlink in its commits).\n>\n> Yes, but at the same time I might want to record it permanently as a project decision or play at my own with it ...\n>\n> So both styles should be supported.\n\nWhile I think they both _could_ have uses, I do not necessarily agree with\nyour \"should be\".  First of all, I am not sure project wide 0{40} really\nmakes sense.\n\nBy creating such a commit in your superproject, you are essentially\nclaiming that you will work with _any_ future version of the subproject,\nwhich is rather absurd.\n\nAnd using 0{40} in trees and in the index to mark it is not really\nnecessary, and here is why.\n\nYou could tell the participants that you do not care the exact version by\nstoring 0{40} in the trees and the index, but in order for you to tell\nthem the tip of which branch of the subproject to use, you need to give\nthat information (i.e. branch name) to them as well.  Obviously there is\nnot enough space to put that information in gitlink (we could make room\nand I have another implementation in mind but that will be a more involved\nchange so for a moment let's not go there).  The infomation will come\nsomewhere out-of-band, not in trees nor in the index.  And at that point,\nthe presense of such an out-of-band information itself is a good enough\ncue that such a path in the superproject is for the \"wilder\" style of\ndevelopment with the submodule.\n\nSuch an out-of-band information is necessary to use submodules in\ndistributed development already (iow, the commit object name in gitlink is\nnot enough), and we already have a Porcelain convention for that.  The\ncanonical repository URL for each submodule path is distributed as part of\nthe superproject in .gitmodules.  I would imagine that the message from\nthe project that says \"we expect you to use 'wilder' development style\nwith this submodule, and use the tip of frotz branch here\", if it ever\nmakes sense, can be recorded in .gitmodules as well.\n\nWhen updating (or initializing) a submodule, we can check .gitmodules, and\niff it is the \"wilder\" kind, we can set assume-unchanged in the index and\nrun \"cd there && git fetch $remote $branch && git checkout FETCH_HEAD^0\"\nor whatever you did in your patch.\n\nIf the supermodule did not work well with the updated submodule in such a\ncheckout, at least you have one commit that you can reset your submodule\ncheckout to, if you do not wipe that information with 0{40} in the trees\nand in the index.  The commit recorded in the gitlink can serve as the\n\"project wide\" suggested version to use, even in \"wilder\" development\nstyle that also suggests to use \"tip of that branch\".\n"}]}