sync: Deprecate fetch-submodules flag names

The names for flags --fetch-submodules / --no-fetch-submodules are
misleading, since they impact the full sync operation (fetch and
checkout), not just the fetching.

Introduce new flags --recurse-submodules / --no-recurse-submodules
and treat the old ones as deprecated aliases.

Change-Id: I78339a3e0496a855c222c1869b27b578507886a7
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/608881
Commit-Queue: Josef Malmstrom <Josef.Malmstrom@arm.com>
Reviewed-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Josef Malmstrom <Josef.Malmstrom@arm.com>
diff --git a/completion.zsh b/completion.zsh
index 8c0322f..704e584 100644
--- a/completion.zsh
+++ b/completion.zsh
@@ -322,8 +322,10 @@
         '--no-clone-bundle[Do not use clone bundle]' \
         '(-u --manifest-server-username)'{-u,--manifest-server-username=}'[Username for manifest server]:username:' \
         '(-p --manifest-server-password)'{-p,--manifest-server-password=}'[Password for manifest server]:password:' \
-        '--fetch-submodules[Fetch submodules]' \
-        '--no-fetch-submodules[Do not fetch submodules]' \
+        '--recurse-submodules[Sync submodules]' \
+        '--no-recurse-submodules[Do not sync submodules]' \
+        '--fetch-submodules[Deprecated alias for --recurse-submodules]' \
+        '--no-fetch-submodules[Deprecated alias for --no-recurse-submodules]' \
         '--use-superproject[Use superproject]' \
         '--no-use-superproject[Do not use superproject]' \
         '--tags[Sync tags]' \
diff --git a/man/repo-smartsync.1 b/man/repo-smartsync.1
index 07bab53..e3fddbc 100644
--- a/man/repo-smartsync.1
+++ b/man/repo-smartsync.1
@@ -1,5 +1,5 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man.
-.TH REPO "1" "June 2026" "repo smartsync" "Repo Manual"
+.TH REPO "1" "July 2026" "repo smartsync" "Repo Manual"
 .SH NAME
 repo \- repo smartsync - manual page for repo smartsync
 .SH SYNOPSIS
@@ -80,11 +80,11 @@
 \fB\-p\fR MANIFEST_SERVER_PASSWORD, \fB\-\-manifest\-server\-password\fR=\fI\,MANIFEST_SERVER_PASSWORD\/\fR
 password to authenticate with the manifest server
 .TP
-\fB\-\-fetch\-submodules\fR
-fetch submodules from server
+\fB\-\-recurse\-submodules\fR
+sync submodules from server
 .TP
-\fB\-\-no\-fetch\-submodules\fR
-don't fetch submodules from server
+\fB\-\-no\-recurse\-submodules\fR
+don't sync submodules from server
 .TP
 \fB\-\-use\-superproject\fR
 use the manifest superproject to sync projects; implies \fB\-c\fR
diff --git a/man/repo-sync.1 b/man/repo-sync.1
index 68d1e5e..66cd37a 100644
--- a/man/repo-sync.1
+++ b/man/repo-sync.1
@@ -80,11 +80,11 @@
 \fB\-p\fR MANIFEST_SERVER_PASSWORD, \fB\-\-manifest\-server\-password\fR=\fI\,MANIFEST_SERVER_PASSWORD\/\fR
 password to authenticate with the manifest server
 .TP
-\fB\-\-fetch\-submodules\fR
-fetch submodules from server
+\fB\-\-recurse\-submodules\fR
+sync submodules from server
 .TP
-\fB\-\-no\-fetch\-submodules\fR
-don't fetch submodules from server
+\fB\-\-no\-recurse\-submodules\fR
+don't sync submodules from server
 .TP
 \fB\-\-use\-superproject\fR
 use the manifest superproject to sync projects; implies \fB\-c\fR
@@ -215,10 +215,13 @@
 delivery network. This may be necessary if there are problems with the local
 Python HTTP client or proxy configuration, but the Git binary works.
 .PP
-The \fB\-\-fetch\-submodules\fR option enables fetching Git submodules of all projects
-from the server. The \fB\-\-no\-fetch\-submodules\fR option disables fetching Git
+The \fB\-\-recurse\-submodules\fR option enables syncing Git submodules of all projects
+from the server. The \fB\-\-no\-recurse\-submodules\fR option disables syncing Git
 submodules, even when a project has sync\-s="true" in the manifest.
 .PP
+The \fB\-\-fetch\-submodules\fR and \fB\-\-no\-fetch\-submodules\fR options are deprecated aliases
+for \fB\-\-recurse\-submodules\fR and \fB\-\-no\-recurse\-submodules\fR, respectively.
+.PP
 The \fB\-c\fR/\-\-current\-branch option can be used to only fetch objects that are on the
 branch specified by a project's revision.
 .PP
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 5a635fa..3fdb36a 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -378,9 +378,12 @@
 may be necessary if there are problems with the local Python
 HTTP client or proxy configuration, but the Git binary works.
 
-The --fetch-submodules option enables fetching Git submodules
-of all projects from the server. The --no-fetch-submodules option disables
-fetching Git submodules, even when a project has sync-s="true" in the manifest.
+The --recurse-submodules option enables syncing Git submodules of all projects
+from the server. The --no-recurse-submodules option disables syncing Git
+submodules, even when a project has sync-s="true" in the manifest.
+
+The --fetch-submodules and --no-fetch-submodules options are deprecated aliases
+for --recurse-submodules and --no-recurse-submodules, respectively.
 
 The -c/--current-branch option can be used to only fetch objects that
 are on the branch specified by a project's revision.
@@ -428,6 +431,15 @@
 
     _JOBS_WARN_THRESHOLD = 100
 
+    @staticmethod
+    def _deprecated_submodules_option(option, opt_str, _value, parser):
+        enabled = opt_str == "--fetch-submodules"
+        replacement = (
+            "--recurse-submodules" if enabled else "--no-recurse-submodules"
+        )
+        logger.warning("%s is deprecated; use %s instead", opt_str, replacement)
+        setattr(parser.values, option.dest, enabled)
+
     def _Options(self, p, show_smart=True):
         p.add_option(
             "--jobs-network",
@@ -570,15 +582,29 @@
             help="password to authenticate with the manifest server",
         )
         p.add_option(
-            "--fetch-submodules",
+            "--recurse-submodules",
             action="store_true",
-            help="fetch submodules from server",
+            help="sync submodules from server",
+        )
+        p.add_option(
+            "--no-recurse-submodules",
+            dest="recurse_submodules",
+            action="store_false",
+            help="don't sync submodules from server",
+        )
+        p.add_option(
+            "--fetch-submodules",
+            dest="recurse_submodules",
+            action="callback",
+            callback=self._deprecated_submodules_option,
+            help=optparse.SUPPRESS_HELP,
         )
         p.add_option(
             "--no-fetch-submodules",
-            dest="fetch_submodules",
-            action="store_false",
-            help="don't fetch submodules from server",
+            dest="recurse_submodules",
+            action="callback",
+            callback=self._deprecated_submodules_option,
+            help=optparse.SUPPRESS_HELP,
         )
         p.add_option(
             "--use-superproject",
@@ -749,7 +775,7 @@
         all_projects = self.GetProjects(
             args,
             missing_ok=True,
-            submodules_ok=opt.fetch_submodules,
+            submodules_ok=opt.recurse_submodules,
             manifest=manifest,
             all_manifests=not opt.this_manifest_only,
         )
@@ -1078,7 +1104,7 @@
                 all_projects = self.GetProjects(
                     args,
                     missing_ok=True,
-                    submodules_ok=opt.fetch_submodules,
+                    submodules_ok=opt.recurse_submodules,
                     manifest=manifest,
                     all_manifests=not opt.this_manifest_only,
                 )
@@ -2325,7 +2351,7 @@
         all_projects = self.GetProjects(
             args,
             missing_ok=True,
-            submodules_ok=opt.fetch_submodules,
+            submodules_ok=opt.recurse_submodules,
             manifest=manifest,
             all_manifests=not opt.this_manifest_only,
         )
@@ -2988,7 +3014,7 @@
                             project_list = self.GetProjects(
                                 args,
                                 missing_ok=True,
-                                submodules_ok=opt.fetch_submodules,
+                                submodules_ok=opt.recurse_submodules,
                                 manifest=manifest,
                                 all_manifests=not opt.this_manifest_only,
                             )
diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py
index 1fb462a..36ba13c 100644
--- a/tests/test_subcmds_sync.py
+++ b/tests/test_subcmds_sync.py
@@ -34,17 +34,40 @@
     "cli_args, expected",
     [
         ([], None),
+        (["--recurse-submodules"], True),
+        (["--no-recurse-submodules"], False),
         (["--fetch-submodules"], True),
         (["--no-fetch-submodules"], False),
     ],
 )
-def test_fetch_submodules_option(cli_args, expected):
-    """The fetch-submodules flags preserve an unset manifest-driven state."""
+def test_recurse_submodules_option(cli_args, expected):
+    """The submodule flags preserve an unset manifest-driven state."""
     cmd = sync.Sync()
 
     opts, _ = cmd.OptionParser.parse_args(cli_args)
 
-    assert opts.fetch_submodules is expected
+    assert opts.recurse_submodules is expected
+
+
+@pytest.mark.parametrize(
+    "old_flag, new_flag",
+    [
+        ("--fetch-submodules", "--recurse-submodules"),
+        ("--no-fetch-submodules", "--no-recurse-submodules"),
+    ],
+)
+def test_recurse_submodules_option_deprecation(old_flag, new_flag):
+    """The old submodule flags warn and direct users to their replacements."""
+    cmd = sync.Sync()
+
+    with mock.patch.object(sync.logger, "warning") as warning:
+        cmd.OptionParser.parse_args([old_flag])
+
+    warning.assert_called_once_with(
+        "%s is deprecated; use %s instead", old_flag, new_flag
+    )
+
+    assert old_flag not in cmd.OptionParser.format_help()
 
 
 @pytest.mark.parametrize(