From patchwork Tue Dec 11 04:08:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yaroslav Halchenko X-Patchwork-Id: 10723017 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B566414E2 for ; Tue, 11 Dec 2018 04:08:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A38DB2A099 for ; Tue, 11 Dec 2018 04:08:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 969142A507; Tue, 11 Dec 2018 04:08:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DC9432A099 for ; Tue, 11 Dec 2018 04:08:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729146AbeLKEIt (ORCPT ); Mon, 10 Dec 2018 23:08:49 -0500 Received: from washoe.dartmouth.edu ([129.170.30.229]:54778 "EHLO smtp.onerussian.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727566AbeLKEIt (ORCPT ); Mon, 10 Dec 2018 23:08:49 -0500 Received: from c-76-24-253-1.hsd1.nh.comcast.net ([76.24.253.1] helo=localhost) by smtp.onerussian.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1gWZLi-0004zL-Cm; Mon, 10 Dec 2018 23:08:46 -0500 From: Yaroslav Halchenko To: git@vger.kernel.org Cc: Yaroslav Halchenko Date: Mon, 10 Dec 2018 23:08:38 -0500 Message-Id: <20181211040839.17472-1-debian@onerussian.com> X-Mailer: git-send-email 2.20.0.rc2.8.g0a3bec4a1c.dirty In-Reply-To: References: MIME-Version: 1.0 X-SA-Exim-Connect-IP: 76.24.253.1 X-SA-Exim-Rcpt-To: git@vger.kernel.org, yoh@onerussian.com X-SA-Exim-Mail-From: yoh@onerussian.com Subject: [PATCH 1/2] submodule: Add --reset-hard option for git submodule update X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:57:07 +0000) X-SA-Exim-Scanned: Yes (on smtp.onerussian.com) Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a --reset-hard option for the update command to hard reset submodule(s) to the gitlink for the corresponding submodule in the superproject. This feature is desired e.g. to be able to discard recent changes in the entire hierarchy of the submodules after running git reset --hard PREVIOUS_STATE in the superproject which leaves submodules in their original state, and git reset --hard --recurse-submodules PREVIOUS_STATE would result in the submodules being checked into detached HEADs. As in the original git reset --hard no checks or any kind of safe-guards against jumping into some state which was never on the current branch is done. must_die_on_failure is not set to yes to mimic behavior of a update --checkout strategy, which would leave user with a non-clean state immediately apparent via git status so an informed decision/actions could be done manually. Signed-off-by: Yaroslav Halchenko --- Documentation/git-submodule.txt | 12 +++++++++++- Documentation/gitmodules.txt | 4 ++-- builtin/submodule--helper.c | 3 ++- git-submodule.sh | 10 +++++++++- submodule.c | 4 ++++ submodule.h | 1 + t/t7406-submodule-update.sh | 17 ++++++++++++++++- 7 files changed, 45 insertions(+), 6 deletions(-) diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index ba3c4df550..f4e0483997 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -124,7 +124,7 @@ If you really want to remove a submodule from the repository and commit that use linkgit:git-rm[1] instead. See linkgit:gitsubmodules[7] for removal options. -update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge] [--reference ] [--depth ] [--recursive] [--jobs ] [--] [...]:: +update [--init] [--remote] [-N|--no-fetch] [--[no-]recommend-shallow] [-f|--force] [--checkout|--rebase|--merge|--reset-hard] [--reference ] [--depth ] [--recursive] [--jobs ] [--] [...]:: + -- Update the registered submodules to match what the superproject @@ -358,6 +358,16 @@ the submodule itself. If the key `submodule.$name.update` is set to `rebase`, this option is implicit. +--reset-hard:: + This option is only valid for the update command. + Hard reset current state to the commit recorded in the superproject. + If this option is given, the submodule's HEAD will not get detached + if it was not detached before. Note that, like with a regular + `git reset --hard` no safe-guards are in place to prevent jumping + to a commit which was never part of the current branch. + If the key `submodule.$name.update` is set to `reset-hard`, this + option is implicit. + --init:: This option is only valid for the update command. Initialize all submodules for which "git submodule init" has not been diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt index 312b6f9259..e085dbc01f 100644 --- a/Documentation/gitmodules.txt +++ b/Documentation/gitmodules.txt @@ -43,8 +43,8 @@ submodule..update:: command in the superproject. This is only used by `git submodule init` to initialize the configuration variable of the same name. Allowed values here are 'checkout', 'rebase', - 'merge' or 'none'. See description of 'update' command in - linkgit:git-submodule[1] for their meaning. Note that the + 'merge', 'reset-hard' or 'none'. See description of 'update' command + in linkgit:git-submodule[1] for their meaning. Note that the '!command' form is intentionally ignored here for security reasons. diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index d38113a31a..31d95c3cd6 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1481,6 +1481,7 @@ static void determine_submodule_update_strategy(struct repository *r, if (just_cloned && (out->type == SM_UPDATE_MERGE || out->type == SM_UPDATE_REBASE || + out->type == SM_UPDATE_RESET_HARD || out->type == SM_UPDATE_NONE)) out->type = SM_UPDATE_CHECKOUT; @@ -1851,7 +1852,7 @@ static int update_clone(int argc, const char **argv, const char *prefix) "submodule boundaries")), OPT_STRING(0, "update", &update, N_("string"), - N_("rebase, merge, checkout or none")), + N_("rebase, merge, checkout, reset-hard or none")), OPT_STRING_LIST(0, "reference", &suc.references, N_("repo"), N_("reference repository")), OPT_BOOL(0, "dissociate", &suc.dissociate, diff --git a/git-submodule.sh b/git-submodule.sh index 5e608f8bad..b5d6fad983 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -9,7 +9,7 @@ USAGE="[--quiet] add [-b ] [-f|--force] [--name ] [--reference ...] or: $dashless [--quiet] init [--] [...] or: $dashless [--quiet] deinit [-f|--force] (--all| [--] ...) - or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference ] [--recursive] [--] [...] + or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase|--reset-hard] [--[no-]recommend-shallow] [--reference ] [--recursive] [--] [...] or: $dashless [--quiet] summary [--cached|--files] [--summary-limit ] [commit] [--] [...] or: $dashless [--quiet] foreach [--recursive] or: $dashless [--quiet] sync [--recursive] [--] [...] @@ -483,6 +483,9 @@ cmd_update() -m|--merge) update="merge" ;; + --reset-hard) + update="reset-hard" + ;; --recursive) recursive=1 ;; @@ -621,6 +624,11 @@ cmd_update() say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")" must_die_on_failure=yes ;; + reset-hard) + command="git reset --hard" + die_msg="$(eval_gettext "Unable to reset --hard to '\$sha1' in submodule path '\$displaypath'")" + say_msg="$(eval_gettext "Submodule path '\$displaypath': was reset --hard to '\$sha1'")" + ;; !*) command="${update_module#!}" die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$displaypath'")" diff --git a/submodule.c b/submodule.c index 6415cc5580..4580cf0944 100644 --- a/submodule.c +++ b/submodule.c @@ -373,6 +373,8 @@ enum submodule_update_type parse_submodule_update_type(const char *value) return SM_UPDATE_REBASE; else if (!strcmp(value, "merge")) return SM_UPDATE_MERGE; + else if (!strcmp(value, "reset-hard")) + return SM_UPDATE_RESET_HARD; else if (*value == '!') return SM_UPDATE_COMMAND; else @@ -406,6 +408,8 @@ const char *submodule_strategy_to_string(const struct submodule_update_strategy return "checkout"; case SM_UPDATE_MERGE: return "merge"; + case SM_UPDATE_RESET_HARD: + return "reset-hard"; case SM_UPDATE_REBASE: return "rebase"; case SM_UPDATE_NONE: diff --git a/submodule.h b/submodule.h index a680214c01..f23ac4630e 100644 --- a/submodule.h +++ b/submodule.h @@ -29,6 +29,7 @@ enum submodule_update_type { SM_UPDATE_CHECKOUT, SM_UPDATE_REBASE, SM_UPDATE_MERGE, + SM_UPDATE_RESET_HARD, SM_UPDATE_NONE, SM_UPDATE_COMMAND }; diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index e87164aa8f..2e08e0047c 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -6,7 +6,8 @@ test_description='Test updating submodules This test verifies that "git submodule update" detaches the HEAD of the -submodule and "git submodule update --rebase/--merge" does not detach the HEAD. +submodule and "git submodule update --rebase/--merge/--reset-hard" does +not detach the HEAD. ' . ./test-lib.sh @@ -305,6 +306,20 @@ test_expect_success 'submodule update --merge staying on master' ' ) ' +test_expect_success 'submodule update --reset-hard staying on master' ' + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --reset-hard submodule && + cd submodule && + compare_head + ) +' + test_expect_success 'submodule update - rebase in .git/config' ' (cd super && git config submodule.submodule.update rebase From patchwork Tue Dec 11 04:08:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yaroslav Halchenko X-Patchwork-Id: 10723019 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E77B914E2 for ; Tue, 11 Dec 2018 04:08:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D71D52A099 for ; Tue, 11 Dec 2018 04:08:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C8C322A507; Tue, 11 Dec 2018 04:08:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A19D2A099 for ; Tue, 11 Dec 2018 04:08:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730078AbeLKEI6 (ORCPT ); Mon, 10 Dec 2018 23:08:58 -0500 Received: from washoe.dartmouth.edu ([129.170.30.229]:54780 "EHLO smtp.onerussian.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727566AbeLKEI6 (ORCPT ); Mon, 10 Dec 2018 23:08:58 -0500 Received: from c-76-24-253-1.hsd1.nh.comcast.net ([76.24.253.1] helo=localhost) by smtp.onerussian.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1gWZLs-0004zj-E5; Mon, 10 Dec 2018 23:08:56 -0500 From: Yaroslav Halchenko To: git@vger.kernel.org Cc: Yaroslav Halchenko Date: Mon, 10 Dec 2018 23:08:39 -0500 Message-Id: <20181211040839.17472-2-debian@onerussian.com> X-Mailer: git-send-email 2.20.0.rc2.8.g0a3bec4a1c.dirty In-Reply-To: <20181211040839.17472-1-debian@onerussian.com> References: <20181211040839.17472-1-debian@onerussian.com> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 76.24.253.1 X-SA-Exim-Rcpt-To: git@vger.kernel.org, yoh@onerussian.com X-SA-Exim-Mail-From: yoh@onerussian.com Subject: [PATCH 2/2] RF+ENH(TST): compare the entire list of submodule status --recursive to stay intact X-SA-Exim-Version: 4.2.1 (built Mon, 26 Dec 2011 16:57:07 +0000) X-SA-Exim-Scanned: Yes (on smtp.onerussian.com) Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP For submodule update --reset-hard the best test is comparison of the entire status as shown by submodule status --recursive. Upon update --reset-hard we should get back to the original state, with all the branches being the same (no detached HEAD) and commits identical to original (so no merges, new commits, etc). For that, I have introduced two helpers: {record,compare}_submodules_status and an additional test for --reset-hard in nested submodule. I have kept this as a separate PATCH to demonstrate the diff from the original test composition as introduced in the prior patch, and this one where all tests could be of the same type: record_submodule_status && perform evil actions && ! compare_submodule_status && # to double check that evil was done git submodule --reset-hard . && compare_submodule_status # assure that we are all good Signed-off-by: Yaroslav Halchenko --- t/t7406-submodule-update.sh | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 2e08e0047c..1927424f47 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -21,6 +21,17 @@ compare_head() test "$sha_master" = "$sha_head" } +record_submodules_status() +{ + git submodule status --recursive >expect +} + +compare_submodules_status() +{ + git submodule status --recursive >actual && + test_i18ncmp expect actual +} + test_expect_success 'setup a submodule tree' ' echo file > file && @@ -294,7 +305,7 @@ test_expect_success 'submodule update --rebase staying on master' ' test_expect_success 'submodule update --merge staying on master' ' (cd super/submodule && - git reset --hard HEAD~1 + git reset --hard HEAD~1 ) && (cd super && (cd submodule && @@ -307,16 +318,28 @@ test_expect_success 'submodule update --merge staying on master' ' ' test_expect_success 'submodule update --reset-hard staying on master' ' - (cd super/submodule && - git reset --hard HEAD~1 - ) && (cd super && + record_submodules_status && (cd submodule && - compare_head + git reset --hard HEAD~1 ) && + ! compare_submodules_status && git submodule update --reset-hard submodule && - cd submodule && - compare_head + compare_submodules_status + ) +' + +test_expect_success 'submodule update --reset-hard in nested submodule' ' + (cd recursivesuper && + git submodule update --init --recursive && + record_submodules_status && + (cd super/submodule && + echo 123 >> file && + git commit -m "new commit" file + ) && + ! compare_submodules_status && + git submodule update --reset-hard --recursive && + compare_submodules_status ) '