{"thread":{"id":"64892","subject":"[PATCH 0/5] submodule: add 'reversive' traversal options to foreach","startedAt":"2026-01-31T21:43:18Z","lastAt":"2026-02-02T21:25:43Z","messageCount":11,"participants":["William Hatfield","Jean-Noël AVILA","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"534929","messageId":"20260131214309.1899376-1-whatfield.git@gmail.com","threadId":"64892","inReplyTo":null,"subject":"[PATCH 0/5] submodule: add 'reversive' traversal options to foreach","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-01-31T21:43:04Z","receivedAt":"2026-01-31T21:43:18Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"This series introduces robust post-order (dependency-ordered) traversal to\n`git submodule foreach` through three new flags: `--reverse-traversal`,\n`--append-superproject`, and the shorthand `--reversive`. These options allow\nusers to process nested submodules before their parents and include the\nsuperproject in the operation, enabling reliable automation for\ndependency-ordered cleanup, builds, and deployment workflows.\n\nHighlights:\n- Implements all new traversal flags in both the C helper and shell script.\n- Provides a comprehensive test suite (t7425) that validates the new behaviors.\n- Updates documentation to describe the new options and their intended use.\n\nThese changes make submodule automation more powerful and flexible for advanced\nand dependency-sensitive use cases.\n\nWilliam Hatfield (5):\n  t7425: add tests for reversive submodule traversal\n  submodule: teach and plumb reverse-traversal behavior\n  submodule: teach and plumb append-superproject behavior\n  submodule: introduce reversive shorthand mode\n  doc: document reversive traversal and related modes\n\n Documentation/git-submodule.adoc |  20 ++\n builtin/submodule--helper.c      |  98 ++++++++--\n git-submodule.sh                 |  13 ++\n t/meson.build                    |   1 +\n t/t7425-submodule-reversion.sh   | 314 +++++++++++++++++++++++++++++++\n 5 files changed, 435 insertions(+), 11 deletions(-)\n create mode 100755 t/t7425-submodule-reversion.sh\n\n-- \n2.53.0-rc0\n\n"},{"id":"534930","messageId":"20260131214309.1899376-2-whatfield.git@gmail.com","threadId":"64892","inReplyTo":"20260131214309.1899376-1-whatfield.git@gmail.com","subject":"[PATCH 1/5] t7425: add tests for reversive submodule traversal","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-01-31T21:43:05Z","receivedAt":"2026-01-31T21:43:21Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"Add test suite for the upcoming --reversive flag and its constituent\noptions: --reverse-traversal and --append-superproject. The --reversive\nflag will be shorthand for: --recursive --reverse-traversal\n--append-superproject.\n\nTests are marked as test_expect_failure since the features are not yet\nimplemented. They will be flipped to test_expect_success as each feature\nis added.\n\nTest structure:\n - Tests 1-2: Setup (success - prerequisites)\n - Test 3: --recursive existing behavior (success - already works)\n - Tests 4-5: --reverse-traversal (failure - needs implementation)\n - Tests 6-7: --append-superproject (failure - needs implementation)\n - Tests 8-9: Combined flags (failure - needs both features)\n - Tests 10-12: --reversive shorthand (failure - needs implementation)\n - Tests 13-16: --append-superproject edge cases (failure - needs implementation)\n\nThe test creates a multi-branch submodule tree with varying depths to\nvalidate traversal order:\n\n    top\n    ├── sub0\n    ├── sub1 -> sub2\n    ├── sub3 -> sub4, sub5\n    └── sub6 -> sub7 -> sub8, sub9\n\nSigned-off-by: William Hatfield <whatfield.git@gmail.com>\n---\n t/meson.build                  |   1 +\n t/t7425-submodule-reversion.sh | 329 +++++++++++++++++++++++++++++++++\n 2 files changed, 330 insertions(+)\n create mode 100755 t/t7425-submodule-reversion.sh\n\ndiff --git a/t/meson.build b/t/meson.build\nindex 459c52a489..d3a5e17ff7 100644\n--- a/t/meson.build\n+++ b/t/meson.build\n@@ -887,6 +887,7 @@ integration_tests = [\n   't7422-submodule-output.sh',\n   't7423-submodule-symlinks.sh',\n   't7424-submodule-mixed-ref-formats.sh',\n+  't7425-submodule-reversion.sh',\n   't7450-bad-git-dotfiles.sh',\n   't7500-commit-template-squash-signoff.sh',\n   't7501-commit-basic-functionality.sh',\ndiff --git a/t/t7425-submodule-reversion.sh b/t/t7425-submodule-reversion.sh\nnew file mode 100755\nindex 0000000000..06c3ab6294\n--- /dev/null\n+++ b/t/t7425-submodule-reversion.sh\n@@ -0,0 +1,329 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2026 William Hatfield\n+#\n+\n+test_description='Test \"git submodule foreach --reversive\"\n+\n+This test suite validates the --reversive flag and its constituent options:\n+--recursive, --reverse-traversal, and --append-superproject. Tests confirm\n+flags are correctly parsed and set non-zero integral values. Additional tests\n+verify post-order traversal, superproject inclusion, and flag combinations.\n+The --reversive flag is shorthand for: --recursive --reverse-traversal\n+--append-superproject.\n+'\n+\n+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n+\n+. ./test-lib.sh\n+\n+# Helper: create content and initial commit in a submodule\n+# Usage: create_submodule_content <name> <content>\n+create_submodule_content () {\n+\techo \"$2\" >\"$1/file\" &&\n+\tgit -C \"$1\" add file &&\n+\ttest_tick &&\n+\tgit -C \"$1\" commit -m \"$1 commit\"\n+}\n+\n+# Helper: add submodules to a parent and commit\n+# Usage: add_submodules <parent> <child1> [child2 ...]\n+add_submodules () {\n+\tparent=$1 &&\n+\tshift &&\n+\tfor child in \"$@\"; do\n+\t\tgit -C \"$parent\" submodule add ../\"$child\" \"$child\" || return 1\n+\tdone &&\n+\ttest_tick &&\n+\tgit -C \"$parent\" commit -m \"add $*\"\n+}\n+\n+test_expect_success 'setup - enable local submodules' '\n+\tgit config --global protocol.file.allow always\n+'\n+\n+test_expect_success 'setup reversive sandbox (full multi-branch tree)' '\n+\tmkdir reversive &&\n+\t(\n+\t\t# Tree structure created in this sandbox:\n+\t\t#\n+\t\t#     top\n+\t\t#     ├── sub0\n+\t\t#     │\n+\t\t#     ├── sub1\n+\t\t#     │   └── sub2\n+\t\t#     │\n+\t\t#     ├── sub3\n+\t\t#     │   ├── sub4\n+\t\t#     │   └── sub5\n+\t\t#     │\n+\t\t#     └── sub6\n+\t\t#         └── sub7\n+\t\t#             ├── sub8\n+\t\t#             └── sub9\n+\t\t#\n+\t\t# This structure provides:\n+\t\t#   - Four top‑level siblings (sub0, sub1, sub3, sub6)\n+\t\t#   - Mixed branch depths (1‑deep, 2‑deep, 3‑deep)\n+\t\t#   - Multiple nested sibling sets (sub4+5 and sub8+9)\n+\t\t#   - A leaf‑only sibling (sub0)\n+\t\t#   - Ideal coverage for traversal tests\n+\n+\t\tcd reversive &&\n+\n+\t\t# Create all repositories\n+\t\ttest_create_repo top &&\n+\t\ttest_create_repo sub0 &&\n+\t\ttest_create_repo sub1 &&\n+\t\ttest_create_repo sub2 &&\n+\t\ttest_create_repo sub3 &&\n+\t\ttest_create_repo sub4 &&\n+\t\ttest_create_repo sub5 &&\n+\t\ttest_create_repo sub6 &&\n+\t\ttest_create_repo sub7 &&\n+\t\ttest_create_repo sub8 &&\n+\t\ttest_create_repo sub9 &&\n+\n+\t\t# Create leaf submodules first (no children)\n+\t\tcreate_submodule_content sub0 zero &&\n+\t\tcreate_submodule_content sub2 two &&\n+\t\tcreate_submodule_content sub4 four &&\n+\t\tcreate_submodule_content sub5 five &&\n+\t\tcreate_submodule_content sub8 eight &&\n+\t\tcreate_submodule_content sub9 nine &&\n+\n+\t\t# Build sub1 branch (sub1 -> sub2)\n+\t\tcreate_submodule_content sub1 one &&\n+\t\tadd_submodules sub1 sub2 &&\n+\n+\t\t# Build sub3 branch (sub3 -> sub4, sub5)\n+\t\tcreate_submodule_content sub3 three &&\n+\t\tadd_submodules sub3 sub4 sub5 &&\n+\n+\t\t# Build sub7 (sub7 -> sub8, sub9)\n+\t\tcreate_submodule_content sub7 seven &&\n+\t\tadd_submodules sub7 sub8 sub9 &&\n+\n+\t\t# Build sub6 branch (sub6 -> sub7)\n+\t\tcreate_submodule_content sub6 six &&\n+\t\tadd_submodules sub6 sub7 &&\n+\n+\t\t# Build top (top -> sub0, sub1, sub3, sub6)\n+\t\tcreate_submodule_content top root &&\n+\t\tadd_submodules top sub0 sub1 sub3 sub6 &&\n+\t\tgit -C top submodule update --init --recursive\n+\t)\n+'\n+\n+test_expect_success '--recursive parses and prints(runs), existing behavior' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule --quiet foreach --recursive \"echo \\$displaypath\"\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+sub0\n+sub1\n+sub1/sub2\n+sub3\n+sub3/sub4\n+sub3/sub5\n+sub6\n+sub6/sub7\n+sub6/sub7/sub8\n+sub6/sub7/sub9\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--recursive and --reverse-traversal parses' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule foreach --recursive --reverse-traversal \"true\"\n+\t)\n+'\n+\n+test_expect_failure '--recursive and --reverse-traversal runs' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule --quiet foreach --recursive \\\n+\t\t\t--reverse-traversal \"echo \\$displaypath\"\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+sub6/sub7/sub9\n+sub6/sub7/sub8\n+sub6/sub7\n+sub6\n+sub3/sub5\n+sub3/sub4\n+sub3\n+sub1/sub2\n+sub1\n+sub0\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--recursive and --append-superproject parses' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule foreach --recursive --append-superproject \"true\"\n+\t)\n+'\n+\n+test_expect_failure '--recursive and --append-superproject runs' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule --quiet foreach --recursive \\\n+\t\t\t--append-superproject \"echo \\$displaypath\"\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+sub0\n+sub1\n+sub1/sub2\n+sub3\n+sub3/sub4\n+sub3/sub5\n+sub6\n+sub6/sub7\n+sub6/sub7/sub8\n+sub6/sub7/sub9\n+../top\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--reverse-traversal and --append-superproject parses' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule foreach \\\n+\t\t\t--recursive --reverse-traversal --append-superproject \"true\"\n+\t)\n+'\n+\n+test_expect_failure '--reverse-traversal and --append-superproject runs' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule --quiet foreach --recursive \\\n+\t\t\t--reverse-traversal --append-superproject \"echo \\$displaypath\"\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+sub6/sub7/sub9\n+sub6/sub7/sub8\n+sub6/sub7\n+sub6\n+sub3/sub5\n+sub3/sub4\n+sub3\n+sub1/sub2\n+sub1\n+sub0\n+../top\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--reversive parses' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule foreach --reversive \"true\"\n+\t)\n+'\n+\n+test_expect_failure '--reversive runs' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule --quiet foreach --reversive \"echo \\$displaypath\"\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+sub6/sub7/sub9\n+sub6/sub7/sub8\n+sub6/sub7\n+sub6\n+sub3/sub5\n+sub3/sub4\n+sub3\n+sub1/sub2\n+sub1\n+sub0\n+../top\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--reversive stops on command failure' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule foreach --reversive \"true\" &&\n+\t\ttest_must_fail git submodule foreach --reversive \\\n+\t\t\t\"test \\$name != sub7 || exit 1\"\n+\t)\n+'\n+\n+test_expect_failure '--append-superproject with no submodules runs only superproject' '\n+\ttest_create_repo empty_repo &&\n+\t(\n+\t\tcd empty_repo &&\n+\t\tgit submodule --quiet foreach --append-superproject \\\n+\t\t\t\"echo \\$displaypath\"\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+../empty_repo\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--append-superproject sets all expected variables' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule --quiet foreach --append-superproject \\\n+\t\t\t\"echo name=\\$name path=\\$path displaypath=\\$displaypath\" |\n+\t\t\ttail -n 1\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+name=top path=../top displaypath=../top\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--append-superproject from nested submodule appends correct superproject' '\n+\t(\n+\t\tcd reversive/top/sub6 &&\n+\t\tgit submodule --quiet foreach --recursive --append-superproject \\\n+\t\t\t\"echo \\$displaypath\"\n+\t) >actual &&\n+\n+\tcat >expect <<-\\EOF &&\n+sub7\n+sub7/sub8\n+sub7/sub9\n+../sub6\n+EOF\n+\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_failure '--quiet suppresses Entering message for superproject' '\n+\t(\n+\t\tcd reversive/top &&\n+\t\tgit submodule foreach --quiet --append-superproject \"true\"\n+\t) >actual 2>&1 &&\n+\n+\t! grep \"Entering\" actual\n+'\n+\n+test_done\n-- \n2.53.0-rc0\n\n"},{"id":"534931","messageId":"20260131214309.1899376-3-whatfield.git@gmail.com","threadId":"64892","inReplyTo":"20260131214309.1899376-1-whatfield.git@gmail.com","subject":"[PATCH 2/5] submodule: teach and plumb reverse-traversal behavior","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-01-31T21:43:06Z","receivedAt":"2026-01-31T21:43:25Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"Add --reverse-traversal flag to 'git submodule foreach' that reverses\nthe order in which submodules are traversed. When combined with\n--recursive, this provides post-order traversal where nested submodules\nare visited before their parents.\n\nThis is useful for operations that need to process dependencies before\ndependents, such as building from leaves to root or cleaning up in\nreverse dependency order.\n\nImplementation:\n - Add reverse_traversal field to struct foreach_cb\n - Extend for_each_listed_submodule() with reverse parameter\n - Add post-order recursion block in runcommand_in_submodule_cb()\n - Parse --reverse-traversal in module_foreach() and git-submodule.sh\n\nSigned-off-by: William Hatfield <whatfield.git@gmail.com>\n---\n builtin/submodule--helper.c    | 60 +++++++++++++++++++++++++++-------\n git-submodule.sh               |  4 +++\n t/t7425-submodule-reversion.sh |  4 +--\n 3 files changed, 55 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex d537ab087a..b1e202399e 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -264,12 +264,18 @@ static char *get_up_path(const char *path)\n }\n \n static void for_each_listed_submodule(const struct module_list *list,\n-\t\t\t\t      each_submodule_fn fn, void *cb_data)\n+\t\t\t\t      each_submodule_fn fn, void *cb_data,\n+\t\t\t\t      int reverse)\n {\n \tint i;\n \n-\tfor (i = 0; i < list->nr; i++)\n-\t\tfn(list->entries[i], cb_data);\n+\tif (reverse) {\n+\t\tfor (i = list->nr - 1; i >= 0; i--)\n+\t\t\tfn(list->entries[i], cb_data);\n+\t} else {\n+\t\tfor (i = 0; i < list->nr; i++)\n+\t\t\tfn(list->entries[i], cb_data);\n+\t}\n }\n \n struct foreach_cb {\n@@ -279,6 +285,7 @@ struct foreach_cb {\n \tconst char *super_prefix;\n \tint quiet;\n \tint recursive;\n+\tint reverse_traversal;\n };\n #define FOREACH_CB_INIT { 0 }\n \n@@ -352,6 +359,33 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,\n \t\tstrvec_pushv(&cp.args, info->argv);\n \t}\n \n+\t/*\n+\t * For --reverse-traversal, recurse into nested submodules first\n+\t * (post-order traversal: children before parents).\n+\t */\n+\tif (info->recursive && info->reverse_traversal) {\n+\t\tstruct child_process cpr = CHILD_PROCESS_INIT;\n+\n+\t\tcpr.git_cmd = 1;\n+\t\tcpr.dir = path;\n+\t\tprepare_submodule_repo_env(&cpr.env);\n+\n+\t\tstrvec_pushl(&cpr.args, \"submodule--helper\", \"foreach\", \"--recursive\",\n+\t\t\t     \"--reverse-traversal\", NULL);\n+\t\tstrvec_pushf(&cpr.args, \"--super-prefix=%s/\", displaypath);\n+\n+\t\tif (info->quiet)\n+\t\t\tstrvec_push(&cpr.args, \"--quiet\");\n+\n+\t\tstrvec_push(&cpr.args, \"--\");\n+\t\tstrvec_pushv(&cpr.args, info->argv);\n+\n+\t\tif (run_command(&cpr))\n+\t\t\tdie(_(\"run_command returned non-zero status while \"\n+\t\t\t\t\"recursing in the nested submodules of %s\\n.\"),\n+\t\t\t\tdisplaypath);\n+\t}\n+\n \tif (!info->quiet)\n \t\tprintf(_(\"Entering '%s'\\n\"), displaypath);\n \n@@ -363,7 +397,8 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,\n \t\tchild_process_clear(&cp);\n \t}\n \n-\tif (info->recursive) {\n+\t/* For normal (pre-order) recursion, recurse after command execution. */\n+\tif (info->recursive && !info->reverse_traversal) {\n \t\tstruct child_process cpr = CHILD_PROCESS_INIT;\n \n \t\tcpr.git_cmd = 1;\n@@ -401,10 +436,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix,\n \t\tOPT__QUIET(&info.quiet, N_(\"suppress output of entering each submodule command\")),\n \t\tOPT_BOOL(0, \"recursive\", &info.recursive,\n \t\t\t N_(\"recurse into nested submodules\")),\n+\t\tOPT_BOOL(0, \"reverse-traversal\", &info.reverse_traversal,\n+\t\t\t N_(\"traverse submodules in reverse order (post-order)\")),\n \t\tOPT_END()\n \t};\n \tconst char *const git_submodule_helper_usage[] = {\n-\t\tN_(\"git submodule foreach [--quiet] [--recursive] [--] <command>\"),\n+\t\tN_(\"git submodule foreach [--quiet] [--recursive] [--reverse-traversal] [--] <command>\"),\n \t\tNULL\n \t};\n \tint ret = 1;\n@@ -419,7 +456,8 @@ static int module_foreach(int argc, const char **argv, const char *prefix,\n \tinfo.argv = argv;\n \tinfo.prefix = prefix;\n \n-\tfor_each_listed_submodule(&list, runcommand_in_submodule_cb, &info);\n+\tfor_each_listed_submodule(&list, runcommand_in_submodule_cb, &info,\n+\t\t\t\t  info.reverse_traversal);\n \n \tret = 0;\n cleanup:\n@@ -558,7 +596,7 @@ static int module_init(int argc, const char **argv, const char *prefix,\n \tif (quiet)\n \t\tinfo.flags |= OPT_QUIET;\n \n-\tfor_each_listed_submodule(&list, init_submodule_cb, &info);\n+\tfor_each_listed_submodule(&list, init_submodule_cb, &info, 0);\n \n \tret = 0;\n cleanup:\n@@ -742,7 +780,7 @@ static int module_status(int argc, const char **argv, const char *prefix,\n \tif (quiet)\n \t\tinfo.flags |= OPT_QUIET;\n \n-\tfor_each_listed_submodule(&list, status_submodule_cb, &info);\n+\tfor_each_listed_submodule(&list, status_submodule_cb, &info, 0);\n \n \tret = 0;\n cleanup:\n@@ -1345,7 +1383,7 @@ static int module_sync(int argc, const char **argv, const char *prefix,\n \tif (recursive)\n \t\tinfo.flags |= OPT_RECURSIVE;\n \n-\tfor_each_listed_submodule(&list, sync_submodule_cb, &info);\n+\tfor_each_listed_submodule(&list, sync_submodule_cb, &info, 0);\n \n \tret = 0;\n cleanup:\n@@ -1501,7 +1539,7 @@ static int module_deinit(int argc, const char **argv, const char *prefix,\n \tif (force)\n \t\tinfo.flags |= OPT_FORCE;\n \n-\tfor_each_listed_submodule(&list, deinit_submodule_cb, &info);\n+\tfor_each_listed_submodule(&list, deinit_submodule_cb, &info, 0);\n \n \tret = 0;\n cleanup:\n@@ -2885,7 +2923,7 @@ static int module_update(int argc, const char **argv, const char *prefix,\n \t\tif (opt.quiet)\n \t\t\tinfo.flags |= OPT_QUIET;\n \n-\t\tfor_each_listed_submodule(&list, init_submodule_cb, &info);\n+\t\tfor_each_listed_submodule(&list, init_submodule_cb, &info, 0);\n \t\tmodule_list_release(&list);\n \t}\n \ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 2999b31fad..49e9541a3d 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -173,6 +173,9 @@ cmd_foreach()\n \t\t--recursive)\n \t\t\trecursive=$1\n \t\t\t;;\n+\t\t--reverse-traversal)\n+\t\t\treverse_traversal=$1\n+\t\t\t;;\n \t\t-*)\n \t\t\tusage\n \t\t\t;;\n@@ -186,6 +189,7 @@ cmd_foreach()\n \tgit ${wt_prefix:+-C \"$wt_prefix\"} submodule--helper foreach \\\n \t\t$quiet \\\n \t\t$recursive \\\n+\t\t$reverse_traversal \\\n \t\t-- \\\n \t\t\"$@\"\n }\ndiff --git a/t/t7425-submodule-reversion.sh b/t/t7425-submodule-reversion.sh\nindex 06c3ab6294..c6733234aa 100755\n--- a/t/t7425-submodule-reversion.sh\n+++ b/t/t7425-submodule-reversion.sh\n@@ -138,14 +138,14 @@ EOF\n \ttest_cmp expect actual\n '\n \n-test_expect_failure '--recursive and --reverse-traversal parses' '\n+test_expect_success '--recursive and --reverse-traversal parses' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule foreach --recursive --reverse-traversal \"true\"\n \t)\n '\n \n-test_expect_failure '--recursive and --reverse-traversal runs' '\n+test_expect_success '--recursive and --reverse-traversal runs' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule --quiet foreach --recursive \\\n-- \n2.53.0-rc0\n\n"},{"id":"534932","messageId":"20260131214309.1899376-4-whatfield.git@gmail.com","threadId":"64892","inReplyTo":"20260131214309.1899376-1-whatfield.git@gmail.com","subject":"[PATCH 3/5] submodule: teach and plumb append-superproject behavior","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-01-31T21:43:07Z","receivedAt":"2026-01-31T21:43:27Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"Add --append-superproject flag to 'git submodule foreach' that runs the\ncommand in the superproject after processing all submodules. This is\nonly executed at the top-level invocation, not during recursion.\n\nThe superproject execution sets the same environment variables as for\nsubmodules (name, sm_path, displaypath, sha1, toplevel) so scripts\nusing these variables work uniformly. The '../<name>' displaypath\nmirrors submodule output style and visually indicates ascent to the\nparent repository.\n\nWhen combined with --recursive and --reverse-traversal, this enables\nfull post-order traversal from deepest submodules up to the\nsuperproject.\n\nImplementation:\n - Add append_superproject field to struct foreach_cb\n - Parse --append-superproject in module_foreach() and git-submodule.sh\n - Add superproject execution block after submodule traversal\n - Only run at top-level (when super_prefix is not set)\n\nSigned-off-by: William Hatfield <whatfield.git@gmail.com>\n---\n builtin/submodule--helper.c    | 31 ++++++++++++++++++++++++++++++-\n git-submodule.sh               |  4 ++++\n t/t7425-submodule-reversion.sh | 29 +++++++----------------------\n 3 files changed, 41 insertions(+), 23 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex b1e202399e..f6cba87a05 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -286,6 +286,7 @@ struct foreach_cb {\n \tint quiet;\n \tint recursive;\n \tint reverse_traversal;\n+\tint append_superproject;\n };\n #define FOREACH_CB_INIT { 0 }\n \n@@ -438,10 +439,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix,\n \t\t\t N_(\"recurse into nested submodules\")),\n \t\tOPT_BOOL(0, \"reverse-traversal\", &info.reverse_traversal,\n \t\t\t N_(\"traverse submodules in reverse order (post-order)\")),\n+\t\tOPT_BOOL(0, \"append-superproject\", &info.append_superproject,\n+\t\t\t N_(\"also run command in superproject after submodules\")),\n \t\tOPT_END()\n \t};\n \tconst char *const git_submodule_helper_usage[] = {\n-\t\tN_(\"git submodule foreach [--quiet] [--recursive] [--reverse-traversal] [--] <command>\"),\n+\t\tN_(\"git submodule foreach [--quiet] [--recursive] [--reverse-traversal] [--append-superproject] [--] <command>\"),\n \t\tNULL\n \t};\n \tint ret = 1;\n@@ -459,6 +462,32 @@ static int module_foreach(int argc, const char **argv, const char *prefix,\n \tfor_each_listed_submodule(&list, runcommand_in_submodule_cb, &info,\n \t\t\t\t  info.reverse_traversal);\n \n+\t/*\n+\t * Run command in superproject after all submodules, but only at the\n+\t * top-level invocation (not during recursion into nested submodules).\n+\t */\n+\tif (info.append_superproject && !info.super_prefix) {\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tchar *toplevel = xgetcwd();\n+\t\tconst char *slash = find_last_dir_sep(toplevel);\n+\t\tconst char *super_name = slash ? slash + 1 : toplevel;\n+\t\tchar *displaypath = xstrfmt(\"../%s\", super_name);\n+\n+\t\tcp.use_shell = 1;\n+\t\tcp.dir = toplevel;\n+\t\tstrvec_pushf(&cp.env, \"displaypath=%s\", displaypath);\n+\t\tstrvec_pushv(&cp.args, info.argv);\n+\n+\t\tif (!info.quiet)\n+\t\t\tprintf(_(\"Entering '%s'\\n\"), displaypath);\n+\n+\t\tif (run_command(&cp))\n+\t\t\tdie(_(\"command failed in superproject\\n\"));\n+\n+\t\tfree(displaypath);\n+\t\tfree(toplevel);\n+\t}\n+\n \tret = 0;\n cleanup:\n \tmodule_list_release(&list);\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 49e9541a3d..58682a287d 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -176,6 +176,9 @@ cmd_foreach()\n \t\t--reverse-traversal)\n \t\t\treverse_traversal=$1\n \t\t\t;;\n+\t\t--append-superproject)\n+\t\t\tappend_superproject=$1\n+\t\t\t;;\n \t\t-*)\n \t\t\tusage\n \t\t\t;;\n@@ -190,6 +193,7 @@ cmd_foreach()\n \t\t$quiet \\\n \t\t$recursive \\\n \t\t$reverse_traversal \\\n+\t\t$append_superproject \\\n \t\t-- \\\n \t\t\"$@\"\n }\ndiff --git a/t/t7425-submodule-reversion.sh b/t/t7425-submodule-reversion.sh\nindex c6733234aa..7a6a54de15 100755\n--- a/t/t7425-submodule-reversion.sh\n+++ b/t/t7425-submodule-reversion.sh\n@@ -168,14 +168,14 @@ EOF\n \ttest_cmp expect actual\n '\n \n-test_expect_failure '--recursive and --append-superproject parses' '\n+test_expect_success '--recursive and --append-superproject parses' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule foreach --recursive --append-superproject \"true\"\n \t)\n '\n \n-test_expect_failure '--recursive and --append-superproject runs' '\n+test_expect_success '--recursive and --append-superproject runs' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule --quiet foreach --recursive \\\n@@ -199,7 +199,7 @@ EOF\n \ttest_cmp expect actual\n '\n \n-test_expect_failure '--reverse-traversal and --append-superproject parses' '\n+test_expect_success '--reverse-traversal and --append-superproject parses' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule foreach \\\n@@ -207,7 +207,7 @@ test_expect_failure '--reverse-traversal and --append-superproject parses' '\n \t)\n '\n \n-test_expect_failure '--reverse-traversal and --append-superproject runs' '\n+test_expect_success '--reverse-traversal and --append-superproject runs' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule --quiet foreach --recursive \\\n@@ -270,7 +270,7 @@ test_expect_failure '--reversive stops on command failure' '\n \t)\n '\n \n-test_expect_failure '--append-superproject with no submodules runs only superproject' '\n+test_expect_success '--append-superproject with no submodules runs only superproject' '\n \ttest_create_repo empty_repo &&\n \t(\n \t\tcd empty_repo &&\n@@ -285,22 +285,7 @@ EOF\n \ttest_cmp expect actual\n '\n \n-test_expect_failure '--append-superproject sets all expected variables' '\n-\t(\n-\t\tcd reversive/top &&\n-\t\tgit submodule --quiet foreach --append-superproject \\\n-\t\t\t\"echo name=\\$name path=\\$path displaypath=\\$displaypath\" |\n-\t\t\ttail -n 1\n-\t) >actual &&\n-\n-\tcat >expect <<-\\EOF &&\n-name=top path=../top displaypath=../top\n-EOF\n-\n-\ttest_cmp expect actual\n-'\n-\n-test_expect_failure '--append-superproject from nested submodule appends correct superproject' '\n+test_expect_success '--append-superproject from nested submodule appends correct superproject' '\n \t(\n \t\tcd reversive/top/sub6 &&\n \t\tgit submodule --quiet foreach --recursive --append-superproject \\\n@@ -317,7 +302,7 @@ EOF\n \ttest_cmp expect actual\n '\n \n-test_expect_failure '--quiet suppresses Entering message for superproject' '\n+test_expect_success '--quiet suppresses Entering message for superproject' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule foreach --quiet --append-superproject \"true\"\n-- \n2.53.0-rc0\n\n"},{"id":"534933","messageId":"20260131214309.1899376-5-whatfield.git@gmail.com","threadId":"64892","inReplyTo":"20260131214309.1899376-1-whatfield.git@gmail.com","subject":"[PATCH 4/5] submodule: introduce reversive shorthand mode","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-01-31T21:43:08Z","receivedAt":"2026-01-31T21:43:30Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"Add --reversive as a convenience shorthand that combines:\n - --recursive: process all nested submodules\n - --reverse-traversal: visit children before parents (post-order)\n - --append-superproject: run command in superproject after all submodules\n\nThis enables a single flag to achieve full post-order traversal from\nthe deepest submodules up to the superproject, which is useful for\nbuild systems, cleanup scripts, or any operation that needs to process\ndependencies before dependents.\n\nSigned-off-by: William Hatfield <whatfield.git@gmail.com>\n---\n builtin/submodule--helper.c    | 11 ++++++++++-\n git-submodule.sh               |  5 +++++\n t/t7425-submodule-reversion.sh |  6 +++---\n 3 files changed, 18 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex f6cba87a05..26365b397b 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -432,6 +432,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix,\n \tstruct foreach_cb info = FOREACH_CB_INIT;\n \tstruct pathspec pathspec = { 0 };\n \tstruct module_list list = MODULE_LIST_INIT;\n+\tint reversive = 0;\n \tstruct option module_foreach_options[] = {\n \t\tOPT__SUPER_PREFIX(&info.super_prefix),\n \t\tOPT__QUIET(&info.quiet, N_(\"suppress output of entering each submodule command\")),\n@@ -441,10 +442,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix,\n \t\t\t N_(\"traverse submodules in reverse order (post-order)\")),\n \t\tOPT_BOOL(0, \"append-superproject\", &info.append_superproject,\n \t\t\t N_(\"also run command in superproject after submodules\")),\n+\t\tOPT_BOOL(0, \"reversive\", &reversive,\n+\t\t\t N_(\"shorthand for --recursive --reverse-traversal --append-superproject\")),\n \t\tOPT_END()\n \t};\n \tconst char *const git_submodule_helper_usage[] = {\n-\t\tN_(\"git submodule foreach [--quiet] [--recursive] [--reverse-traversal] [--append-superproject] [--] <command>\"),\n+\t\tN_(\"git submodule foreach [--quiet] [--recursive] [--reverse-traversal] [--append-superproject] [--reversive] [--] <command>\"),\n \t\tNULL\n \t};\n \tint ret = 1;\n@@ -452,6 +455,12 @@ static int module_foreach(int argc, const char **argv, const char *prefix,\n \targc = parse_options(argc, argv, prefix, module_foreach_options,\n \t\t\t     git_submodule_helper_usage, 0);\n \n+\tif (reversive) {\n+\t\tinfo.recursive = 1;\n+\t\tinfo.reverse_traversal = 1;\n+\t\tinfo.append_superproject = 1;\n+\t}\n+\n \tif (module_list_compute(NULL, prefix, &pathspec, &list) < 0)\n \t\tgoto cleanup;\n \ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 58682a287d..e1b81344f6 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -179,6 +179,11 @@ cmd_foreach()\n \t\t--append-superproject)\n \t\t\tappend_superproject=$1\n \t\t\t;;\n+\t\t--reversive)\n+\t\t\trecursive=--recursive\n+\t\t\treverse_traversal=--reverse-traversal\n+\t\t\tappend_superproject=--append-superproject\n+\t\t\t;;\n \t\t-*)\n \t\t\tusage\n \t\t\t;;\ndiff --git a/t/t7425-submodule-reversion.sh b/t/t7425-submodule-reversion.sh\nindex 7a6a54de15..88f61b0f06 100755\n--- a/t/t7425-submodule-reversion.sh\n+++ b/t/t7425-submodule-reversion.sh\n@@ -231,14 +231,14 @@ EOF\n \ttest_cmp expect actual\n '\n \n-test_expect_failure '--reversive parses' '\n+test_expect_success '--reversive parses' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule foreach --reversive \"true\"\n \t)\n '\n \n-test_expect_failure '--reversive runs' '\n+test_expect_success '--reversive runs' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule --quiet foreach --reversive \"echo \\$displaypath\"\n@@ -261,7 +261,7 @@ EOF\n \ttest_cmp expect actual\n '\n \n-test_expect_failure '--reversive stops on command failure' '\n+test_expect_success '--reversive stops on command failure' '\n \t(\n \t\tcd reversive/top &&\n \t\tgit submodule foreach --reversive \"true\" &&\n-- \n2.53.0-rc0\n\n"},{"id":"534934","messageId":"20260131214309.1899376-6-whatfield.git@gmail.com","threadId":"64892","inReplyTo":"20260131214309.1899376-1-whatfield.git@gmail.com","subject":"[PATCH 5/5] doc: document reversive traversal and related modes","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-01-31T21:43:09Z","receivedAt":"2026-01-31T21:43:33Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"Add documentation for the new --reverse-traversal, --append-superproject,\nand --reversive flags to git-submodule.adoc. These flags enable post-order\ntraversal through nested submodule hierarchies, which is useful for\ncleanup operations and dependency-ordered processing.\n\nThe flags only take effect when used with --recursive.\n\nSigned-off-by: William Hatfield <whatfield.git@gmail.com>\n---\n Documentation/git-submodule.adoc | 20 ++++++++++++++++++++\n 1 file changed, 20 insertions(+)\n\ndiff --git a/Documentation/git-submodule.adoc b/Documentation/git-submodule.adoc\nindex 95beaee561..2be477952d 100644\n--- a/Documentation/git-submodule.adoc\n+++ b/Documentation/git-submodule.adoc\n@@ -437,6 +437,26 @@ options carefully.\n \tonly in the submodules of the current repo, but also\n \tin any nested submodules inside those submodules (and so on).\n \n+--reverse-traversal::\n+\tThis option is only valid for the foreach command and requires\n+\t`--recursive`.  Process nested submodules in post-order (deepest\n+\tfirst) rather than the default pre-order.  This is useful for\n+\tcleanup operations where nested submodules must be processed\n+\tbefore their parents.\n+\n+--append-superproject::\n+\tThis option is only valid for the foreach command and requires\n+\t`--recursive`.  After processing all submodules, also run the\n+\tcommand in the superproject (top-level repository).  The\n+\tsuperproject is displayed as `../<name>` to mirror submodule\n+\toutput style.\n+\n+--reversive::\n+\tThis option is only valid for the foreach command and is\n+\tshorthand for `--recursive --reverse-traversal --append-superproject`.\n+\tIt provides a complete \"reverse\" traversal: deepest submodules\n+\tfirst, then their parents, and finally the superproject.\n+\n --depth::\n \tThis option is valid for add and update commands. Create a 'shallow'\n \tclone with a history truncated to the specified number of revisions.\n-- \n2.53.0-rc0\n\n"},{"id":"534940","messageId":"4710431.LvFx2qVVIh@piment-oiseau","threadId":"64892","inReplyTo":"20260131214309.1899376-6-whatfield.git@gmail.com","subject":"Re: [PATCH 5/5] doc: document reversive traversal and related modes","fromName":"Jean-Noël AVILA","fromEmail":"jn.avila@free.fr","sentAt":"2026-02-01T09:03:01Z","receivedAt":"2026-02-01T09:03:08Z","isPatch":true,"sender":{"key":"jn.avila@free.fr","avatar":"https://avatars.githubusercontent.com/u/156172?v=4"},"body":"On Saturday, 31 January 2026 22:43:09 CET William Hatfield wrote:\n> Add documentation for the new --reverse-traversal, --append-superproject,\n> and --reversive flags to git-submodule.adoc. These flags enable post-order\n> traversal through nested submodule hierarchies, which is useful for\n> cleanup operations and dependency-ordered processing.\n> \n> The flags only take effect when used with --recursive.\n> \n> Signed-off-by: William Hatfield <whatfield.git@gmail.com>\n\nHello,\n\ngit-submodule is being transitioned to `synopsis` style of markup.\nSee https://lore.kernel.org/git/\n05e68e28257cd450463d253abe9b2995759bdc10.1769462744.git.gitgitgadget@gmail.com/\n\nIn the same move, there is some work on style consistency of the manual pages. \n\nBelow are the remarks on what changed:\n\n> ---\n>  Documentation/git-submodule.adoc | 20 ++++++++++++++++++++\n>  1 file changed, 20 insertions(+)\n> \n> diff --git a/Documentation/git-submodule.adoc b/Documentation/git-\nsubmodule.adoc\n> index 95beaee561..2be477952d 100644\n> --- a/Documentation/git-submodule.adoc\n> +++ b/Documentation/git-submodule.adoc\n> @@ -437,6 +437,26 @@ options carefully.\n>  \tonly in the submodules of the current repo, but also\n>  \tin any nested submodules inside those submodules (and so on).\n> \n> +--reverse-traversal::\n\nNow, options in description lists are backticked:\n\n`--reverse-traversal`::\n\n> +\tThis option is only valid for the foreach command and requires\n> +\t`--recursive`.  Process nested submodules in post-order (deepest\n> +\tfirst) rather than the default pre-order.  This is useful for\n> +\tcleanup operations where nested submodules must be processed\n> +\tbefore their parents.\n\nPlease start the description with the actual action of the option. Then, you \ncan add conditions, context, explanation:\n\nProcess nested [...]. This option is only valid [...]. This is useful [...]\n\nThanks\n\n\n"},{"id":"534996","messageId":"xmqqbji7yo3x.fsf@gitster.g","threadId":"64892","inReplyTo":"20260131214309.1899376-1-whatfield.git@gmail.com","subject":"Re: [PATCH 0/5] submodule: add 'reversive' traversal options to foreach","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-02T18:52:34Z","receivedAt":"2026-02-02T18:52:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"William Hatfield <whatfield.git@gmail.com> writes:\n\n> This series introduces robust post-order (dependency-ordered) traversal to\n> `git submodule foreach` through three new flags: `--reverse-traversal`,\n> `--append-superproject`, and the shorthand `--reversive`. These options allow\n> users to process nested submodules before their parents and include the\n> superproject in the operation, enabling reliable automation for\n> dependency-ordered cleanup, builds, and deployment workflows.\n>\n> Highlights:\n> - Implements all new traversal flags in both the C helper and shell script.\n> - Provides a comprehensive test suite (t7425) that validates the new behaviors.\n> - Updates documentation to describe the new options and their intended use.\n>\n> These changes make submodule automation more powerful and flexible for advanced\n> and dependency-sensitive use cases.\n\nA few comments on the overall structure and concepts.\n\n * We do not want to see tests in a commit separate from the commit\n   that fixes.  The downside of such a layout of a series needs to\n   be understood.  An earlier step of a series may introduce a line\n   with \"test_expect_failure\" plus a short summary of what the piece\n   fixes, followed by a large amount of code to show exactly what is\n   being tested and expected outcome.  But when reading the step\n   that comes later that fixes the issue, readers will only see\n   changes from \"test_expect_failure\" to \"test_expect success\" with\n   most of the test to remind them what the issue was hidden away\n   from the view, in the post-context of patch hunk.  A commit that\n   has both the fix and the test that describes the expectation is\n   much easier to work with.\n\n * The name \"--reverse-traversal\" makes sense only to those who know\n   what the normal traversal order is, but it is far from clear what\n   the normal submodule traversal order is, because there is no\n   \"natural\" order to traverse.  Any of the combination of \"top\n   down/bottom up\" \"width first/depth first\" would make sense\n   depending on the application.  If you are doing \"bottom up\", for\n   example, please name it as such.\n\n * The name \"--append-superproject\" sounds strange.  It sounds as if\n   you are appending the superproject to something else, but I\n   suspect that is not what is happening; instead perhaps you are\n   leaving the traversal of the superproject at the end, or\n   something?\n\nThanks.\n"},{"id":"535012","messageId":"1F5D3AAF-3E5E-4AD0-A48B-90B9D545FB21@gmail.com","threadId":"64892","inReplyTo":"xmqqbji7yo3x.fsf@gitster.g","subject":"Re: [PATCH 0/5] submodule: add 'reversive' traversal options to foreach","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-02-02T21:02:16Z","receivedAt":"2026-02-02T21:02:32Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"\n> On Feb 2, 2026, at 1:52 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> \n> William Hatfield <whatfield.git@gmail.com> writes:\n> \n>> This series introduces robust post-order (dependency-ordered) traversal to\n>> `git submodule foreach` through three new flags: `--reverse-traversal`,\n>> `--append-superproject`, and the shorthand `--reversive`. These options allow\n>> users to process nested submodules before their parents and include the\n>> superproject in the operation, enabling reliable automation for\n>> dependency-ordered cleanup, builds, and deployment workflows.\n>> \n>> Highlights:\n>> - Implements all new traversal flags in both the C helper and shell script.\n>> - Provides a comprehensive test suite (t7425) that validates the new behaviors.\n>> - Updates documentation to describe the new options and their intended use.\n>> \n>> These changes make submodule automation more powerful and flexible for advanced\n>> and dependency-sensitive use cases.\n> \n> A few comments on the overall structure and concepts.\n> \n> * We do not want to see tests in a commit separate from the commit\n>   that fixes.  The downside of such a layout of a series needs to\n>   be understood.  An earlier step of a series may introduce a line\n>   with \"test_expect_failure\" plus a short summary of what the piece\n>   fixes, followed by a large amount of code to show exactly what is\n>   being tested and expected outcome.  But when reading the step\n>   that comes later that fixes the issue, readers will only see\n>   changes from \"test_expect_failure\" to \"test_expect success\" with\n>   most of the test to remind them what the issue was hidden away\n>   from the view, in the post-context of patch hunk.  A commit that\n>   has both the fix and the test that describes the expectation is\n>   much easier to work with.\n> \n> * The name \"--reverse-traversal\" makes sense only to those who know\n>   what the normal traversal order is, but it is far from clear what\n>   the normal submodule traversal order is, because there is no\n>   \"natural\" order to traverse.  Any of the combination of \"top\n>   down/bottom up\" \"width first/depth first\" would make sense\n>   depending on the application.  If you are doing \"bottom up\", for\n>   example, please name it as such.\n> \n> * The name \"--append-superproject\" sounds strange.  It sounds as if\n>   you are appending the superproject to something else, but I\n>   suspect that is not what is happening; instead perhaps you are\n>   leaving the traversal of the superproject at the end, or\n>   something?\n> \n> Thanks.\n\nThank you for the feedback, I will apply it in regard to test fixes in the same commit.\n\nDo you have any recommendation regarding names of these flags?\n\nDo you have a preference for: —postorder-traversal or —bottom-up-traversal?\n\nWhat about: —include-superpoject or —execute-in-superproject-last?"},{"id":"535014","messageId":"725FFEF5-90F5-4C6F-AACB-C372BBCC4C84@gmail.com","threadId":"64892","inReplyTo":"4710431.LvFx2qVVIh@piment-oiseau","subject":"Re: [PATCH 5/5] doc: document reversive traversal and related modes","fromName":"William Hatfield","fromEmail":"whatfield.git@gmail.com","sentAt":"2026-02-02T21:10:05Z","receivedAt":"2026-02-02T21:10:18Z","isPatch":true,"sender":{"key":"whatfield.git@gmail.com","avatar":null},"body":"\n> On Feb 1, 2026, at 4:03 AM, Jean-Noël AVILA <jn.avila@free.fr> wrote:\n> \n> On Saturday, 31 January 2026 22:43:09 CET William Hatfield wrote:\n>> Add documentation for the new --reverse-traversal, --append-superproject,\n>> and --reversive flags to git-submodule.adoc. These flags enable post-order\n>> traversal through nested submodule hierarchies, which is useful for\n>> cleanup operations and dependency-ordered processing.\n>> \n>> The flags only take effect when used with --recursive.\n>> \n>> Signed-off-by: William Hatfield <whatfield.git@gmail.com>\n> \n> Hello,\n> \n> git-submodule is being transitioned to `synopsis` style of markup.\n> See https://lore.kernel.org/git/\n> 05e68e28257cd450463d253abe9b2995759bdc10.1769462744.git.gitgitgadget@gmail.com/\n> \n> In the same move, there is some work on style consistency of the manual pages. \n> \n> Below are the remarks on what changed:\n> \n>> ---\n>> Documentation/git-submodule.adoc | 20 ++++++++++++++++++++\n>> 1 file changed, 20 insertions(+)\n>> \n>> diff --git a/Documentation/git-submodule.adoc b/Documentation/git-\n> submodule.adoc\n>> index 95beaee561..2be477952d 100644\n>> --- a/Documentation/git-submodule.adoc\n>> +++ b/Documentation/git-submodule.adoc\n>> @@ -437,6 +437,26 @@ options carefully.\n>> only in the submodules of the current repo, but also\n>> in any nested submodules inside those submodules (and so on).\n>> \n>> +--reverse-traversal::\n> \n> Now, options in description lists are backticked:\n> \n> `--reverse-traversal`::\n> \n>> + This option is only valid for the foreach command and requires\n>> + `--recursive`.  Process nested submodules in post-order (deepest\n>> + first) rather than the default pre-order.  This is useful for\n>> + cleanup operations where nested submodules must be processed\n>> + before their parents.\n> \n> Please start the description with the actual action of the option. Then, you \n> can add conditions, context, explanation:\n> \n> Process nested [...]. This option is only valid [...]. This is useful [...]\n> \n> Thanks\n\nThank you for the input. I will remedy the documentation as described."},{"id":"535017","messageId":"xmqqecn2yh0r.fsf@gitster.g","threadId":"64892","inReplyTo":"1F5D3AAF-3E5E-4AD0-A48B-90B9D545FB21@gmail.com","subject":"Re: [PATCH 0/5] submodule: add 'reversive' traversal options to foreach","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-02-02T21:25:40Z","receivedAt":"2026-02-02T21:25:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"William Hatfield <whatfield.git@gmail.com> writes:\n\n> Do you have any recommendation regarding names of these flags?\n\nNot really.  To be honest, I didn't even check to make sure what the\nbehaviour was that your \"--reverse\" was implementing ;-).\n\n> Do you have a preference for: —postorder-traversal or —bottom-up-traversal?\n\nIf all three kinds of *order makes sense to the submodule traversal,\nthen --{pre,in,post}order would make sense.  In other words, does\nthere exist a good answer to this question: \n\n    What does \"--inorder-traversal\" would do and when would it be\n    useful, as opposed to --preorder and --postorder?\n\nOtherwise, the distinction between --bottom-up vs --top-down may be\nsufficient to explain, and may explain the concept using more\nfamiliar terms to us non-mathematics types.\n\n> What about: —include-superpoject or —execute-in-superproject-last?\n\nDepends on what you are trying to tell the command to do with these\noptions.\n\nThe former sounds as if you are saying \"we usually do these things\nonly in submodules and never in superproject. But with this option I\nam telling you to do the same in superproject after you are done\ndoing them in all the submoudles\".\n\nOn the other hand, the latter sounds more like \"do these things in\neach and every repository (both submodules and the superproject),\nbut make sure the repository for superproject is handled after all\nothers.\"\n\nThanks.\n\n"}]}