{"thread":{"id":"26920","subject":"[PATCH] submodule: Add --force option for git submodule update","startedAt":"2011-03-30T07:56:21Z","lastAt":"2011-03-31T18:13:29Z","messageCount":9,"participants":["Nicolas Morey-Chaisemartin","Jens Lehmann","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"164666","messageId":"4D92E225.3040602@morey-chaisemartin.com","threadId":"26920","inReplyTo":null,"subject":"[PATCH] submodule: Add --force option for git submodule update","fromName":"Nicolas Morey-Chaisemartin","fromEmail":"devel-git@morey-chaisemartin.com","sentAt":"2011-03-30T07:56:21Z","receivedAt":"2011-03-30T07:56:21Z","isPatch":true,"sender":{"key":"devel-git@morey-chaisemartin.com","avatar":"https://avatars.githubusercontent.com/u/108326?v=4"},"body":"By default git submodule update runs a simple checkout on submodules\nthat are not up-to-date.\nIf the submodules contains modified or untracked files, the command may\nexit sanely with an error:\n\n$ git submodule update\nerror: Your local changes to the following files would be overwritten by\ncheckout:\n\tfile\nPlease, commit your changes or stash them before you can switch branches.\nAborting\nUnable to checkout '1b69c6e55606b48d3284a3a9efe4b58bfb7e8c9e' in\nsubmodule path 'test1'\n\nThis implies that to reset a whole git submodule tree, a user has to run\nfirst 'git submodule foreach --recursive git checkout -f' to then be\nable to run git submodule update.\n\nThis patch adds a --force option for the update command (only used for\nsubmodules without --rebase or --merge options). It passes the --force\noption to git checkout which will throw away the local changes.\nAlso when --force is specified, git checkout -f is always called on\nsubmodules whether their HEAD matches the reference or not.\n\nSigned-off-by: Nicolas Morey-Chaisemartin <nicolas@morey-chaisemartin.com>\n---\n Documentation/git-submodule.txt |    5 ++-\n git-submodule.sh                |   68 ++++++++++++++++++++------------------\n t/t7406-submodule-update.sh     |   23 +++++++++++++\n 3 files changed, 62 insertions(+), 34 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 3a5aa01..6482a84 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -185,8 +185,9 @@ OPTIONS\n \n -f::\n --force::\n-\tThis option is only valid for the add command.\n-\tAllow adding an otherwise ignored submodule path.\n+\tThis option is only valid for add and update commands.\n+\tWhen running add, allow adding an otherwise ignored submodule path.\n+\tWhen running update, throw away local changes in submodules.\n \n --cached::\n \tThis option is only valid for status and summary commands.  These\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 3a13397..a195879 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -8,7 +8,7 @@ dashless=$(basename \"$0\" | sed -e 's/-/ /')\n USAGE=\"[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]\n    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] init [--] [<path>...]\n-   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--] [<path>...]\"\n@@ -385,6 +385,9 @@ cmd_update()\n \t\t-N|--no-fetch)\n \t\t\tnofetch=1\n \t\t\t;;\n+\t\t-f | --force)\n+\t\t\tforce=$1\n+\t\t\t;;\n \t\t-r|--rebase)\n \t\t\tupdate=\"rebase\"\n \t\t\t;;\n@@ -430,6 +433,7 @@ cmd_update()\n \t\tname=$(module_name \"$path\") || exit\n \t\turl=$(git config submodule.\"$name\".url)\n \t\tupdate_module=$(git config submodule.\"$name\".update)\n+\t\tforce_checkout=\n \t\tif test -z \"$url\"\n \t\tthen\n \t\t\t# Only mention uninitialized submodules when its\n@@ -456,13 +460,38 @@ cmd_update()\n \t\t\tupdate_module=$update\n \t\tfi\n \n-\t\tif test \"$subsha1\" != \"$sha1\"\n+\t\tif test -z \"$subsha1\" -a -z \"$force\"\n+\t\tthen\n+\t\t    force_checkout=\"-f\"\n+\t\tfi\n+\n+\t\t# Is this something we just cloned?\n+\t\tcase \";$cloned_modules;\" in\n+\t\t    *\";$name;\"*)\n+\t\t\t # then there is no local change to integrate\n+\t\t\t update_module= ;;\n+\t\tesac\n+\n+\t\tcase \"$update_module\" in\n+\t\t    rebase)\n+\t\t\t command=\"git rebase\"\n+\t\t\t action=\"rebase\"\n+\t\t\t msg=\"rebased onto\"\n+\t\t\t ;;\n+\t\t    merge)\n+\t\t\t command=\"git merge\"\n+\t\t\t action=\"merge\"\n+\t\t\t msg=\"merged in\"\n+\t\t\t ;;\n+\t\t    *)\n+\t\t\t command=\"git checkout $force $force_checkout -q\"\n+\t\t\t action=\"checkout\"\n+\t\t\t msg=\"checked out\"\n+\t\t\t ;;\n+\t\tesac\n+\n+\t\tif test \"$subsha1\" != \"$sha1\" || test -n \"$force\" -a \"$action\" = \"checkout\"\n \t\tthen\n-\t\t\tforce=\n-\t\t\tif test -z \"$subsha1\"\n-\t\t\tthen\n-\t\t\t\tforce=\"-f\"\n-\t\t\tfi\n \n \t\t\tif test -z \"$nofetch\"\n \t\t\tthen\n@@ -471,31 +500,6 @@ cmd_update()\n \t\t\t\tdie \"Unable to fetch in submodule path '$path'\"\n \t\t\tfi\n \n-\t\t\t# Is this something we just cloned?\n-\t\t\tcase \";$cloned_modules;\" in\n-\t\t\t*\";$name;\"*)\n-\t\t\t\t# then there is no local change to integrate\n-\t\t\t\tupdate_module= ;;\n-\t\t\tesac\n-\n-\t\t\tcase \"$update_module\" in\n-\t\t\trebase)\n-\t\t\t\tcommand=\"git rebase\"\n-\t\t\t\taction=\"rebase\"\n-\t\t\t\tmsg=\"rebased onto\"\n-\t\t\t\t;;\n-\t\t\tmerge)\n-\t\t\t\tcommand=\"git merge\"\n-\t\t\t\taction=\"merge\"\n-\t\t\t\tmsg=\"merged in\"\n-\t\t\t\t;;\n-\t\t\t*)\n-\t\t\t\tcommand=\"git checkout $force -q\"\n-\t\t\t\taction=\"checkout\"\n-\t\t\t\tmsg=\"checked out\"\n-\t\t\t\t;;\n-\t\t\tesac\n-\n \t\t\t(clear_local_git_env; cd \"$path\" && $command \"$sha1\") ||\n \t\t\tdie \"Unable to $action '$sha1' in submodule path '$path'\"\n \t\t\tsay \"Submodule path '$path': $msg '$sha1'\"\ndiff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh\nindex fa9d23a..5d24d9f 100755\n--- a/t/t7406-submodule-update.sh\n+++ b/t/t7406-submodule-update.sh\n@@ -74,6 +74,29 @@ test_expect_success 'submodule update detaching the HEAD ' '\n \t)\n '\n \n+test_expect_success 'submodule update should fail due to local changes' '\n+\t(cd super/submodule &&\n+\t git reset --hard HEAD~1 &&\n+\t echo \"local change\" > file\n+\t) &&\n+\t(cd super &&\n+\t (cd submodule &&\n+\t  compare_head\n+\t ) &&\n+\t test_must_fail git submodule update submodule\n+\t)\n+'\n+test_expect_success 'submodule update should throw away changes with --force ' '\n+\t(cd super &&\n+\t (cd submodule &&\n+\t  compare_head\n+\t ) &&\n+\t git submodule update --force submodule &&\n+\t cd submodule &&\n+\t ! compare_head\n+\t)\n+'\n+\n test_expect_success 'submodule update --rebase staying on master' '\n \t(cd super/submodule &&\n \t  git checkout master\n"},{"id":"164703","messageId":"4D93773C.2010807@web.de","threadId":"26920","inReplyTo":"4D92E225.3040602@morey-chaisemartin.com","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-03-30T18:32:28Z","receivedAt":"2011-03-30T18:32:28Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 30.03.2011 09:56, schrieb Nicolas Morey-Chaisemartin:\n> By default git submodule update runs a simple checkout on submodules\n> that are not up-to-date.\n> If the submodules contains modified or untracked files, the command may\n> exit sanely with an error:\n> \n> $ git submodule update\n> error: Your local changes to the following files would be overwritten by\n> checkout:\n> \tfile\n> Please, commit your changes or stash them before you can switch branches.\n> Aborting\n> Unable to checkout '1b69c6e55606b48d3284a3a9efe4b58bfb7e8c9e' in\n> submodule path 'test1'\n> \n> This implies that to reset a whole git submodule tree, a user has to run\n> first 'git submodule foreach --recursive git checkout -f' to then be\n> able to run git submodule update.\n> \n> This patch adds a --force option for the update command (only used for\n> submodules without --rebase or --merge options). It passes the --force\n> option to git checkout which will throw away the local changes.\n> Also when --force is specified, git checkout -f is always called on\n> submodules whether their HEAD matches the reference or not.\n\nI like where this is going (and it has tests too :-).\n\nMaybe we can simplify the patch and simplify one of the tests (see below)\nbut apart from that I'm all for it.\n\n> Signed-off-by: Nicolas Morey-Chaisemartin <nicolas@morey-chaisemartin.com>\n> ---\n>  Documentation/git-submodule.txt |    5 ++-\n>  git-submodule.sh                |   68 ++++++++++++++++++++------------------\n>  t/t7406-submodule-update.sh     |   23 +++++++++++++\n>  3 files changed, 62 insertions(+), 34 deletions(-)\n> \n> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\n> index 3a5aa01..6482a84 100644\n> --- a/Documentation/git-submodule.txt\n> +++ b/Documentation/git-submodule.txt\n> @@ -185,8 +185,9 @@ OPTIONS\n>  \n>  -f::\n>  --force::\n> -\tThis option is only valid for the add command.\n> -\tAllow adding an otherwise ignored submodule path.\n> +\tThis option is only valid for add and update commands.\n> +\tWhen running add, allow adding an otherwise ignored submodule path.\n> +\tWhen running update, throw away local changes in submodules.\n>  \n>  --cached::\n>  \tThis option is only valid for status and summary commands.  These\n> diff --git a/git-submodule.sh b/git-submodule.sh\n> index 3a13397..a195879 100755\n> --- a/git-submodule.sh\n> +++ b/git-submodule.sh\n> @@ -8,7 +8,7 @@ dashless=$(basename \"$0\" | sed -e 's/-/ /')\n>  USAGE=\"[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]\n>     or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]\n>     or: $dashless [--quiet] init [--] [<path>...]\n> -   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]\n> +   or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]\n>     or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n>     or: $dashless [--quiet] foreach [--recursive] <command>\n>     or: $dashless [--quiet] sync [--] [<path>...]\"\n> @@ -385,6 +385,9 @@ cmd_update()\n>  \t\t-N|--no-fetch)\n>  \t\t\tnofetch=1\n>  \t\t\t;;\n> +\t\t-f | --force)\n> +\t\t\tforce=$1\n> +\t\t\t;;\n>  \t\t-r|--rebase)\n>  \t\t\tupdate=\"rebase\"\n>  \t\t\t;;\n\nAll looking good up to here. But I wonder if the rest of git-submodule.sh\ncould be changed a bit less invasive ... maybe as simple as this?\n\n@@ -458,7 +461,6 @@ cmd_update()\n\n \t\tif test \"$subsha1\" != \"$sha1\"\n \t\tthen\n-\t\t\tforce=\n \t\t\tif test -z \"$subsha1\"\n \t\t\tthen\n \t\t\t\tforce=\"-f\"\n\nNow force will not be cleared and thus contain \"-f\" if the user provided\nit on the command line. All tests (including your new ones) are running\nfine with this simplification ... am I missing something?\n\n> @@ -430,6 +433,7 @@ cmd_update()\n>  \t\tname=$(module_name \"$path\") || exit\n>  \t\turl=$(git config submodule.\"$name\".url)\n>  \t\tupdate_module=$(git config submodule.\"$name\".update)\n> +\t\tforce_checkout=\n>  \t\tif test -z \"$url\"\n>  \t\tthen\n>  \t\t\t# Only mention uninitialized submodules when its\n> @@ -456,13 +460,38 @@ cmd_update()\n>  \t\t\tupdate_module=$update\n>  \t\tfi\n>  \n> -\t\tif test \"$subsha1\" != \"$sha1\"\n> +\t\tif test -z \"$subsha1\" -a -z \"$force\"\n> +\t\tthen\n> +\t\t    force_checkout=\"-f\"\n> +\t\tfi\n> +\n> +\t\t# Is this something we just cloned?\n> +\t\tcase \";$cloned_modules;\" in\n> +\t\t    *\";$name;\"*)\n> +\t\t\t # then there is no local change to integrate\n> +\t\t\t update_module= ;;\n> +\t\tesac\n> +\n> +\t\tcase \"$update_module\" in\n> +\t\t    rebase)\n> +\t\t\t command=\"git rebase\"\n> +\t\t\t action=\"rebase\"\n> +\t\t\t msg=\"rebased onto\"\n> +\t\t\t ;;\n> +\t\t    merge)\n> +\t\t\t command=\"git merge\"\n> +\t\t\t action=\"merge\"\n> +\t\t\t msg=\"merged in\"\n> +\t\t\t ;;\n> +\t\t    *)\n> +\t\t\t command=\"git checkout $force $force_checkout -q\"\n> +\t\t\t action=\"checkout\"\n> +\t\t\t msg=\"checked out\"\n> +\t\t\t ;;\n> +\t\tesac\n> +\n> +\t\tif test \"$subsha1\" != \"$sha1\" || test -n \"$force\" -a \"$action\" = \"checkout\"\n>  \t\tthen\n> -\t\t\tforce=\n> -\t\t\tif test -z \"$subsha1\"\n> -\t\t\tthen\n> -\t\t\t\tforce=\"-f\"\n> -\t\t\tfi\n>  \n>  \t\t\tif test -z \"$nofetch\"\n>  \t\t\tthen\n> @@ -471,31 +500,6 @@ cmd_update()\n>  \t\t\t\tdie \"Unable to fetch in submodule path '$path'\"\n>  \t\t\tfi\n>  \n> -\t\t\t# Is this something we just cloned?\n> -\t\t\tcase \";$cloned_modules;\" in\n> -\t\t\t*\";$name;\"*)\n> -\t\t\t\t# then there is no local change to integrate\n> -\t\t\t\tupdate_module= ;;\n> -\t\t\tesac\n> -\n> -\t\t\tcase \"$update_module\" in\n> -\t\t\trebase)\n> -\t\t\t\tcommand=\"git rebase\"\n> -\t\t\t\taction=\"rebase\"\n> -\t\t\t\tmsg=\"rebased onto\"\n> -\t\t\t\t;;\n> -\t\t\tmerge)\n> -\t\t\t\tcommand=\"git merge\"\n> -\t\t\t\taction=\"merge\"\n> -\t\t\t\tmsg=\"merged in\"\n> -\t\t\t\t;;\n> -\t\t\t*)\n> -\t\t\t\tcommand=\"git checkout $force -q\"\n> -\t\t\t\taction=\"checkout\"\n> -\t\t\t\tmsg=\"checked out\"\n> -\t\t\t\t;;\n> -\t\t\tesac\n> -\n>  \t\t\t(clear_local_git_env; cd \"$path\" && $command \"$sha1\") ||\n>  \t\t\tdie \"Unable to $action '$sha1' in submodule path '$path'\"\n>  \t\t\tsay \"Submodule path '$path': $msg '$sha1'\"\n\nAnd if I'm right all stuff up to here can go.\n\n> diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh\n> index fa9d23a..5d24d9f 100755\n> --- a/t/t7406-submodule-update.sh\n> +++ b/t/t7406-submodule-update.sh\n> @@ -74,6 +74,29 @@ test_expect_success 'submodule update detaching the HEAD ' '\n>  \t)\n>  '\n>  \n> +test_expect_success 'submodule update should fail due to local changes' '\n> +\t(cd super/submodule &&\n> +\t git reset --hard HEAD~1 &&\n> +\t echo \"local change\" > file\n> +\t) &&\n> +\t(cd super &&\n> +\t (cd submodule &&\n> +\t  compare_head\n> +\t ) &&\n> +\t test_must_fail git submodule update submodule\n> +\t)\n> +'\n\nThis test is shorter and might be easier to understand rewritten as:\n\n+test_expect_success 'submodule update should fail due to local changes' '\n+\t(cd super &&\n+\t (cd submodule &&\n+\t  git reset --hard HEAD~1 &&\n+\t  echo \"local change\" > file\n+\t  compare_head\n+\t ) &&\n+\t test_must_fail git submodule update submodule\n+\t)\n+'\n\n> +test_expect_success 'submodule update should throw away changes with --force ' '\n> +\t(cd super &&\n> +\t (cd submodule &&\n> +\t  compare_head\n> +\t ) &&\n> +\t git submodule update --force submodule &&\n> +\t cd submodule &&\n> +\t ! compare_head\n> +\t)\n> +'\n> +\n>  test_expect_success 'submodule update --rebase staying on master' '\n>  \t(cd super/submodule &&\n>  \t  git checkout master\n"},{"id":"164705","messageId":"4D937B7E.10808@morey-chaisemartin.com","threadId":"26920","inReplyTo":"4D93773C.2010807@web.de","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Nicolas Morey-Chaisemartin","fromEmail":"devel-git@morey-chaisemartin.com","sentAt":"2011-03-30T18:50:38Z","receivedAt":"2011-03-30T18:50:38Z","isPatch":true,"sender":{"key":"devel-git@morey-chaisemartin.com","avatar":"https://avatars.githubusercontent.com/u/108326?v=4"},"body":"On 03/30/2011 08:32 PM, Jens Lehmann wrote:\n> Am 30.03.2011 09:56, schrieb Nicolas Morey-Chaisemartin:\n\n> All looking good up to here. But I wonder if the rest of git-submodule.sh\n> could be changed a bit less invasive ... maybe as simple as this?\n> \n> @@ -458,7 +461,6 @@ cmd_update()\n> \n>  \t\tif test \"$subsha1\" != \"$sha1\"\n>  \t\tthen\n> -\t\t\tforce=\n>  \t\t\tif test -z \"$subsha1\"\n>  \t\t\tthen\n>  \t\t\t\tforce=\"-f\"\n> \n> Now force will not be cleared and thus contain \"-f\" if the user provided\n> it on the command line. All tests (including your new ones) are running\n> fine with this simplification ... am I missing something?\n\nActually, I don't think this work.\nBy doing that, if you run git submodule update without -f, it will set -f when you reached the first submodule not yet checked out ( -z $subsha1 ),\nand the following submodules will be checkout using --force which may throw away changes the user wanted to keep.\n\nI know it is very intrusive. The main reason for that is I wanted the -f option to always behave the same (meaning throw away changes),\nwhether the submodule is already on the right commit or not.\n\nIf we accept to drop this and only drop the changes when subsha1 != sha1, the patch can be much sorter by simply keeping the force flags I used and without modifying all the case/while thing.\n\n\n>>  \n>> +test_expect_success 'submodule update should fail due to local changes' '\n>> +\t(cd super/submodule &&\n>> +\t git reset --hard HEAD~1 &&\n>> +\t echo \"local change\" > file\n>> +\t) &&\n>> +\t(cd super &&\n>> +\t (cd submodule &&\n>> +\t  compare_head\n>> +\t ) &&\n>> +\t test_must_fail git submodule update submodule\n>> +\t)\n>> +'\n> \n> This test is shorter and might be easier to understand rewritten as:\n> \n> +test_expect_success 'submodule update should fail due to local changes' '\n> +\t(cd super &&\n> +\t (cd submodule &&\n> +\t  git reset --hard HEAD~1 &&\n> +\t  echo \"local change\" > file\n> +\t  compare_head\n> +\t ) &&\n> +\t test_must_fail git submodule update submodule\n> +\t)\n> +'\n> \n\nAgreed.\n"},{"id":"164711","messageId":"4D937F09.10000@web.de","threadId":"26920","inReplyTo":"4D937B7E.10808@morey-chaisemartin.com","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-03-30T19:05:45Z","receivedAt":"2011-03-30T19:05:45Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 30.03.2011 20:50, schrieb Nicolas Morey-Chaisemartin:\n> On 03/30/2011 08:32 PM, Jens Lehmann wrote:\n>> Am 30.03.2011 09:56, schrieb Nicolas Morey-Chaisemartin:\n> \n>> All looking good up to here. But I wonder if the rest of git-submodule.sh\n>> could be changed a bit less invasive ... maybe as simple as this?\n>>\n>> @@ -458,7 +461,6 @@ cmd_update()\n>>\n>>  \t\tif test \"$subsha1\" != \"$sha1\"\n>>  \t\tthen\n>> -\t\t\tforce=\n>>  \t\t\tif test -z \"$subsha1\"\n>>  \t\t\tthen\n>>  \t\t\t\tforce=\"-f\"\n>>\n>> Now force will not be cleared and thus contain \"-f\" if the user provided\n>> it on the command line. All tests (including your new ones) are running\n>> fine with this simplification ... am I missing something?\n> \n> Actually, I don't think this work.\n> By doing that, if you run git submodule update without -f, it will set -f when you reached the first submodule not yet checked out ( -z $subsha1 ),\n> and the following submodules will be checkout using --force which may throw away changes the user wanted to keep.\n\nYou are right, I just came to that conclusion myself ... but with a loop\nlocal variable initialized from force on every iteration it should work.\n\n> I know it is very intrusive. The main reason for that is I wanted the -f option to always behave the same (meaning throw away changes),\n> whether the submodule is already on the right commit or not.\n\nHmm, I don't know if that is a good thing to do. People are used to\n\"git submodule update\" to only touch those submodule where the HEAD\ndiffers from the commit recorded in the superproject (And I often\nfind myself using \"-f\" if the command didn't succeed without it).\nBut when using \"-f\" touches other submodules than not using it the\nuser might experience a rather unpleasant surprise, I'm not sure we\nwant to go that way.\n\n> If we accept to drop this and only drop the changes when subsha1 != sha1, the patch can be much sorter by simply keeping the force flags I used and without modifying all the case/while thing.\n\nYes.\n"},{"id":"164725","messageId":"4D93905E.5030806@morey-chaisemartin.com","threadId":"26920","inReplyTo":"4D937F09.10000@web.de","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Nicolas Morey-Chaisemartin","fromEmail":"devel-git@morey-chaisemartin.com","sentAt":"2011-03-30T20:19:42Z","receivedAt":"2011-03-30T20:19:42Z","isPatch":true,"sender":{"key":"devel-git@morey-chaisemartin.com","avatar":"https://avatars.githubusercontent.com/u/108326?v=4"},"body":"On 03/30/2011 09:05 PM, Jens Lehmann wrote:\n>> I know it is very intrusive. The main reason for that is I wanted the -f option to always behave the same (meaning throw away changes),\n>> whether the submodule is already on the right commit or not.\n> \n> Hmm, I don't know if that is a good thing to do. People are used to\n> \"git submodule update\" to only touch those submodule where the HEAD\n> differs from the commit recorded in the superproject (And I often\n> find myself using \"-f\" if the command didn't succeed without it).\n> But when using \"-f\" touches other submodules than not using it the\n> user might experience a rather unpleasant surprise, I'm not sure we\n> want to go that way.\n> \n\nWell I was'nt sure about it either.\nThe idea for me was to be able to put the repo and submodules in the cloned state (except for ignored files)\nIn the current version the right thing to do is a bit of a mess:\n$ git submodule foreach --recursive 'git checkout -f HEAD'\n$ git submodule foreach --recursive 'git clean -f' # An untracked file on HEAD may be overwrittent by the new HEAD so checkout may fail if you don't do that\n$ git submodule update --recursive\n\nHopefully with --force we can simplify to:\n$ git submodule foreach --recursive 'git checkout -f HEAD'\n$ git submodule update --recursive --force\n\nHowever the first step is not that trivial for most people (I sadly have too many first hand examples with my git users).\nIf the --force option only works on submodule where HEAD differs from the reference, the first step will still be necessary !\nI find this a bit redundant.\n\nMaybe another way would be to add another option.\nKeep the --force as you proposed. And add a --all option of some sort that let the user decides if he wants to hit all the submodules or not.\nThis way we keep the regular behaviour with -f but provide a way to bypass the first step above.\n\nNicolas Morey-Chaisemartin\n"},{"id":"164729","messageId":"7vd3l8mi3m.fsf@alter.siamese.dyndns.org","threadId":"26920","inReplyTo":"4D93905E.5030806@morey-chaisemartin.com","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-03-30T21:08:45Z","receivedAt":"2011-03-30T21:08:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> writes:\n\n> On 03/30/2011 09:05 PM, Jens Lehmann wrote:\n>>> I know it is very intrusive. The main reason for that is I wanted the -f option to always behave the same (meaning throw away changes),\n>>> whether the submodule is already on the right commit or not.\n>> \n>> Hmm, I don't know if that is a good thing to do. People are used to\n>> \"git submodule update\" to only touch those submodule where the HEAD\n>> differs from the commit recorded in the superproject (And I often\n>> find myself using \"-f\" if the command didn't succeed without it).\n>> But when using \"-f\" touches other submodules than not using it the\n>> user might experience a rather unpleasant surprise, I'm not sure we\n>> want to go that way.\n>\n> Well I was'nt sure about it either.\n> The idea for me was to be able to put the repo and submodules in the cloned state (except for ignored files)\n> In the current version the right thing to do is a bit of a mess:\n> $ git submodule foreach --recursive 'git checkout -f HEAD'\n> $ git submodule foreach --recursive 'git clean -f' # An untracked file on HEAD may be overwrittent by the new HEAD so checkout may fail if you don't do that\n> $ git submodule update --recursive\n\nShouldn't you be questioning _why_ your users have such changes that\nrequire them to run \"checkout -f\" everywhere in the submodule forests and\nstill want to run \"submodule update\" in the first place?  If it happens\nvery often and your users are constantly discarding what they have half\naccomplished, there is something wrong with the way your project works.\n\nIf we read your motivation section in your original,\n\n  > This implies that to reset a whole git submodule tree, a user has to run\n  > first 'git submodule foreach --recursive git checkout -f' to then be\n  > able to run git submodule update.\n\nthis is about \"resetting\", i.e. throwing away the work.  I think that is a\nsensible thing to do, but it is a very different purpose than \"updating\nsubmodules so that I can work on top of what other people did\", which\nwould happen a lot more often than that.\n\nWouldn't it be both safer and easier to understand for the users if this\n\"obliterate all my uncommitted work\" were a separate subcommand, e.g. \"git\nsubmodule reset --recursive\" or something?\n"},{"id":"164752","messageId":"4D93E4F1.70103@morey-chaisemartin.com","threadId":"26920","inReplyTo":"7vd3l8mi3m.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Nicolas Morey-Chaisemartin","fromEmail":"devel-git@morey-chaisemartin.com","sentAt":"2011-03-31T02:20:33Z","receivedAt":"2011-03-31T02:20:33Z","isPatch":true,"sender":{"key":"devel-git@morey-chaisemartin.com","avatar":"https://avatars.githubusercontent.com/u/108326?v=4"},"body":"On 03/30/2011 11:08 PM, Junio C Hamano wrote:\n> Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> writes:\n>> Well I was'nt sure about it either.\n>> The idea for me was to be able to put the repo and submodules in the cloned state (except for ignored files)\n>> In the current version the right thing to do is a bit of a mess:\n>> $ git submodule foreach --recursive 'git checkout -f HEAD'\n>> $ git submodule foreach --recursive 'git clean -f' # An untracked file on HEAD may be overwrittent by the new HEAD so checkout may fail if you don't do that\n>> $ git submodule update --recursive\n> \n> Shouldn't you be questioning _why_ your users have such changes that\n> require them to run \"checkout -f\" everywhere in the submodule forests and\n> still want to run \"submodule update\" in the first place?  If it happens\n> very often and your users are constantly discarding what they have half\n> accomplished, there is something wrong with the way your project works.\n> \n\nI did. Thee reason is we commit file generated by compilation.\nWhether it's docs, references (for automated integration) or simply result files that take 2 days to build,\nwe have a strong need to commit generated files.\nAnd in this case, we need to discard a lot of things very often.\n\n> If we read your motivation section in your original,\n> \n>   > This implies that to reset a whole git submodule tree, a user has to run\n>   > first 'git submodule foreach --recursive git checkout -f' to then be\n>   > able to run git submodule update.\n> \n> this is about \"resetting\", i.e. throwing away the work.  I think that is a\n> sensible thing to do, but it is a very different purpose than \"updating\n> submodules so that I can work on top of what other people did\", which\n> would happen a lot more often than that.\n> \n> Wouldn't it be both safer and easier to understand for the users if this\n> \"obliterate all my uncommitted work\" were a separate subcommand, e.g. \"git\n> submodule reset --recursive\" or something?\n> \n\nI agree. A git submodule reset command makes a lot of sense.\nBut I also still think having a --force option to update does too, in the way Jens proposed it (only on submodule that actually needed a checkout), don't you?\n"},{"id":"164808","messageId":"4D94BCCC.7090808@web.de","threadId":"26920","inReplyTo":"4D93E4F1.70103@morey-chaisemartin.com","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2011-03-31T17:41:32Z","receivedAt":"2011-03-31T17:41:32Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 31.03.2011 04:20, schrieb Nicolas Morey-Chaisemartin:\n> On 03/30/2011 11:08 PM, Junio C Hamano wrote:\n>> Shouldn't you be questioning _why_ your users have such changes that\n>> require them to run \"checkout -f\" everywhere in the submodule forests and\n>> still want to run \"submodule update\" in the first place?  If it happens\n>> very often and your users are constantly discarding what they have half\n>> accomplished, there is something wrong with the way your project works.\n>\n> I did. Thee reason is we commit file generated by compilation.\n> Whether it's docs, references (for automated integration) or simply result files that take 2 days to build,\n> we have a strong need to commit generated files.\n\nWe are in a similar situation at my dayjob, but we handled the issue in\na different way. We were reluctant to check in generated files into our\nrepository, so we decided to distribute them via zip files. We have a\nbeefy build machine which builds and tests master over night and if\neverything went ok it zips the whole work tree including .git directory,\nbuild artifacts and submodules into one file. Then each developer just\nhas to unpack this file, fetch from the git server and he is all set.\n\n>> If we read your motivation section in your original,\n>>\n>>   > This implies that to reset a whole git submodule tree, a user has to run\n>>   > first 'git submodule foreach --recursive git checkout -f' to then be\n>>   > able to run git submodule update.\n>>\n>> this is about \"resetting\", i.e. throwing away the work.  I think that is a\n>> sensible thing to do, but it is a very different purpose than \"updating\n>> submodules so that I can work on top of what other people did\", which\n>> would happen a lot more often than that.\n>>\n>> Wouldn't it be both safer and easier to understand for the users if this\n>> \"obliterate all my uncommitted work\" were a separate subcommand, e.g. \"git\n>> submodule reset --recursive\" or something?\n> \n> I agree. A git submodule reset command makes a lot of sense.\n\nMe too agrees that being able to reset a whole work tree including all\nsubmodules recursively makes a lot of sense. But I would not be so happy\nseeing this functionality being added to the git-submodule.sh script, as\nI believe it belongs into \"git reset\", so you'll just have to do a \"git\nreset --hard --recurse-submodules\" and you are done.\n\nIn the branch \"git-checkout-recurse-submodules\" in my github repo (which\nis at https://github.com/jlehmann/git-submod-enhancements) you can see a\npreliminary implementation of that (it works and I use it every day at my\njob. It has recursion enabled by default at the moment yet still might\noverwrite local changes even if it shouldn't, so use with care ;-).\n\n> But I also still think having a --force option to update does too, in the way Jens proposed it (only on submodule that actually needed a checkout), don't you?\n\nYes, I still think it makes sense to add the \"-f\" flag to submodule update.\n"},{"id":"164810","messageId":"4D94C449.1040903@morey-chaisemartin.com","threadId":"26920","inReplyTo":"4D94BCCC.7090808@web.de","subject":"Re: [PATCH] submodule: Add --force option for git submodule update","fromName":"Nicolas Morey-Chaisemartin","fromEmail":"devel-git@morey-chaisemartin.com","sentAt":"2011-03-31T18:13:29Z","receivedAt":"2011-03-31T18:13:29Z","isPatch":true,"sender":{"key":"devel-git@morey-chaisemartin.com","avatar":"https://avatars.githubusercontent.com/u/108326?v=4"},"body":"On 03/31/2011 07:41 PM, Jens Lehmann wrote:\n> We are in a similar situation at my dayjob, but we handled the issue in\n> a different way. We were reluctant to check in generated files into our\n> repository, so we decided to distribute them via zip files. We have a\n> beefy build machine which builds and tests master over night and if\n> everything went ok it zips the whole work tree including .git directory,\n> build artifacts and submodules into one file. Then each developer just\n> has to unpack this file, fetch from the git server and he is all set.\n> \n\nWe have something a bit similar for cross project dependencies.\nWe just store in project a file with the SHA1 to another one and we have a server which stores all the packages ever generated\nand a sqliteDB to have the  SHA1 <=> package relation.\nIt works but it requires to add DB files, CGI script to update/query the DB...\nSo we limited this only to a few dependencies between otherwise separated projects.\nFor the rest, it's just easier to commit generated small files.\n\n\n> \n> Me too agrees that being able to reset a whole work tree including all\n> submodules recursively makes a lot of sense. But I would not be so happy\n> seeing this functionality being added to the git-submodule.sh script, as\n> I believe it belongs into \"git reset\", so you'll just have to do a \"git\n> reset --hard --recurse-submodules\" and you are done.\n> \nYes it is probably easier and clearer for everyone to put it into the dedicated command.\nThis way you know it does the same thing it usually does except on all submodules.\nThinking about \"git submodule reset\" I started wondering about what should be done for indexes, checked out files, ignored files and so on,\nand whatever is chosen it will confuse pretty much everyone.\nAlso a git clean --recurse-submodules would be nice !\n\n> In the branch \"git-checkout-recurse-submodules\" in my github repo (which\n> is at https://github.com/jlehmann/git-submod-enhancements) you can see a\n> preliminary implementation of that (it works and I use it every day at my\n> job. It has recursion enabled by default at the moment yet still might\n> overwrite local changes even if it shouldn't, so use with care ;-).\n> \nI'll have a look at it. For the moment I use a bash script which recurse in all submodules doing git clean and git checkout all other the place\n(it also works with old gits that lack all the foreach and --recursive features)\n\n>> But I also still think having a --force option to update does too, in the way Jens proposed it (only on submodule that actually needed a checkout), don't you?\n> \n> Yes, I still think it makes sense to add the \"-f\" flag to submodule update.\n> \n\nIf Junio agrees with the idea, I'll repost a much simpler version of the path that just add -f for the submodules that needs it.\n\nNicolas Morey-Chaisemartin\n"}]}