{"thread":{"id":"63564","subject":"[PATCH 0/2] contrib/subtree: Add -S/-gpg-sign","startedAt":"2025-06-02T16:40:45Z","lastAt":"2025-06-04T16:33:03Z","messageCount":12,"participants":["Patrik Weiskircher via GitGitGadget","D. Ben Knoble","Patrik Weiskircher","Kristoffer Haugsbakk","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"519483","messageId":"pull.1928.git.1748882439.gitgitgadget@gmail.com","threadId":"63564","inReplyTo":null,"subject":"[PATCH 0/2] contrib/subtree: Add -S/-gpg-sign","fromName":"Patrik Weiskircher via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-06-02T16:40:37Z","receivedAt":"2025-06-02T16:40:45Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"This patch adds support for the -S/--gpg-sign option to the git subtree\ncommand.\n\nCurrently, git subtree creates squash and merge commits without applying GPG\nsignatures, even when commit signing is configured via commit.gpgSign. This\ncauses issues in repositories that require signed commits for policy\nreasons.\n\nThe implementation ensures that -S/--gpg-sign behaves consistently with\nother Git commands, passing the flag through to git commit-tree and git\nmerge where appropriate.\n\nThis change improves compatibility with workflows and repositories that\nenforce signed commits.\n\nChanges have been made to this patch according to a discussion with Junio C\nHamano gitster@pobox.com on my previous patch attempt.\n\nPatrik Weiskircher (2):\n  contrib/subtree: parse using --stuck-long\n  contrib/subtree: add -S/--gpg-sign\n\n contrib/subtree/git-subtree.adoc   |  19 +++--\n contrib/subtree/git-subtree.sh     |  66 ++++++++---------\n contrib/subtree/t/t7900-subtree.sh | 113 +++++++++++++++++++++++++++++\n 3 files changed, 158 insertions(+), 40 deletions(-)\n\n\nbase-commit: 7014b55638da979331baf8dc31c4e1d697cf2d67\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1928%2Fpweiskircher%2Fsubtree-sign-the-second-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1928/pweiskircher/subtree-sign-the-second-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/1928\n-- \ngitgitgadget\n"},{"id":"519485","messageId":"fe7e918ba1831fffead46791441da350223998f7.1748882439.git.gitgitgadget@gmail.com","threadId":"63564","inReplyTo":"pull.1928.git.1748882439.gitgitgadget@gmail.com","subject":"[PATCH 1/2] contrib/subtree: parse using --stuck-long","fromName":"Patrik Weiskircher via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-06-02T16:40:38Z","receivedAt":"2025-06-02T16:40:45Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"From: Patrik Weiskircher <patrik@pspdfkit.com>\n\n-S/--gpg-sign requires an optional parameter. Optional parameter\nhandling only works unambiguous with git rev-parse --parseopt when using\nthe --stuck-long option.\n\nSigned-off-by: Patrik Weiskircher <patrik@pspdfkit.com>\n---\n contrib/subtree/git-subtree.sh | 34 +++++++++++++---------------------\n 1 file changed, 13 insertions(+), 21 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 15ae86db1b27..60b2431b8bba 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -115,7 +115,7 @@ main () {\n \tthen\n \t\tset -- -h\n \tfi\n-\tset_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\tset_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt --stuck-long -- \"$@\" || echo exit $?)\"\n \teval \"$set_args\"\n \t. git-sh-setup\n \trequire_work_tree\n@@ -131,9 +131,6 @@ main () {\n \t\topt=\"$1\"\n \t\tshift\n \t\tcase \"$opt\" in\n-\t\t\t--annotate|-b|-P|-m|--onto)\n-\t\t\t\tshift\n-\t\t\t\t;;\n \t\t\t--rejoin)\n \t\t\t\targ_split_rejoin=1\n \t\t\t\t;;\n@@ -177,42 +174,37 @@ main () {\n \t\tshift\n \n \t\tcase \"$opt\" in\n-\t\t-q)\n+\t\t--quiet)\n \t\t\targ_quiet=1\n \t\t\t;;\n-\t\t-d)\n+\t\t--debug)\n \t\t\targ_debug=1\n \t\t\t;;\n-\t\t--annotate)\n+\t\t--annotate=*)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_split_annotate=\"$1\"\n-\t\t\tshift\n+\t\t\targ_split_annotate=\"${opt#*=}\"\n \t\t\t;;\n \t\t--no-annotate)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n \t\t\targ_split_annotate=\n \t\t\t;;\n-\t\t-b)\n+\t\t--branch=*)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_split_branch=\"$1\"\n-\t\t\tshift\n+\t\t\targ_split_branch=\"${opt#*=}\"\n \t\t\t;;\n-\t\t-P)\n-\t\t\targ_prefix=\"${1%/}\"\n-\t\t\tshift\n+\t\t--prefix=*)\n+\t\t\targ_prefix=\"${opt#*=}\"\n \t\t\t;;\n-\t\t-m)\n+\t\t--message=*)\n \t\t\ttest -n \"$allow_addmerge\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_addmerge_message=\"$1\"\n-\t\t\tshift\n+\t\t\targ_addmerge_message=\"${opt#*=}\"\n \t\t\t;;\n \t\t--no-prefix)\n \t\t\targ_prefix=\n \t\t\t;;\n-\t\t--onto)\n+\t\t--onto=*)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_split_onto=\"$1\"\n-\t\t\tshift\n+\t\t\targ_split_onto=\"${opt#*=}\"\n \t\t\t;;\n \t\t--no-onto)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-- \ngitgitgadget\n\n"},{"id":"519484","messageId":"45ae2c31bc03bc00f4eff6b217c7e29c509be9a1.1748882439.git.gitgitgadget@gmail.com","threadId":"63564","inReplyTo":"pull.1928.git.1748882439.gitgitgadget@gmail.com","subject":"[PATCH 2/2] contrib/subtree: add -S/--gpg-sign","fromName":"Patrik Weiskircher via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-06-02T16:40:39Z","receivedAt":"2025-06-02T16:40:46Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"From: Patrik Weiskircher <patrik@pspdfkit.com>\n\nAllows optionally signing the commits that git subtree creates. This can\nbe necessary when working in a repository that requires gpg signed\ncommits.\n\nSigned-off-by: Patrik Weiskircher <patrik@pspdfkit.com>\n---\n contrib/subtree/git-subtree.adoc   |  19 +++--\n contrib/subtree/git-subtree.sh     |  32 ++++----\n contrib/subtree/t/t7900-subtree.sh | 113 +++++++++++++++++++++++++++++\n 3 files changed, 145 insertions(+), 19 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.adoc b/contrib/subtree/git-subtree.adoc\nindex 004abf415b8e..b2bcbcad0d05 100644\n--- a/contrib/subtree/git-subtree.adoc\n+++ b/contrib/subtree/git-subtree.adoc\n@@ -9,14 +9,14 @@ git-subtree - Merge subtrees together and split repository into subtrees\n SYNOPSIS\n --------\n [verse]\n-'git subtree' [<options>] -P <prefix> add <local-commit>\n-'git subtree' [<options>] -P <prefix> add <repository> <remote-ref>\n-'git subtree' [<options>] -P <prefix> merge <local-commit> [<repository>]\n-'git subtree' [<options>] -P <prefix> split [<local-commit>]\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <local-commit>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] merge <local-commit> [<repository>]\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] split [<local-commit>]\n \n [verse]\n-'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n-'git subtree' [<options>] -P <prefix> push <repository> <refspec>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] pull <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] push <repository> <refspec>\n \n DESCRIPTION\n -----------\n@@ -149,6 +149,13 @@ OPTIONS FOR ALL COMMANDS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n+-S[<keyid>]::\n+--gpg-sign[=<keyid>]::\n+--no-gpg-sign::\n+\tGPG-sign commits. The `keyid` argument is optional and\n+\tdefaults to the committer identity; `--no-gpg-sign` is useful to\n+\tcountermand a `--gpg-sign` option given earlier on the command line.\n+\n OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin')\n -----------------------------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 60b2431b8bba..3fddba797cb9 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -26,12 +26,12 @@ then\n fi\n \n OPTS_SPEC=\"\\\n-git subtree add   --prefix=<prefix> <commit>\n-git subtree add   --prefix=<prefix> <repository> <ref>\n-git subtree merge --prefix=<prefix> <commit>\n-git subtree split --prefix=<prefix> [<commit>]\n-git subtree pull  --prefix=<prefix> <repository> <ref>\n-git subtree push  --prefix=<prefix> <repository> <refspec>\n+git subtree add   --prefix=<prefix> [-S[=<key-id>]] <commit>\n+git subtree add   --prefix=<prefix> [-S[=<key-id>]] <repository> <ref>\n+git subtree merge --prefix=<prefix> [-S[=<key-id>]] <commit>\n+git subtree split --prefix=<prefix> [-S[=<key-id>]] [<commit>]\n+git subtree pull  --prefix=<prefix> [-S[=<key-id>]] <repository> <ref>\n+git subtree push  --prefix=<prefix> [-S[=<key-id>]] <repository> <refspec>\n --\n h,help!       show the help\n q,quiet!      quiet\n@@ -46,6 +46,7 @@ rejoin        merge the new branch back into HEAD\n  options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin')\n squash        merge subtree changes as a single commit\n m,message!=   use the given message as the commit message for the merge commit\n+S,gpg-sign?key-id   GPG-sign commits. The keyid argument is optional and defaults to the committer identity\n \"\n \n indent=0\n@@ -168,6 +169,7 @@ main () {\n \targ_split_annotate=\n \targ_addmerge_squash=\n \targ_addmerge_message=\n+    arg_gpg_sign=\n \twhile test $# -gt 0\n \tdo\n \t\topt=\"$1\"\n@@ -232,6 +234,9 @@ main () {\n \t\t\ttest -n \"$allow_addmerge\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n \t\t\targ_addmerge_squash=\n \t\t\t;;\n+\t--gpg-sign=* | --gpg-sign | --no-gpg-sign)\n+\t    arg_gpg_sign=\"$opt\"\n+\t    ;;\n \t\t--)\n \t\t\tbreak\n \t\t\t;;\n@@ -264,6 +269,7 @@ main () {\n \tdebug \"quiet: {$arg_quiet}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n+    debug \"gpg-sign: {$arg_gpg_sign}\"\n \tdebug\n \n \t\"cmd_$arg_command\" \"$@\"\n@@ -529,7 +535,7 @@ copy_commit () {\n \t\t\tprintf \"%s\" \"$arg_split_annotate\"\n \t\t\tcat\n \t\t) |\n-\t\tgit commit-tree \"$2\" $3  # reads the rest of stdin\n+\t\tgit commit-tree $arg_gpg_sign \"$2\" $3  # reads the rest of stdin\n \t) || die \"fatal: can't copy commit $1\"\n }\n \n@@ -675,10 +681,10 @@ new_squash_commit () {\n \tif test -n \"$old\"\n \tthen\n \t\tsquash_msg \"$dir\" \"$oldsub\" \"$newsub\" |\n-\t\tgit commit-tree \"$tree\" -p \"$old\" || exit $?\n+\t\tgit commit-tree $arg_gpg_sign \"$tree\" -p \"$old\" || exit $?\n \telse\n \t\tsquash_msg \"$dir\" \"\" \"$newsub\" |\n-\t\tgit commit-tree \"$tree\" || exit $?\n+\t\tgit commit-tree $arg_gpg_sign \"$tree\" || exit $?\n \tfi\n }\n \n@@ -917,11 +923,11 @@ cmd_add_commit () {\n \tthen\n \t\trev=$(new_squash_commit \"\" \"\" \"$rev\") || exit $?\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n-\t\t\tgit commit-tree \"$tree\" $headp -p \"$rev\") || exit $?\n+\t\t\tgit commit-tree $arg_gpg_sign \"$tree\" $headp -p \"$rev\") || exit $?\n \telse\n \t\trevp=$(peel_committish \"$rev\") || exit $?\n \t\tcommit=$(add_msg \"$dir\" $headrev \"$rev\" |\n-\t\t\tgit commit-tree \"$tree\" $headp -p \"$revp\") || exit $?\n+\t\t\tgit commit-tree $arg_gpg_sign \"$tree\" $headp -p \"$revp\") || exit $?\n \tfi\n \tgit reset \"$commit\" || exit $?\n \n@@ -1072,9 +1078,9 @@ cmd_merge () {\n \tif test -n \"$arg_addmerge_message\"\n \tthen\n \t\tgit merge --no-ff -Xsubtree=\"$arg_prefix\" \\\n-\t\t\t--message=\"$arg_addmerge_message\" \"$rev\"\n+\t\t\t--message=\"$arg_addmerge_message\" $arg_gpg_sign \"$rev\"\n \telse\n-\t\tgit merge --no-ff -Xsubtree=\"$arg_prefix\" $rev\n+\t\tgit merge --no-ff -Xsubtree=\"$arg_prefix\" $arg_gpg_sign $rev\n \tfi\n }\n \ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 3c6103f6d270..3edbb33af469 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -11,6 +11,7 @@ and push subcommands of git subtree.\n \n TEST_DIRECTORY=$(pwd)/../../../t\n . \"$TEST_DIRECTORY\"/test-lib.sh\n+. \"$TEST_DIRECTORY\"/lib-gpg.sh\n \n # Use our own wrapper around test-lib.sh's test_create_repo, in order\n # to set log.date=relative.  `git subtree` parses the output of `git\n@@ -1563,4 +1564,116 @@ test_expect_success 'subtree descendant check' '\n \t)\n '\n \n+test_expect_success GPG 'add subproj with GPG signing using -S flag' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" -S FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'add subproj with GPG signing using --gpg-sign flag' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --gpg-sign FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'add subproj with GPG signing using specific key ID' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" -S\"$GIT_COMMITTER_EMAIL\" FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'merge with GPG signing' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" -S FETCH_HEAD &&\n+\t\tgit verify-commit HEAD\n+\t)\n+'\n+\n+test_expect_success GPG 'split with GPG signing and --rejoin' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir/main-sub1\" &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree split --prefix=\"sub dir\" --rejoin -S &&\n+\t\tgit verify-commit HEAD\n+\t)\n+'\n+\n+test_expect_success GPG 'add with --squash and GPG signing' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash -S FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\t# With --squash, the commit subject should reference the squash commit (first parent of merge)\n+\t\tsquash_commit=$(git rev-parse HEAD^2) &&\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$squash_commit'\\'' as '\\''sub dir'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'pull with GPG signing' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree add --prefix=\"sub dir\" ./\"sub proj\" HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" -S ./\"sub proj\" HEAD &&\n+\t\tgit verify-commit HEAD\n+\t)\n+'\n+\n test_done\n-- \ngitgitgadget\n"},{"id":"519591","messageId":"CALnO6CDk4cP1Mef07F6Z8Sm-1MxwWWd-rYEfL-e5_Nnq50B4ng@mail.gmail.com","threadId":"63564","inReplyTo":"fe7e918ba1831fffead46791441da350223998f7.1748882439.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 1/2] contrib/subtree: parse using --stuck-long","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2025-06-03T20:42:34Z","receivedAt":"2025-06-03T20:42:46Z","isPatch":true,"sender":{"key":"ben.knoble@gmail.com","avatar":"https://avatars.githubusercontent.com/u/22802209?v=4"},"body":"On Mon, Jun 2, 2025 at 12:41 PM Patrik Weiskircher via GitGitGadget\n<gitgitgadget@gmail.com> wrote:\n>\n> From: Patrik Weiskircher <patrik@pspdfkit.com>\n>\n> -S/--gpg-sign requires an optional parameter. Optional parameter\n> handling only works unambiguous with git rev-parse --parseopt when using\n> the --stuck-long option.\n\nHere we mention \"-S\", but that flag isn't implemented yet, right?\n\nPerhaps something like:\n\n    Optional parameter handling only works unambiguous with git rev-parse\n    --parseopt when using the --stuck-long option. To prepare for future commits\n    which add flags with optional parameters, parse with --stuck-long.\n\n>\n> Signed-off-by: Patrik Weiskircher <patrik@pspdfkit.com>\n> ---\n>  contrib/subtree/git-subtree.sh | 34 +++++++++++++---------------------\n>  1 file changed, 13 insertions(+), 21 deletions(-)\n>\n> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\n> index 15ae86db1b27..60b2431b8bba 100755\n> --- a/contrib/subtree/git-subtree.sh\n> +++ b/contrib/subtree/git-subtree.sh\n> @@ -115,7 +115,7 @@ main () {\n>         then\n>                 set -- -h\n>         fi\n> -       set_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n> +       set_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt --stuck-long -- \"$@\" || echo exit $?)\"\n>         eval \"$set_args\"\n>         . git-sh-setup\n>         require_work_tree\n> @@ -131,9 +131,6 @@ main () {\n>                 opt=\"$1\"\n>                 shift\n>                 case \"$opt\" in\n> -                       --annotate|-b|-P|-m|--onto)\n> -                               shift\n> -                               ;;\n>                         --rejoin)\n>                                 arg_split_rejoin=1\n>                                 ;;\n> @@ -177,42 +174,37 @@ main () {\n>                 shift\n>\n>                 case \"$opt\" in\n> -               -q)\n> +               --quiet)\n>                         arg_quiet=1\n>                         ;;\n> -               -d)\n> +               --debug)\n>                         arg_debug=1\n>                         ;;\n> -               --annotate)\n> +               --annotate=*)\n>                         test -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n> -                       arg_split_annotate=\"$1\"\n> -                       shift\n> +                       arg_split_annotate=\"${opt#*=}\"\n>                         ;;\n>                 --no-annotate)\n>                         test -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n>                         arg_split_annotate=\n>                         ;;\n> -               -b)\n> +               --branch=*)\n>                         test -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n> -                       arg_split_branch=\"$1\"\n> -                       shift\n> +                       arg_split_branch=\"${opt#*=}\"\n>                         ;;\n> -               -P)\n> -                       arg_prefix=\"${1%/}\"\n> -                       shift\n> +               --prefix=*)\n> +                       arg_prefix=\"${opt#*=}\"\n>                         ;;\n> -               -m)\n> +               --message=*)\n>                         test -n \"$allow_addmerge\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n> -                       arg_addmerge_message=\"$1\"\n> -                       shift\n> +                       arg_addmerge_message=\"${opt#*=}\"\n>                         ;;\n>                 --no-prefix)\n>                         arg_prefix=\n>                         ;;\n> -               --onto)\n> +               --onto=*)\n>                         test -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n> -                       arg_split_onto=\"$1\"\n> -                       shift\n> +                       arg_split_onto=\"${opt#*=}\"\n>                         ;;\n>                 --no-onto)\n>                         test -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n> --\n> gitgitgadget\n>\n>\n\n\n-- \nD. Ben Knoble\n"},{"id":"519667","messageId":"CANMzfzjhe=mxrcxgyXYqOD3GJ0UdX=xsP7oq3H8OGPfuwOphow@mail.gmail.com","threadId":"63564","inReplyTo":"CALnO6CDk4cP1Mef07F6Z8Sm-1MxwWWd-rYEfL-e5_Nnq50B4ng@mail.gmail.com","subject":"Re: [PATCH 1/2] contrib/subtree: parse using --stuck-long","fromName":"Patrik Weiskircher","fromEmail":"patrik.weiskircher@nutrient.io","sentAt":"2025-06-04T13:56:50Z","receivedAt":"2025-06-04T13:57:03Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"On Tue, Jun 3, 2025 at 4:42 PM D. Ben Knoble <ben.knoble@gmail.com> wrote:\n>\n> On Mon, Jun 2, 2025 at 12:41 PM Patrik Weiskircher via GitGitGadget\n> <gitgitgadget@gmail.com> wrote:\n> >\n> > From: Patrik Weiskircher <patrik@pspdfkit.com>\n> >\n> > -S/--gpg-sign requires an optional parameter. Optional parameter\n> > handling only works unambiguous with git rev-parse --parseopt when using\n> > the --stuck-long option.\n>\n> Here we mention \"-S\", but that flag isn't implemented yet, right?\n>\n> Perhaps something like:\n>\n>     Optional parameter handling only works unambiguous with git rev-parse\n>     --parseopt when using the --stuck-long option. To prepare for future commits\n>     which add flags with optional parameters, parse with --stuck-long.\n>\n\nMakes sense! Changing that. What is a good policy to resubmit\nsomething? Should I wait longer? Sorry, very new here!\n"},{"id":"519668","messageId":"0c65723e-fb52-43e1-8bf2-32bd421163a1@app.fastmail.com","threadId":"63564","inReplyTo":"CANMzfzjhe=mxrcxgyXYqOD3GJ0UdX=xsP7oq3H8OGPfuwOphow@mail.gmail.com","subject":"Re: [PATCH 1/2] contrib/subtree: parse using --stuck-long","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2025-06-04T14:09:33Z","receivedAt":"2025-06-04T14:09:55Z","isPatch":true,"sender":{"key":"kristofferhaugsbakk@fastmail.com","avatar":null},"body":"On Wed, Jun 4, 2025, at 15:56, Patrik Weiskircher wrote:\n>>\n>> Here we mention \"-S\", but that flag isn't implemented yet, right?\n>>\n>> Perhaps something like:\n>>\n>>     Optional parameter handling only works unambiguous with git rev-parse\n>>     --parseopt when using the --stuck-long option. To prepare for future commits\n>>     which add flags with optional parameters, parse with --stuck-long.\n>>\n>\n> Makes sense! Changing that. What is a good policy to resubmit\n> something? Should I wait longer? Sorry, very new here!\n\n• Force-push your branch to gitgitgadget\n• Edit the PR description with something like “Changes since v1:” to\n  summarize the changes\n• (`/preview` comment)\n• To send the next version: `/submit` comment again\n\nI think that’s it. :)\n\nI don’t think there’s a need to wait if you don’t want to.\n\n-- \nKristoffer Haugsbakk\n"},{"id":"519669","messageId":"pull.1928.v2.git.1749046597.gitgitgadget@gmail.com","threadId":"63564","inReplyTo":"pull.1928.git.1748882439.gitgitgadget@gmail.com","subject":"[PATCH v2 0/2] contrib/subtree: Add -S/-gpg-sign","fromName":"Patrik Weiskircher via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-06-04T14:16:35Z","receivedAt":"2025-06-04T14:16:40Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"This patch adds support for the -S/--gpg-sign option to the git subtree\ncommand.\n\nCurrently, git subtree creates squash and merge commits without applying GPG\nsignatures, even when commit signing is configured via commit.gpgSign. This\ncauses issues in repositories that require signed commits for policy\nreasons.\n\nThe implementation ensures that -S/--gpg-sign behaves consistently with\nother Git commands, passing the flag through to git commit-tree and git\nmerge where appropriate.\n\nThis change improves compatibility with workflows and repositories that\nenforce signed commits.\n\nChanges have been made to this patch according to a discussion with Junio C\nHamano gitster@pobox.com on my previous patch attempt.\n\nChanges since v1:\n\n * Adjusted commit message to not mention the not implemented flag yet.\n\nPatrik Weiskircher (2):\n  contrib/subtree: parse using --stuck-long\n  contrib/subtree: add -S/--gpg-sign\n\n contrib/subtree/git-subtree.adoc   |  19 +++--\n contrib/subtree/git-subtree.sh     |  66 ++++++++---------\n contrib/subtree/t/t7900-subtree.sh | 113 +++++++++++++++++++++++++++++\n 3 files changed, 158 insertions(+), 40 deletions(-)\n\n\nbase-commit: 0bd2d791cc9f745ebaedafc0e1cbebdebe41343e\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1928%2Fpweiskircher%2Fsubtree-sign-the-second-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1928/pweiskircher/subtree-sign-the-second-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/1928\n\nRange-diff vs v1:\n\n 1:  fe7e918ba18 ! 1:  5bbdbf01636 contrib/subtree: parse using --stuck-long\n     @@ Metadata\n       ## Commit message ##\n          contrib/subtree: parse using --stuck-long\n      \n     -    -S/--gpg-sign requires an optional parameter. Optional parameter\n     -    handling only works unambiguous with git rev-parse --parseopt when using\n     -    the --stuck-long option.\n     +    Optional parameter handling only works unambiguous with git rev-parse\n     +    --parseopt when using the --stuck-long option. To prepare for future commits\n     +    which add flags with optional parameters, parse with --stuck-long.\n      \n          Signed-off-by: Patrik Weiskircher <patrik@pspdfkit.com>\n      \n 2:  45ae2c31bc0 = 2:  af5b4a65b63 contrib/subtree: add -S/--gpg-sign\n\n-- \ngitgitgadget\n"},{"id":"519670","messageId":"5bbdbf01636058b945ec7f40df6f2a8cb4cdc966.1749046597.git.gitgitgadget@gmail.com","threadId":"63564","inReplyTo":"pull.1928.v2.git.1749046597.gitgitgadget@gmail.com","subject":"[PATCH v2 1/2] contrib/subtree: parse using --stuck-long","fromName":"Patrik Weiskircher via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-06-04T14:16:36Z","receivedAt":"2025-06-04T14:16:41Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"From: Patrik Weiskircher <patrik@pspdfkit.com>\n\nOptional parameter handling only works unambiguous with git rev-parse\n--parseopt when using the --stuck-long option. To prepare for future commits\nwhich add flags with optional parameters, parse with --stuck-long.\n\nSigned-off-by: Patrik Weiskircher <patrik@pspdfkit.com>\n---\n contrib/subtree/git-subtree.sh | 34 +++++++++++++---------------------\n 1 file changed, 13 insertions(+), 21 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 15ae86db1b27..60b2431b8bba 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -115,7 +115,7 @@ main () {\n \tthen\n \t\tset -- -h\n \tfi\n-\tset_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\tset_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt --stuck-long -- \"$@\" || echo exit $?)\"\n \teval \"$set_args\"\n \t. git-sh-setup\n \trequire_work_tree\n@@ -131,9 +131,6 @@ main () {\n \t\topt=\"$1\"\n \t\tshift\n \t\tcase \"$opt\" in\n-\t\t\t--annotate|-b|-P|-m|--onto)\n-\t\t\t\tshift\n-\t\t\t\t;;\n \t\t\t--rejoin)\n \t\t\t\targ_split_rejoin=1\n \t\t\t\t;;\n@@ -177,42 +174,37 @@ main () {\n \t\tshift\n \n \t\tcase \"$opt\" in\n-\t\t-q)\n+\t\t--quiet)\n \t\t\targ_quiet=1\n \t\t\t;;\n-\t\t-d)\n+\t\t--debug)\n \t\t\targ_debug=1\n \t\t\t;;\n-\t\t--annotate)\n+\t\t--annotate=*)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_split_annotate=\"$1\"\n-\t\t\tshift\n+\t\t\targ_split_annotate=\"${opt#*=}\"\n \t\t\t;;\n \t\t--no-annotate)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n \t\t\targ_split_annotate=\n \t\t\t;;\n-\t\t-b)\n+\t\t--branch=*)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_split_branch=\"$1\"\n-\t\t\tshift\n+\t\t\targ_split_branch=\"${opt#*=}\"\n \t\t\t;;\n-\t\t-P)\n-\t\t\targ_prefix=\"${1%/}\"\n-\t\t\tshift\n+\t\t--prefix=*)\n+\t\t\targ_prefix=\"${opt#*=}\"\n \t\t\t;;\n-\t\t-m)\n+\t\t--message=*)\n \t\t\ttest -n \"$allow_addmerge\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_addmerge_message=\"$1\"\n-\t\t\tshift\n+\t\t\targ_addmerge_message=\"${opt#*=}\"\n \t\t\t;;\n \t\t--no-prefix)\n \t\t\targ_prefix=\n \t\t\t;;\n-\t\t--onto)\n+\t\t--onto=*)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-\t\t\targ_split_onto=\"$1\"\n-\t\t\tshift\n+\t\t\targ_split_onto=\"${opt#*=}\"\n \t\t\t;;\n \t\t--no-onto)\n \t\t\ttest -n \"$allow_split\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n-- \ngitgitgadget\n\n"},{"id":"519671","messageId":"af5b4a65b63b587d8dc186ef0575d019ecafab81.1749046597.git.gitgitgadget@gmail.com","threadId":"63564","inReplyTo":"pull.1928.v2.git.1749046597.gitgitgadget@gmail.com","subject":"[PATCH v2 2/2] contrib/subtree: add -S/--gpg-sign","fromName":"Patrik Weiskircher via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2025-06-04T14:16:37Z","receivedAt":"2025-06-04T14:16:42Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"From: Patrik Weiskircher <patrik@pspdfkit.com>\n\nAllows optionally signing the commits that git subtree creates. This can\nbe necessary when working in a repository that requires gpg signed\ncommits.\n\nSigned-off-by: Patrik Weiskircher <patrik@pspdfkit.com>\n---\n contrib/subtree/git-subtree.adoc   |  19 +++--\n contrib/subtree/git-subtree.sh     |  32 ++++----\n contrib/subtree/t/t7900-subtree.sh | 113 +++++++++++++++++++++++++++++\n 3 files changed, 145 insertions(+), 19 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.adoc b/contrib/subtree/git-subtree.adoc\nindex 004abf415b8e..b2bcbcad0d05 100644\n--- a/contrib/subtree/git-subtree.adoc\n+++ b/contrib/subtree/git-subtree.adoc\n@@ -9,14 +9,14 @@ git-subtree - Merge subtrees together and split repository into subtrees\n SYNOPSIS\n --------\n [verse]\n-'git subtree' [<options>] -P <prefix> add <local-commit>\n-'git subtree' [<options>] -P <prefix> add <repository> <remote-ref>\n-'git subtree' [<options>] -P <prefix> merge <local-commit> [<repository>]\n-'git subtree' [<options>] -P <prefix> split [<local-commit>]\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <local-commit>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] add <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] merge <local-commit> [<repository>]\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] split [<local-commit>]\n \n [verse]\n-'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n-'git subtree' [<options>] -P <prefix> push <repository> <refspec>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] pull <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> [-S[<keyid>]] push <repository> <refspec>\n \n DESCRIPTION\n -----------\n@@ -149,6 +149,13 @@ OPTIONS FOR ALL COMMANDS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n+-S[<keyid>]::\n+--gpg-sign[=<keyid>]::\n+--no-gpg-sign::\n+\tGPG-sign commits. The `keyid` argument is optional and\n+\tdefaults to the committer identity; `--no-gpg-sign` is useful to\n+\tcountermand a `--gpg-sign` option given earlier on the command line.\n+\n OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin')\n -----------------------------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 60b2431b8bba..3fddba797cb9 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -26,12 +26,12 @@ then\n fi\n \n OPTS_SPEC=\"\\\n-git subtree add   --prefix=<prefix> <commit>\n-git subtree add   --prefix=<prefix> <repository> <ref>\n-git subtree merge --prefix=<prefix> <commit>\n-git subtree split --prefix=<prefix> [<commit>]\n-git subtree pull  --prefix=<prefix> <repository> <ref>\n-git subtree push  --prefix=<prefix> <repository> <refspec>\n+git subtree add   --prefix=<prefix> [-S[=<key-id>]] <commit>\n+git subtree add   --prefix=<prefix> [-S[=<key-id>]] <repository> <ref>\n+git subtree merge --prefix=<prefix> [-S[=<key-id>]] <commit>\n+git subtree split --prefix=<prefix> [-S[=<key-id>]] [<commit>]\n+git subtree pull  --prefix=<prefix> [-S[=<key-id>]] <repository> <ref>\n+git subtree push  --prefix=<prefix> [-S[=<key-id>]] <repository> <refspec>\n --\n h,help!       show the help\n q,quiet!      quiet\n@@ -46,6 +46,7 @@ rejoin        merge the new branch back into HEAD\n  options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin')\n squash        merge subtree changes as a single commit\n m,message!=   use the given message as the commit message for the merge commit\n+S,gpg-sign?key-id   GPG-sign commits. The keyid argument is optional and defaults to the committer identity\n \"\n \n indent=0\n@@ -168,6 +169,7 @@ main () {\n \targ_split_annotate=\n \targ_addmerge_squash=\n \targ_addmerge_message=\n+    arg_gpg_sign=\n \twhile test $# -gt 0\n \tdo\n \t\topt=\"$1\"\n@@ -232,6 +234,9 @@ main () {\n \t\t\ttest -n \"$allow_addmerge\" || die_incompatible_opt \"$opt\" \"$arg_command\"\n \t\t\targ_addmerge_squash=\n \t\t\t;;\n+\t--gpg-sign=* | --gpg-sign | --no-gpg-sign)\n+\t    arg_gpg_sign=\"$opt\"\n+\t    ;;\n \t\t--)\n \t\t\tbreak\n \t\t\t;;\n@@ -264,6 +269,7 @@ main () {\n \tdebug \"quiet: {$arg_quiet}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n+    debug \"gpg-sign: {$arg_gpg_sign}\"\n \tdebug\n \n \t\"cmd_$arg_command\" \"$@\"\n@@ -529,7 +535,7 @@ copy_commit () {\n \t\t\tprintf \"%s\" \"$arg_split_annotate\"\n \t\t\tcat\n \t\t) |\n-\t\tgit commit-tree \"$2\" $3  # reads the rest of stdin\n+\t\tgit commit-tree $arg_gpg_sign \"$2\" $3  # reads the rest of stdin\n \t) || die \"fatal: can't copy commit $1\"\n }\n \n@@ -675,10 +681,10 @@ new_squash_commit () {\n \tif test -n \"$old\"\n \tthen\n \t\tsquash_msg \"$dir\" \"$oldsub\" \"$newsub\" |\n-\t\tgit commit-tree \"$tree\" -p \"$old\" || exit $?\n+\t\tgit commit-tree $arg_gpg_sign \"$tree\" -p \"$old\" || exit $?\n \telse\n \t\tsquash_msg \"$dir\" \"\" \"$newsub\" |\n-\t\tgit commit-tree \"$tree\" || exit $?\n+\t\tgit commit-tree $arg_gpg_sign \"$tree\" || exit $?\n \tfi\n }\n \n@@ -917,11 +923,11 @@ cmd_add_commit () {\n \tthen\n \t\trev=$(new_squash_commit \"\" \"\" \"$rev\") || exit $?\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n-\t\t\tgit commit-tree \"$tree\" $headp -p \"$rev\") || exit $?\n+\t\t\tgit commit-tree $arg_gpg_sign \"$tree\" $headp -p \"$rev\") || exit $?\n \telse\n \t\trevp=$(peel_committish \"$rev\") || exit $?\n \t\tcommit=$(add_msg \"$dir\" $headrev \"$rev\" |\n-\t\t\tgit commit-tree \"$tree\" $headp -p \"$revp\") || exit $?\n+\t\t\tgit commit-tree $arg_gpg_sign \"$tree\" $headp -p \"$revp\") || exit $?\n \tfi\n \tgit reset \"$commit\" || exit $?\n \n@@ -1072,9 +1078,9 @@ cmd_merge () {\n \tif test -n \"$arg_addmerge_message\"\n \tthen\n \t\tgit merge --no-ff -Xsubtree=\"$arg_prefix\" \\\n-\t\t\t--message=\"$arg_addmerge_message\" \"$rev\"\n+\t\t\t--message=\"$arg_addmerge_message\" $arg_gpg_sign \"$rev\"\n \telse\n-\t\tgit merge --no-ff -Xsubtree=\"$arg_prefix\" $rev\n+\t\tgit merge --no-ff -Xsubtree=\"$arg_prefix\" $arg_gpg_sign $rev\n \tfi\n }\n \ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 3c6103f6d270..3edbb33af469 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -11,6 +11,7 @@ and push subcommands of git subtree.\n \n TEST_DIRECTORY=$(pwd)/../../../t\n . \"$TEST_DIRECTORY\"/test-lib.sh\n+. \"$TEST_DIRECTORY\"/lib-gpg.sh\n \n # Use our own wrapper around test-lib.sh's test_create_repo, in order\n # to set log.date=relative.  `git subtree` parses the output of `git\n@@ -1563,4 +1564,116 @@ test_expect_success 'subtree descendant check' '\n \t)\n '\n \n+test_expect_success GPG 'add subproj with GPG signing using -S flag' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" -S FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'add subproj with GPG signing using --gpg-sign flag' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --gpg-sign FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'add subproj with GPG signing using specific key ID' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" -S\"$GIT_COMMITTER_EMAIL\" FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'merge with GPG signing' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" -S FETCH_HEAD &&\n+\t\tgit verify-commit HEAD\n+\t)\n+'\n+\n+test_expect_success GPG 'split with GPG signing and --rejoin' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir/main-sub1\" &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree split --prefix=\"sub dir\" --rejoin -S &&\n+\t\tgit verify-commit HEAD\n+\t)\n+'\n+\n+test_expect_success GPG 'add with --squash and GPG signing' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash -S FETCH_HEAD &&\n+\t\tgit verify-commit HEAD &&\n+\t\t# With --squash, the commit subject should reference the squash commit (first parent of merge)\n+\t\tsquash_commit=$(git rev-parse HEAD^2) &&\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$squash_commit'\\'' as '\\''sub dir'\\''\"\n+\t)\n+'\n+\n+test_expect_success GPG 'pull with GPG signing' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree add --prefix=\"sub dir\" ./\"sub proj\" HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" -S ./\"sub proj\" HEAD &&\n+\t\tgit verify-commit HEAD\n+\t)\n+'\n+\n test_done\n-- \ngitgitgadget\n"},{"id":"519676","messageId":"xmqqcybjcy5q.fsf@gitster.g","threadId":"63564","inReplyTo":"0c65723e-fb52-43e1-8bf2-32bd421163a1@app.fastmail.com","subject":"Re: [PATCH 1/2] contrib/subtree: parse using --stuck-long","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-04T15:41:05Z","receivedAt":"2025-06-04T15:41:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Kristoffer Haugsbakk\" <kristofferhaugsbakk@fastmail.com> writes:\n\n> On Wed, Jun 4, 2025, at 15:56, Patrik Weiskircher wrote:\n>>>\n>>> Here we mention \"-S\", but that flag isn't implemented yet, right?\n>>>\n>>> Perhaps something like:\n>>>\n>>>     Optional parameter handling only works unambiguous with git rev-parse\n>>>     --parseopt when using the --stuck-long option. To prepare for future commits\n>>>     which add flags with optional parameters, parse with --stuck-long.\n>>>\n>>\n>> Makes sense! Changing that. What is a good policy to resubmit\n>> something? Should I wait longer? Sorry, very new here!\n>\n> • Force-push your branch to gitgitgadget\n> • Edit the PR description with something like “Changes since v1:” to\n>   summarize the changes\n> • (`/preview` comment)\n> • To send the next version: `/submit` comment again\n>\n> I think that’s it. :)\n>\n> I don’t think there’s a need to wait if you don’t want to.\n\nIt would be nice for potential reviewers to give at least 24 hours\nto ensure people anywhere on the globe have a chance to comment, and\na chance for you to respond to them, before sending your next\niteration.\n\nAlso, for future reference, when responding to a review comment that\ncauses you to drastically change the course of the series, you can\nrespond whenever you want to, but it is nice to other potential\nreviewers to give at least 24 hours to voice their opinions, before\nsending an updated series based on that comment, since suggested\nchanges in such a comment may be controversial and after seeing you\nspend some time already to adjust to it, others may feel discouraged\nto make you redo your series again even whey they think the\nsuggested changes are not taking us in the right direction.\n"},{"id":"519677","messageId":"CANMzfzgOfb1O1cQTmDFRDWEDLO-J6E_iq-MRQimhpmgAkU8pYA@mail.gmail.com","threadId":"63564","inReplyTo":"xmqqcybjcy5q.fsf@gitster.g","subject":"Re: [PATCH 1/2] contrib/subtree: parse using --stuck-long","fromName":"Patrik Weiskircher","fromEmail":"patrik.weiskircher@nutrient.io","sentAt":"2025-06-04T15:43:08Z","receivedAt":"2025-06-04T15:43:21Z","isPatch":true,"sender":{"key":"patrik.weiskircher@nutrient.io","avatar":null},"body":"On Wed, Jun 4, 2025 at 11:41 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Kristoffer Haugsbakk\" <kristofferhaugsbakk@fastmail.com> writes:\n>\n> > On Wed, Jun 4, 2025, at 15:56, Patrik Weiskircher wrote:\n> >>>\n> >>> Here we mention \"-S\", but that flag isn't implemented yet, right?\n> >>>\n> >>> Perhaps something like:\n> >>>\n> >>>     Optional parameter handling only works unambiguous with git rev-parse\n> >>>     --parseopt when using the --stuck-long option. To prepare for future commits\n> >>>     which add flags with optional parameters, parse with --stuck-long.\n> >>>\n> >>\n> >> Makes sense! Changing that. What is a good policy to resubmit\n> >> something? Should I wait longer? Sorry, very new here!\n> >\n> > • Force-push your branch to gitgitgadget\n> > • Edit the PR description with something like “Changes since v1:” to\n> >   summarize the changes\n> > • (`/preview` comment)\n> > • To send the next version: `/submit` comment again\n> >\n> > I think that’s it. :)\n> >\n> > I don’t think there’s a need to wait if you don’t want to.\n>\n> It would be nice for potential reviewers to give at least 24 hours\n> to ensure people anywhere on the globe have a chance to comment, and\n> a chance for you to respond to them, before sending your next\n> iteration.\n>\n> Also, for future reference, when responding to a review comment that\n> causes you to drastically change the course of the series, you can\n> respond whenever you want to, but it is nice to other potential\n> reviewers to give at least 24 hours to voice their opinions, before\n> sending an updated series based on that comment, since suggested\n> changes in such a comment may be controversial and after seeing you\n> spend some time already to adjust to it, others may feel discouraged\n> to make you redo your series again even whey they think the\n> suggested changes are not taking us in the right direction.\n\nMakes sense! I'll keep that in mind for the future!\n"},{"id":"519682","messageId":"xmqqldq7bh6q.fsf@gitster.g","threadId":"63564","inReplyTo":"pull.1928.v2.git.1749046597.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 0/2] contrib/subtree: Add -S/-gpg-sign","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-06-04T16:33:01Z","receivedAt":"2025-06-04T16:33:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Patrik Weiskircher via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> Changes since v1:\n>\n>  * Adjusted commit message to not mention the not implemented flag yet.\n>\n> Patrik Weiskircher (2):\n>   contrib/subtree: parse using --stuck-long\n>   contrib/subtree: add -S/--gpg-sign\n>\n>  contrib/subtree/git-subtree.adoc   |  19 +++--\n>  contrib/subtree/git-subtree.sh     |  66 ++++++++---------\n>  contrib/subtree/t/t7900-subtree.sh | 113 +++++++++++++++++++++++++++++\n>  3 files changed, 158 insertions(+), 40 deletions(-)\n\nStill looking good.  Will queue.  Thanks.\n"}]}