control: tags -1 patch

> Even after the fix from https://bugs.debian.org/1102106, git ftbfs on
> s390x. Filing as a separate bug because this is a different failure.

The patch you took was the top-most in the fix series, you also need the
few that were applied before that one. That last one depends on the
previous changes. I took me a while to figure that out.

I collected them and verified that the package builds on amd64 and
s390x.
I can perform an NMU if you want.

Sebastian
diff -Nru git-2.49.0/debian/changelog git-2.49.0/debian/changelog
--- git-2.49.0/debian/changelog	2025-05-29 17:33:17.000000000 +0200
+++ git-2.49.0/debian/changelog	2025-06-06 18:07:16.000000000 +0200
@@ -1,3 +1,11 @@
+git (1:2.49.0-2.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Add a handfull of command line parsing patches for proper handling on big
+    endian machines. (Closes: #1106786).
+
+ -- Sebastian Andrzej Siewior <sebast...@breakpoint.cc>  Fri, 06 Jun 2025 18:07:16 +0200
+
 git (1:2.49.0-2) unstable; urgency=medium
 
   * debian/rules: remove overly strict check for license file
diff -Nru git-2.49.0/debian/patches/0001-parse-fix-off-by-one-for-minimum-signed-values.patch git-2.49.0/debian/patches/0001-parse-fix-off-by-one-for-minimum-signed-values.patch
--- git-2.49.0/debian/patches/0001-parse-fix-off-by-one-for-minimum-signed-values.patch	1970-01-01 01:00:00.000000000 +0100
+++ git-2.49.0/debian/patches/0001-parse-fix-off-by-one-for-minimum-signed-values.patch	2025-05-29 17:33:17.000000000 +0200
@@ -0,0 +1,39 @@
+From 8f282bdff0b49744b45d619075b59a5e8b596613 Mon Sep 17 00:00:00 2001
+From: Patrick Steinhardt <p...@pks.im>
+Date: Thu, 17 Apr 2025 12:49:36 +0200
+Subject: [PATCH 1/7] parse: fix off-by-one for minimum signed values
+
+We accept a maximum value in `git_parse_signed()` that restricts the
+range of accepted integers. As the intent is to pass `INT*_MAX` values
+here, this maximum doesn't only act as the upper bound, but also as the
+implicit lower bound of the accepted range.
+
+This lower bound is calculated by negating the maximum. But given that
+the maximum value of a signed integer with N bits is `2^(N-1)-1` whereas
+the minimum value is `-2^(N-1)` we have an off-by-one error in the lower
+bound.
+
+Fix this off-by-one error by using `-max - 1` as lower bound instead.
+
+Signed-off-by: Patrick Steinhardt <p...@pks.im>
+Signed-off-by: Junio C Hamano <gits...@pobox.com>
+---
+ parse.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/parse.c b/parse.c
+index 7a60a4f816..3c47448ca6 100644
+--- a/parse.c
++++ b/parse.c
+@@ -38,7 +38,7 @@ int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
+ 			errno = EINVAL;
+ 			return 0;
+ 		}
+-		if ((val < 0 && -max / factor > val) ||
++		if ((val < 0 && (-max - 1) / factor > val) ||
+ 		    (val > 0 && max / factor < val)) {
+ 			errno = ERANGE;
+ 			return 0;
+-- 
+2.39.5
+
diff -Nru git-2.49.0/debian/patches/0001-parse-options-detect-mismatches-in-integer-signedness.diff git-2.49.0/debian/patches/0001-parse-options-detect-mismatches-in-integer-signedness.diff
--- git-2.49.0/debian/patches/0001-parse-options-detect-mismatches-in-integer-signedness.diff	2025-05-29 17:25:56.000000000 +0200
+++ git-2.49.0/debian/patches/0001-parse-options-detect-mismatches-in-integer-signedness.diff	1970-01-01 01:00:00.000000000 +0100
@@ -1,161 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Patrick Steinhardt <p...@pks.im>
-Date: Thu, 17 Apr 2025 12:49:42 +0200
-Subject: parse-options: detect mismatches in integer signedness
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-commit 791aeddfa2fdb9e830e24c50c97bb5e8bf3613e6 upstream.
-
-It was reported that "t5620-backfill.sh" fails on s390x and sparc64 in a
-test that exercises the "--min-batch-size" command line option. The
-symptom was that the option didn't seem to have an effect: we didn't
-fetch objects with a batch size of 20, but instead fetched all objects
-at once.
-
-As it turns out, the root cause is that `--min-batch-size` uses
-`OPT_INTEGER()` to parse the command line option. While this macro
-expects the caller to pass a pointer to an integer, we instead pass a
-pointer to a `size_t`. This coincidentally works on most platforms, but
-it breaks apart on the mentioned platforms because they are big endian.
-
-This issue isn't specific to git-backfill(1): there are a couple of
-other places where we have the same type confusion going on. This
-indicates that the issue really is the interface that the parse-options
-subsystem provides -- it is simply too easy to get this wrong as there
-isn't any kind of compiler warning, and things just work on the most
-common systems.
-
-Address the systemic issue by introducing two new build asserts
-`BARF_UNLESS_SIGNED()` and `BARF_UNLESS_UNSIGNED()`. As the names
-already hint at, those macros will cause a compiler error when passed a
-value that is not signed or unsigned, respectively.
-
-Adapt `OPT_INTEGER()`, `OPT_UNSIGNED()` as well as `OPT_MAGNITUDE()` to
-use those asserts. This uncovers a small set of sites where we indeed
-have the same bug as in git-backfill(1). Adapt all of them to use the
-correct option.
-
-Reported-by: Todd Zullinger <t...@pobox.com>
-Reported-by: John Paul Adrian Glaubitz <glaub...@physik.fu-berlin.de>
-Helped-by: SZEDER Gábor <szeder....@gmail.com>
-Helped-by: Jeff King <p...@peff.net>
-Signed-off-by: Patrick Steinhardt <p...@pks.im>
-Signed-off-by: Junio C Hamano <gits...@pobox.com>
-[jn: backport by using OPT_MAGNITUDE instead of OPT_UNSIGNED]
-Signed-off-by: Jonathan Nieder <jrnie...@gmail.com>
----
- apply.c            | 4 ++--
- builtin/backfill.c | 4 ++--
- builtin/column.c   | 2 +-
- builtin/grep.c     | 4 ++--
- git-compat-util.h  | 7 +++++++
- parse-options.h    | 4 ++--
- 6 files changed, 16 insertions(+), 9 deletions(-)
-
-diff --git a/apply.c b/apply.c
-index f274a379487..954c5749233 100644
---- a/apply.c
-+++ b/apply.c
-@@ -5123,8 +5123,8 @@ int apply_parse_options(int argc, const char **argv,
- 		/* Think twice before adding "--nul" synonym to this */
- 		OPT_SET_INT('z', NULL, &state->line_termination,
- 			N_("paths are separated with NUL character"), '\0'),
--		OPT_INTEGER('C', NULL, &state->p_context,
--				N_("ensure at least <n> lines of context match")),
-+		OPT_MAGNITUDE('C', NULL, &state->p_context,
-+			      N_("ensure at least <n> lines of context match")),
- 		OPT_CALLBACK(0, "whitespace", state, N_("action"),
- 			N_("detect new or modified lines that have whitespace errors"),
- 			apply_option_parse_whitespace),
-diff --git a/builtin/backfill.c b/builtin/backfill.c
-index 33e1ea2f84f..a6069fb783c 100644
---- a/builtin/backfill.c
-+++ b/builtin/backfill.c
-@@ -123,8 +123,8 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
- 		.sparse = 0,
- 	};
- 	struct option options[] = {
--		OPT_INTEGER(0, "min-batch-size", &ctx.min_batch_size,
--			    N_("Minimum number of objects to request at a time")),
-+		OPT_MAGNITUDE(0, "min-batch-size", &ctx.min_batch_size,
-+			      N_("Minimum number of objects to request at a time")),
- 		OPT_BOOL(0, "sparse", &ctx.sparse,
- 			 N_("Restrict the missing objects to the current sparse-checkout")),
- 		OPT_END(),
-diff --git a/builtin/column.c b/builtin/column.c
-index 50314cc2559..290194e92e6 100644
---- a/builtin/column.c
-+++ b/builtin/column.c
-@@ -31,7 +31,7 @@ int cmd_column(int argc,
- 	struct option options[] = {
- 		OPT_STRING(0, "command", &real_command, N_("name"), N_("lookup config vars")),
- 		OPT_COLUMN(0, "mode", &colopts, N_("layout to use")),
--		OPT_INTEGER(0, "raw-mode", &colopts, N_("layout to use")),
-+		OPT_MAGNITUDE(0, "raw-mode", &colopts, N_("layout to use")),
- 		OPT_INTEGER(0, "width", &copts.width, N_("maximum width")),
- 		OPT_STRING(0, "indent", &copts.indent, N_("string"), N_("padding space on left border")),
- 		OPT_STRING(0, "nl", &copts.nl, N_("string"), N_("padding space on right border")),
-diff --git a/builtin/grep.c b/builtin/grep.c
-index d1427290f77..d1073c9e6e5 100644
---- a/builtin/grep.c
-+++ b/builtin/grep.c
-@@ -983,9 +983,9 @@ int cmd_grep(int argc,
- 		OPT_CALLBACK('C', "context", &opt, N_("n"),
- 			N_("show <n> context lines before and after matches"),
- 			context_callback),
--		OPT_INTEGER('B', "before-context", &opt.pre_context,
-+		OPT_MAGNITUDE('B', "before-context", &opt.pre_context,
- 			N_("show <n> context lines before matches")),
--		OPT_INTEGER('A', "after-context", &opt.post_context,
-+		OPT_MAGNITUDE('A', "after-context", &opt.post_context,
- 			N_("show <n> context lines after matches")),
- 		OPT_INTEGER(0, "threads", &num_threads,
- 			N_("use <n> worker threads")),
-diff --git a/git-compat-util.h b/git-compat-util.h
-index e123288e8f1..18573f7be86 100644
---- a/git-compat-util.h
-+++ b/git-compat-util.h
-@@ -110,12 +110,19 @@ DISABLE_WARNING(-Wsign-compare)
- # define BARF_UNLESS_COPYABLE(dst, src) \
- 	BUILD_ASSERT_OR_ZERO(__builtin_types_compatible_p(__typeof__(*(dst)), \
- 							  __typeof__(*(src))))
-+
-+# define BARF_UNLESS_SIGNED(var)   BUILD_ASSERT_OR_ZERO(((__typeof__(var)) -1) < 0)
-+# define BARF_UNLESS_UNSIGNED(var) BUILD_ASSERT_OR_ZERO(((__typeof__(var)) -1) > 0)
- #else
- # define BARF_UNLESS_AN_ARRAY(arr) 0
- # define BARF_UNLESS_COPYABLE(dst, src) \
- 	BUILD_ASSERT_OR_ZERO(0 ? ((*(dst) = *(src)), 0) : \
- 				 sizeof(*(dst)) == sizeof(*(src)))
-+
-+# define BARF_UNLESS_SIGNED(var)   0
-+# define BARF_UNLESS_UNSIGNED(var) 0
- #endif
-+
- /*
-  * ARRAY_SIZE - get the number of elements in a visible array
-  * @x: the array whose size you want.
-diff --git a/parse-options.h b/parse-options.h
-index 997ffbee805..bf14c9962a9 100644
---- a/parse-options.h
-+++ b/parse-options.h
-@@ -213,7 +213,7 @@ struct option {
- 	.type = OPTION_INTEGER, \
- 	.short_name = (s), \
- 	.long_name = (l), \
--	.value = (v), \
-+	.value = (v) + BARF_UNLESS_SIGNED(*(v)), \
- 	.argh = N_("n"), \
- 	.help = (h), \
- 	.flags = (f), \
-@@ -274,7 +274,7 @@ struct option {
- 	.type = OPTION_MAGNITUDE, \
- 	.short_name = (s), \
- 	.long_name = (l), \
--	.value = (v), \
-+	.value = (v) + BARF_UNLESS_UNSIGNED(*(v)), \
- 	.argh = N_("n"), \
- 	.help = (h), \
- 	.flags = PARSE_OPT_NONEG, \
diff -Nru git-2.49.0/debian/patches/0002-global-use-designated-initializers-for-options.patch git-2.49.0/debian/patches/0002-global-use-designated-initializers-for-options.patch
--- git-2.49.0/debian/patches/0002-global-use-designated-initializers-for-options.patch	1970-01-01 01:00:00.000000000 +0100
+++ git-2.49.0/debian/patches/0002-global-use-designated-initializers-for-options.patch	2025-05-29 17:33:17.000000000 +0200
@@ -0,0 +1,1008 @@
+From d012ceb5f3351af0589a0c82b07059bce8c7b24b Mon Sep 17 00:00:00 2001
+From: Patrick Steinhardt <p...@pks.im>
+Date: Thu, 17 Apr 2025 12:49:37 +0200
+Subject: [PATCH 2/7] global: use designated initializers for options
+
+While we expose macros for most of our different option types understood
+by the "parse-options" subsystem, not every combination of fields that
+has one as that would otherwise quickly lead to an explosion of macros.
+Instead, we just initialize structures manually for those variants of
+fields that don't have a macro.
+
+Callsites that open-code these structure initialization don't use
+designated initializers though and instead just provide values for each
+of the fields that they want to initialize. This has three significant
+downsides:
+
+  - Callsites need to specify all values up to the last field that they
+    care about. This often includes fields that should simply be left at
+    their default zero-initialized state, which adds distraction.
+
+  - Any reader not deeply familiar with the layout of the structure
+    has a hard time figuring out what the respective initializers mean.
+
+  - Reordering or introducing new fields in the middle of the structure
+    is impossible without adapting all callsites.
+
+Convert all sites to instead use designated initializers, which we have
+started using in our codebase quite a while ago. This allows us to skip
+any default-initialized fields, gives the reader context by specifying
+the field names and allows us to reorder or introduce new fields where
+we want to.
+
+Signed-off-by: Patrick Steinhardt <p...@pks.im>
+Signed-off-by: Junio C Hamano <gits...@pobox.com>
+---
+ archive.c                     |  35 ++++++---
+ builtin/am.c                  |  28 +++++---
+ builtin/clone.c               |  13 +++-
+ builtin/commit-tree.c         |  12 +++-
+ builtin/commit.c              |  62 ++++++++++++----
+ builtin/config.c              |  13 +++-
+ builtin/describe.c            |  24 +++++--
+ builtin/fetch.c               |  10 ++-
+ builtin/fmt-merge-msg.c       |  25 +++++--
+ builtin/gc.c                  |  12 +++-
+ builtin/grep.c                |  14 ++--
+ builtin/init-db.c             |  13 ++--
+ builtin/ls-remote.c           |  11 ++-
+ builtin/merge.c               |  37 +++++++---
+ builtin/read-tree.c           |  11 ++-
+ builtin/rebase.c              |  25 +++++--
+ builtin/revert.c              |  12 +++-
+ builtin/show-branch.c         |  12 +++-
+ builtin/tag.c                 |  23 ++++--
+ builtin/update-index.c        | 131 +++++++++++++++++++++++-----------
+ builtin/write-tree.c          |  12 ++--
+ diff.c                        |  13 ++--
+ ref-filter.h                  |  15 ++--
+ t/helper/test-parse-options.c |  38 +++++++---
+ 24 files changed, 443 insertions(+), 158 deletions(-)
+
+diff --git a/archive.c b/archive.c
+index 8be4e7ac8d..67bba3cd30 100644
+--- a/archive.c
++++ b/archive.c
+@@ -650,20 +650,37 @@ static int parse_archive_args(int argc, const char **argv,
+ 		OPT_STRING(0, "format", &format, N_("fmt"), N_("archive format")),
+ 		OPT_STRING(0, "prefix", &base, N_("prefix"),
+ 			N_("prepend prefix to each pathname in the archive")),
+-		{ OPTION_CALLBACK, 0, "add-file", args, N_("file"),
+-		  N_("add untracked file to archive"), 0, add_file_cb,
+-		  (intptr_t)&base },
+-		{ OPTION_CALLBACK, 0, "add-virtual-file", args,
+-		  N_("path:content"), N_("add untracked file to archive"), 0,
+-		  add_file_cb, (intptr_t)&base },
++		{
++			.type = OPTION_CALLBACK,
++			.long_name = "add-file",
++			.value = args,
++			.argh = N_("file"),
++			.help = N_("add untracked file to archive"),
++			.callback = add_file_cb,
++			.defval = (intptr_t) &base,
++		},
++		{
++			.type = OPTION_CALLBACK,
++			.long_name = "add-virtual-file",
++			.value = args,
++			.argh = N_("path:content"),
++			.help = N_("add untracked file to archive"),
++			.callback = add_file_cb,
++			.defval = (intptr_t) &base,
++		},
+ 		OPT_STRING('o', "output", &output, N_("file"),
+ 			N_("write the archive to this file")),
+ 		OPT_BOOL(0, "worktree-attributes", &worktree_attributes,
+ 			N_("read .gitattributes in working directory")),
+ 		OPT__VERBOSE(&verbose, N_("report archived files on stderr")),
+-		{ OPTION_STRING, 0, "mtime", &mtime_option, N_("time"),
+-		  N_("set modification time of archive entries"),
+-		  PARSE_OPT_NONEG },
++		{
++			.type = OPTION_STRING,
++			.long_name = "mtime",
++			.value = &mtime_option,
++			.argh = N_("time"),
++			.help = N_("set modification time of archive entries"),
++			.flags = PARSE_OPT_NONEG,
++		},
+ 		OPT_NUMBER_CALLBACK(&compression_level,
+ 			N_("set compression level"), number_callback),
+ 		OPT_GROUP(""),
+diff --git a/builtin/am.c b/builtin/am.c
+index 3b61bd4c33..4afb519830 100644
+--- a/builtin/am.c
++++ b/builtin/am.c
+@@ -2400,11 +2400,16 @@ int cmd_am(int argc,
+ 		OPT_CMDMODE(0, "quit", &resume_mode,
+ 			N_("abort the patching operation but keep HEAD where it is"),
+ 			RESUME_QUIT),
+-		{ OPTION_CALLBACK, 0, "show-current-patch", &resume_mode,
+-		  "(diff|raw)",
+-		  N_("show the patch being applied"),
+-		  PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
+-		  parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },
++		{
++			.type = OPTION_CALLBACK,
++			.long_name = "show-current-patch",
++			.value = &resume_mode,
++			.argh = "(diff|raw)",
++			.help = N_("show the patch being applied"),
++			.flags = PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
++			.callback = parse_opt_show_current_patch,
++			.defval = RESUME_SHOW_PATCH_RAW,
++		},
+ 		OPT_CMDMODE(0, "retry", &resume_mode,
+ 			N_("try to apply current patch again"),
+ 			RESUME_APPLY),
+@@ -2417,9 +2422,16 @@ int cmd_am(int argc,
+ 		OPT_BOOL(0, "ignore-date", &state.ignore_date,
+ 			N_("use current timestamp for author date")),
+ 		OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),
+-		{ OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, N_("key-id"),
+-		  N_("GPG-sign commits"),
+-		  PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'S',
++			.long_name = "gpg-sign",
++			.value = &state.sign_commit,
++			.argh = N_("key-id"),
++			.help = N_("GPG-sign commits"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t) "",
++		},
+ 		OPT_CALLBACK_F(0, "empty", &state.empty_type, "(stop|drop|keep)",
+ 		  N_("how to handle empty patches"),
+ 		  PARSE_OPT_NONEG, am_option_parse_empty),
+diff --git a/builtin/clone.c b/builtin/clone.c
+index 88276e5b7a..9c3547f41e 100644
+--- a/builtin/clone.c
++++ b/builtin/clone.c
+@@ -930,9 +930,16 @@ int cmd_clone(int argc,
+ 			 N_("don't use local hardlinks, always copy")),
+ 		OPT_BOOL('s', "shared", &option_shared,
+ 			 N_("setup as shared repository")),
+-		{ OPTION_CALLBACK, 0, "recurse-submodules", &option_recurse_submodules,
+-		  N_("pathspec"), N_("initialize submodules in the clone"),
+-		  PARSE_OPT_OPTARG, recurse_submodules_cb, (intptr_t)"." },
++		{
++			.type = OPTION_CALLBACK,
++			.long_name = "recurse-submodules",
++			.value = &option_recurse_submodules,
++			.argh = N_("pathspec"),
++			.help = N_("initialize submodules in the clone"),
++			.flags = PARSE_OPT_OPTARG,
++			.callback = recurse_submodules_cb,
++			.defval = (intptr_t)".",
++		},
+ 		OPT_ALIAS(0, "recursive", "recurse-submodules"),
+ 		OPT_INTEGER('j', "jobs", &max_jobs,
+ 			    N_("number of submodules cloned in parallel")),
+diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c
+index 38457600a4..c787133d00 100644
+--- a/builtin/commit-tree.c
++++ b/builtin/commit-tree.c
+@@ -111,8 +111,16 @@ int cmd_commit_tree(int argc,
+ 		OPT_CALLBACK_F('F', NULL, &buffer, N_("file"),
+ 			N_("read commit log message from file"), PARSE_OPT_NONEG,
+ 			parse_file_arg_callback),
+-		{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
+-			N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'S',
++			.long_name = "gpg-sign",
++			.value = &sign_commit,
++			.argh = N_("key-id"),
++			.help = N_("GPG sign commit"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t) "",
++		},
+ 		OPT_END()
+ 	};
+ 	int ret;
+diff --git a/builtin/commit.c b/builtin/commit.c
+index 2f45968222..66bd91fd52 100644
+--- a/builtin/commit.c
++++ b/builtin/commit.c
+@@ -1542,17 +1542,34 @@ struct repository *repo UNUSED)
+ 			    STATUS_FORMAT_LONG),
+ 		OPT_BOOL('z', "null", &s.null_termination,
+ 			 N_("terminate entries with NUL")),
+-		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg,
+-		  N_("mode"),
+-		  N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
+-		  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
+-		{ OPTION_STRING, 0, "ignored", &ignored_arg,
+-		  N_("mode"),
+-		  N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"),
+-		  PARSE_OPT_OPTARG, NULL, (intptr_t)"traditional" },
+-		{ OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, N_("when"),
+-		  N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
+-		  PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'u',
++			.long_name = "untracked-files",
++			.value = &untracked_files_arg,
++			.argh = N_("mode"),
++			.help = N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t)"all",
++		},
++		{
++			.type = OPTION_STRING,
++			.long_name = "ignored",
++			.value = &ignored_arg,
++			.argh = N_("mode"),
++			.help = N_("show ignored files, optional modes: traditional, matching, no. (Default: traditional)"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t)"traditional",
++		},
++		{
++			.type = OPTION_STRING,
++			.long_name = "ignore-submodules",
++			.value = &ignore_submodule_arg,
++			.argh = N_("when"),
++			.help = N_("ignore changes to submodules, optional when: all, dirty, untracked. (Default: all)"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t)"all",
++		},
+ 		OPT_COLUMN(0, "column", &s.colopts, N_("list untracked files in columns")),
+ 		OPT_BOOL(0, "no-renames", &no_renames, N_("do not detect renames")),
+ 		OPT_CALLBACK_F('M', "find-renames", &rename_score_arg,
+@@ -1688,8 +1705,16 @@ int cmd_commit(int argc,
+ 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
+ 		OPT_CLEANUP(&cleanup_arg),
+ 		OPT_BOOL(0, "status", &include_status, N_("include status in commit message template")),
+-		{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
+-		  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'S',
++			.long_name = "gpg-sign",
++			.value = &sign_commit,
++			.argh = N_("key-id"),
++			.help = N_("GPG sign commit"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t) "",
++		},
+ 		/* end commit message options */
+ 
+ 		OPT_GROUP(N_("Commit contents options")),
+@@ -1714,7 +1739,16 @@ int cmd_commit(int argc,
+ 			 N_("terminate entries with NUL")),
+ 		OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
+ 		OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
+-		{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'u',
++			.long_name = "untracked-files",
++			.value = &untracked_files_arg,
++			.argh = N_("mode"),
++			.help = N_("show untracked files, optional modes: all, normal, no. (Default: all)"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t)"all",
++		},
+ 		OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
+ 		OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
+ 		/* end commit contents options */
+diff --git a/builtin/config.c b/builtin/config.c
+index 53a90094e3..f70d635477 100644
+--- a/builtin/config.c
++++ b/builtin/config.c
+@@ -131,9 +131,16 @@ struct config_display_options {
+ #define TYPE_COLOR		6
+ #define TYPE_BOOL_OR_STR	7
+ 
+-#define OPT_CALLBACK_VALUE(s, l, v, h, i) \
+-	{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
+-	PARSE_OPT_NONEG, option_parse_type, (i) }
++#define OPT_CALLBACK_VALUE(s, l, v, h, i) { \
++	.type = OPTION_CALLBACK, \
++	.short_name = (s), \
++	.long_name = (l), \
++	.value = (v), \
++	.help = (h), \
++	.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG, \
++	.callback = option_parse_type, \
++	.defval = (i), \
++}
+ 
+ static int option_parse_type(const struct option *opt, const char *arg,
+ 			     int unset)
+diff --git a/builtin/describe.c b/builtin/describe.c
+index e2e73f3d75..2da9f4fed0 100644
+--- a/builtin/describe.c
++++ b/builtin/describe.c
+@@ -601,12 +601,24 @@ int cmd_describe(int argc,
+ 			   N_("do not consider tags matching <pattern>")),
+ 		OPT_BOOL(0, "always",        &always,
+ 			N_("show abbreviated commit object as fallback")),
+-		{OPTION_STRING, 0, "dirty",  &dirty, N_("mark"),
+-			N_("append <mark> on dirty working tree (default: \"-dirty\")"),
+-			PARSE_OPT_OPTARG, NULL, (intptr_t) "-dirty"},
+-		{OPTION_STRING, 0, "broken",  &broken, N_("mark"),
+-			N_("append <mark> on broken working tree (default: \"-broken\")"),
+-			PARSE_OPT_OPTARG, NULL, (intptr_t) "-broken"},
++		{
++			.type = OPTION_STRING,
++			.long_name = "dirty",
++			.value = &dirty,
++			.argh = N_("mark"),
++			.help = N_("append <mark> on dirty working tree (default: \"-dirty\")"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t) "-dirty",
++		},
++		{
++			.type = OPTION_STRING,
++			.long_name = "broken",
++			.value = &broken,
++			.argh = N_("mark"),
++			.help = N_("append <mark> on broken working tree (default: \"-broken\")"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t) "-broken",
++		},
+ 		OPT_END(),
+ 	};
+ 
+diff --git a/builtin/fetch.c b/builtin/fetch.c
+index 02af505469..3a5159d9e6 100644
+--- a/builtin/fetch.c
++++ b/builtin/fetch.c
+@@ -2359,8 +2359,14 @@ int cmd_fetch(int argc,
+ 		OPT_SET_INT_F(0, "refetch", &refetch,
+ 			      N_("re-fetch without negotiating common commits"),
+ 			      1, PARSE_OPT_NONEG),
+-		{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
+-			   N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
++		{
++			.type = OPTION_STRING,
++			.long_name = "submodule-prefix",
++			.value = &submodule_prefix,
++			.argh = N_("dir"),
++			.help = N_("prepend this to submodule path output"),
++			.flags = PARSE_OPT_HIDDEN,
++		},
+ 		OPT_CALLBACK_F(0, "recurse-submodules-default",
+ 			   &recurse_submodules_default, N_("on-demand"),
+ 			   N_("default for recursive fetching of submodules "
+diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
+index 189cd1096a..240cdb474b 100644
+--- a/builtin/fmt-merge-msg.c
++++ b/builtin/fmt-merge-msg.c
+@@ -20,13 +20,24 @@ int cmd_fmt_merge_msg(int argc,
+ 	char *into_name = NULL;
+ 	int shortlog_len = -1;
+ 	struct option options[] = {
+-		{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
+-		  N_("populate log with at most <n> entries from shortlog"),
+-		  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
+-		{ OPTION_INTEGER, 0, "summary", &shortlog_len, N_("n"),
+-		  N_("alias for --log (deprecated)"),
+-		  PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN, NULL,
+-		  DEFAULT_MERGE_LOG_LEN },
++		{
++			.type = OPTION_INTEGER,
++			.long_name = "log",
++			.value = &shortlog_len,
++			.argh = N_("n"),
++			.help = N_("populate log with at most <n> entries from shortlog"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = DEFAULT_MERGE_LOG_LEN,
++		},
++		{
++			.type = OPTION_INTEGER,
++			.long_name = "summary",
++			.value = &shortlog_len,
++			.argh = N_("n"),
++			.help = N_("alias for --log (deprecated)"),
++			.flags = PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN,
++			.defval = DEFAULT_MERGE_LOG_LEN,
++		},
+ 		OPT_STRING('m', "message", &message, N_("text"),
+ 			N_("use <text> as start of message")),
+ 		OPT_STRING(0, "into-name", &into_name, N_("name"),
+diff --git a/builtin/gc.c b/builtin/gc.c
+index 99431fd467..6707a26bc6 100644
+--- a/builtin/gc.c
++++ b/builtin/gc.c
+@@ -699,9 +699,15 @@ struct repository *repo UNUSED)
+ 	int ret;
+ 	struct option builtin_gc_options[] = {
+ 		OPT__QUIET(&quiet, N_("suppress progress reporting")),
+-		{ OPTION_STRING, 0, "prune", &prune_expire_arg, N_("date"),
+-			N_("prune unreferenced objects"),
+-			PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire_arg },
++		{
++			.type = OPTION_STRING,
++			.long_name = "prune",
++			.value = &prune_expire_arg,
++			.argh = N_("date"),
++			.help = N_("prune unreferenced objects"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t)prune_expire_arg,
++		},
+ 		OPT_BOOL(0, "cruft", &cfg.cruft_packs, N_("pack unreferenced objects separately")),
+ 		OPT_MAGNITUDE(0, "max-cruft-size", &cfg.max_cruft_size,
+ 			      N_("with --cruft, limit the size of new cruft packs")),
+diff --git a/builtin/grep.c b/builtin/grep.c
+index d1427290f7..c4869733e1 100644
+--- a/builtin/grep.c
++++ b/builtin/grep.c
+@@ -1017,10 +1017,16 @@ int cmd_grep(int argc,
+ 		OPT_BOOL(0, "all-match", &opt.all_match,
+ 			N_("show only matches from files that match all patterns")),
+ 		OPT_GROUP(""),
+-		{ OPTION_STRING, 'O', "open-files-in-pager", &show_in_pager,
+-			N_("pager"), N_("show matching files in the pager"),
+-			PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,
+-			NULL, (intptr_t)default_pager },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'O',
++			.long_name = "open-files-in-pager",
++			.value = &show_in_pager,
++			.argh = N_("pager"),
++			.help = N_("show matching files in the pager"),
++			.flags = PARSE_OPT_OPTARG | PARSE_OPT_NOCOMPLETE,
++			.defval = (intptr_t)default_pager,
++		},
+ 		OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored,
+ 			   N_("allow calling of grep(1) (ignored by this build)"),
+ 			   PARSE_OPT_NOCOMPLETE),
+diff --git a/builtin/init-db.c b/builtin/init-db.c
+index 196dccdd77..4a950e44d8 100644
+--- a/builtin/init-db.c
++++ b/builtin/init-db.c
+@@ -93,10 +93,15 @@ int cmd_init_db(int argc,
+ 				N_("directory from which templates will be used")),
+ 		OPT_SET_INT(0, "bare", &is_bare_repository_cfg,
+ 				N_("create a bare repository"), 1),
+-		{ OPTION_CALLBACK, 0, "shared", &init_shared_repository,
+-			N_("permissions"),
+-			N_("specify that the git repository is to be shared amongst several users"),
+-			PARSE_OPT_OPTARG | PARSE_OPT_NONEG, shared_callback, 0},
++		{
++			.type = OPTION_CALLBACK,
++			.long_name = "shared",
++			.value = &init_shared_repository,
++			.argh = N_("permissions"),
++			.help = N_("specify that the git repository is to be shared amongst several users"),
++			.flags = PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
++			.callback = shared_callback
++		},
+ 		OPT_BIT('q', "quiet", &flags, N_("be quiet"), INIT_DB_QUIET),
+ 		OPT_STRING(0, "separate-git-dir", &real_git_dir, N_("gitdir"),
+ 			   N_("separate git dir from working tree")),
+diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
+index 42f34e1236..01a4d4daa1 100644
+--- a/builtin/ls-remote.c
++++ b/builtin/ls-remote.c
+@@ -67,9 +67,14 @@ int cmd_ls_remote(int argc,
+ 		OPT__QUIET(&quiet, N_("do not print remote URL")),
+ 		OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"),
+ 			   N_("path of git-upload-pack on the remote host")),
+-		{ OPTION_STRING, 0, "exec", &uploadpack, N_("exec"),
+-			   N_("path of git-upload-pack on the remote host"),
+-			   PARSE_OPT_HIDDEN },
++		{
++			.type = OPTION_STRING,
++			.long_name = "exec",
++			.value = &uploadpack,
++			.argh = N_("exec"),
++			.help = N_("path of git-upload-pack on the remote host"),
++			.flags = PARSE_OPT_HIDDEN,
++		},
+ 		OPT_BIT('t', "tags", &flags, N_("limit to tags"), REF_TAGS),
+ 		OPT_BIT('b', "branches", &flags, N_("limit to branches"), REF_BRANCHES),
+ 		OPT_BIT_F('h', "heads", &flags,
+diff --git a/builtin/merge.c b/builtin/merge.c
+index ba9faf126a..21787d4516 100644
+--- a/builtin/merge.c
++++ b/builtin/merge.c
+@@ -250,9 +250,15 @@ static struct option builtin_merge_options[] = {
+ 	OPT_BOOL(0, "stat", &show_diffstat,
+ 		N_("show a diffstat at the end of the merge")),
+ 	OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
+-	{ OPTION_INTEGER, 0, "log", &shortlog_len, N_("n"),
+-	  N_("add (at most <n>) entries from shortlog to merge commit message"),
+-	  PARSE_OPT_OPTARG, NULL, DEFAULT_MERGE_LOG_LEN },
++	{
++		.type = OPTION_INTEGER,
++		.long_name = "log",
++		.value = &shortlog_len,
++		.argh = N_("n"),
++		.help = N_("add (at most <n>) entries from shortlog to merge commit message"),
++		.flags = PARSE_OPT_OPTARG,
++		.defval = DEFAULT_MERGE_LOG_LEN,
++	},
+ 	OPT_BOOL(0, "squash", &squash,
+ 		N_("create a single commit instead of doing a merge")),
+ 	OPT_BOOL(0, "commit", &option_commit,
+@@ -274,9 +280,16 @@ static struct option builtin_merge_options[] = {
+ 	OPT_CALLBACK('m', "message", &merge_msg, N_("message"),
+ 		N_("merge commit message (for a non-fast-forward merge)"),
+ 		option_parse_message),
+-	{ OPTION_LOWLEVEL_CALLBACK, 'F', "file", &merge_msg, N_("path"),
+-		N_("read message from file"), PARSE_OPT_NONEG,
+-		NULL, 0, option_read_message },
++	{
++		.type = OPTION_LOWLEVEL_CALLBACK,
++		.short_name = 'F',
++		.long_name = "file",
++		.value = &merge_msg,
++		.argh = N_("path"),
++		.help = N_("read message from file"),
++		.flags = PARSE_OPT_NONEG,
++		.ll_callback = option_read_message,
++	},
+ 	OPT_STRING(0, "into-name", &into_name, N_("name"),
+ 		   N_("use <name> instead of the real target")),
+ 	OPT__VERBOSITY(&verbosity),
+@@ -289,8 +302,16 @@ static struct option builtin_merge_options[] = {
+ 	OPT_BOOL(0, "allow-unrelated-histories", &allow_unrelated_histories,
+ 		 N_("allow merging unrelated histories")),
+ 	OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
+-	{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
+-	  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
++	{
++		.type = OPTION_STRING,
++		.short_name = 'S',
++		.long_name = "gpg-sign",
++		.value = &sign_commit,
++		.argh = N_("key-id"),
++		.help = N_("GPG sign commit"),
++		.flags = PARSE_OPT_OPTARG,
++		.defval = (intptr_t) "",
++	},
+ 	OPT_AUTOSTASH(&autostash),
+ 	OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
+ 	OPT_BOOL(0, "signoff", &signoff, N_("add a Signed-off-by trailer")),
+diff --git a/builtin/read-tree.c b/builtin/read-tree.c
+index d2a807a828..a8f352f7cd 100644
+--- a/builtin/read-tree.c
++++ b/builtin/read-tree.c
+@@ -135,9 +135,14 @@ int cmd_read_tree(int argc,
+ 			 N_("3-way merge in presence of adds and removes")),
+ 		OPT_BOOL(0, "reset", &opts.reset,
+ 			 N_("same as -m, but discard unmerged entries")),
+-		{ OPTION_STRING, 0, "prefix", &opts.prefix, N_("<subdirectory>/"),
+-		  N_("read the tree into the index under <subdirectory>/"),
+-		  PARSE_OPT_NONEG },
++		{
++			.type = OPTION_STRING,
++			.long_name = "prefix",
++			.value = &opts.prefix,
++			.argh = N_("<subdirectory>/"),
++			.help = N_("read the tree into the index under <subdirectory>/"),
++			.flags = PARSE_OPT_NONEG,
++		},
+ 		OPT_BOOL('u', NULL, &opts.update,
+ 			 N_("update working tree with merge result")),
+ 		OPT_CALLBACK_F(0, "exclude-per-directory", &opts,
+diff --git a/builtin/rebase.c b/builtin/rebase.c
+index d4715ed35d..d408335009 100644
+--- a/builtin/rebase.c
++++ b/builtin/rebase.c
+@@ -1122,9 +1122,15 @@ int cmd_rebase(int argc,
+ 		OPT_BIT('v', "verbose", &options.flags,
+ 			N_("display a diffstat of what changed upstream"),
+ 			REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT),
+-		{OPTION_NEGBIT, 'n', "no-stat", &options.flags, NULL,
+-			N_("do not show diffstat of what changed upstream"),
+-			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
++		{
++			.type = OPTION_NEGBIT,
++			.short_name = 'n',
++			.long_name = "no-stat",
++			.value = &options.flags,
++			.help = N_("do not show diffstat of what changed upstream"),
++			.flags = PARSE_OPT_NOARG,
++			.defval = REBASE_DIFFSTAT,
++		},
+ 		OPT_BOOL(0, "signoff", &options.signoff,
+ 			 N_("add a Signed-off-by trailer to each commit")),
+ 		OPT_BOOL(0, "committer-date-is-author-date",
+@@ -1190,9 +1196,16 @@ int cmd_rebase(int argc,
+ 		OPT_BOOL(0, "update-refs", &options.update_refs,
+ 			 N_("update branches that point to commits "
+ 			    "that are being rebased")),
+-		{ OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
+-			N_("GPG-sign commits"),
+-			PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'S',
++			.long_name = "gpg-sign",
++			.value = &gpg_sign,
++			.argh = N_("key-id"),
++			.help = N_("GPG-sign commits"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t) "",
++		},
+ 		OPT_AUTOSTASH(&options.autostash),
+ 		OPT_STRING_LIST('x', "exec", &options.exec, N_("exec"),
+ 				N_("add exec lines after each commit of the "
+diff --git a/builtin/revert.c b/builtin/revert.c
+index aca6c293cd..4f5ef97549 100644
+--- a/builtin/revert.c
++++ b/builtin/revert.c
+@@ -132,8 +132,16 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
+ 		OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")),
+ 		OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"),
+ 			N_("option for merge strategy")),
+-		{ OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
+-		  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
++		{
++			.type = OPTION_STRING,
++			.short_name = 'S',
++			.long_name = "gpg-sign",
++			.value = &gpg_sign,
++			.argh = N_("key-id"),
++			.help = N_("GPG sign commit"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = (intptr_t) "",
++		},
+ 		OPT_END()
+ 	};
+ 	struct option *options = base_options;
+diff --git a/builtin/show-branch.c b/builtin/show-branch.c
+index fce6b404e9..dab37019d2 100644
+--- a/builtin/show-branch.c
++++ b/builtin/show-branch.c
+@@ -667,9 +667,15 @@ int cmd_show_branch(int ac,
+ 			 N_("show remote-tracking branches")),
+ 		OPT__COLOR(&showbranch_use_color,
+ 			    N_("color '*!+-' corresponding to the branch")),
+-		{ OPTION_INTEGER, 0, "more", &extra, N_("n"),
+-			    N_("show <n> more commits after the common ancestor"),
+-			    PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
++		{
++			.type = OPTION_INTEGER,
++			.long_name = "more",
++			.value = &extra,
++			.argh = N_("n"),
++			.help = N_("show <n> more commits after the common ancestor"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = 1,
++		},
+ 		OPT_SET_INT(0, "list", &extra, N_("synonym to more=-1"), -1),
+ 		OPT_BOOL(0, "no-name", &no_name, N_("suppress naming strings")),
+ 		OPT_BOOL(0, "current", &with_current_branch,
+diff --git a/builtin/tag.c b/builtin/tag.c
+index d3e0943b73..b266f12bb4 100644
+--- a/builtin/tag.c
++++ b/builtin/tag.c
+@@ -479,9 +479,15 @@ int cmd_tag(int argc,
+ 	int edit_flag = 0;
+ 	struct option options[] = {
+ 		OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
+-		{ OPTION_INTEGER, 'n', NULL, &filter.lines, N_("n"),
+-				N_("print <n> lines of each tag message"),
+-				PARSE_OPT_OPTARG, NULL, 1 },
++		{
++			.type = OPTION_INTEGER,
++			.short_name = 'n',
++			.value = &filter.lines,
++			.argh = N_("n"),
++			.help = N_("print <n> lines of each tag message"),
++			.flags = PARSE_OPT_OPTARG,
++			.defval = 1,
++		},
+ 		OPT_CMDMODE('d', "delete", &cmdmode, N_("delete tags"), 'd'),
+ 		OPT_CMDMODE('v', "verify", &cmdmode, N_("verify tags"), 'v'),
+ 
+@@ -513,9 +519,14 @@ int cmd_tag(int argc,
+ 			N_("do not output a newline after empty formatted refs")),
+ 		OPT_REF_SORT(&sorting_options),
+ 		{
+-			OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
+-			N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
+-			parse_opt_object_name, (intptr_t) "HEAD"
++			.type = OPTION_CALLBACK,
++			.long_name = "points-at",
++			.value = &filter.points_at,
++			.argh = N_("object"),
++			.help = N_("print only tags of the object"),
++			.flags = PARSE_OPT_LASTARG_DEFAULT,
++			.callback = parse_opt_object_name,
++			.defval = (intptr_t) "HEAD",
+ 		},
+ 		OPT_STRING(  0 , "format", &format.format, N_("format"),
+ 			   N_("format to use for the output")),
+diff --git a/builtin/update-index.c b/builtin/update-index.c
+index b2f6b1a3fb..ee64b02267 100644
+--- a/builtin/update-index.c
++++ b/builtin/update-index.c
+@@ -964,29 +964,51 @@ int cmd_update_index(int argc,
+ 			N_("like --refresh, but ignore assume-unchanged setting"),
+ 			PARSE_OPT_NOARG | PARSE_OPT_NONEG,
+ 			really_refresh_callback),
+-		{OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL,
+-			N_("<mode>,<object>,<path>"),
+-			N_("add the specified entry to the index"),
+-			PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
+-			PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
+-			NULL, 0,
+-			cacheinfo_callback},
++		{
++			.type = OPTION_LOWLEVEL_CALLBACK,
++			.long_name = "cacheinfo",
++			.argh = N_("<mode>,<object>,<path>"),
++			.help = N_("add the specified entry to the index"),
++			.flags = PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */
++				 PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
++			.ll_callback = cacheinfo_callback,
++		},
+ 		OPT_CALLBACK_F(0, "chmod", &set_executable_bit, "(+|-)x",
+ 			N_("override the executable bit of the listed files"),
+ 			PARSE_OPT_NONEG,
+ 			chmod_callback),
+-		{OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL,
+-			N_("mark files as \"not changing\""),
+-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
+-		{OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL,
+-			N_("clear assumed-unchanged bit"),
+-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
+-		{OPTION_SET_INT, 0, "skip-worktree", &mark_skip_worktree_only, NULL,
+-			N_("mark files as \"index-only\""),
+-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
+-		{OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL,
+-			N_("clear skip-worktree bit"),
+-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
++		{
++			.type = OPTION_SET_INT,
++			.long_name = "assume-unchanged",
++			.value = &mark_valid_only,
++			.help = N_("mark files as \"not changing\""),
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++			.defval = MARK_FLAG,
++		},
++		{
++			.type = OPTION_SET_INT,
++			.long_name = "no-assume-unchanged",
++			.value = &mark_valid_only,
++			.help = N_("clear assumed-unchanged bit"),
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++			.defval = UNMARK_FLAG,
++		},
++		{
++			.type = OPTION_SET_INT,
++			.long_name = "skip-worktree",
++			.value = &mark_skip_worktree_only,
++			.help = N_("mark files as \"index-only\""),
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++			.defval = MARK_FLAG,
++		},
++		{
++			.type = OPTION_SET_INT,
++			.long_name = "no-skip-worktree",
++			.value = &mark_skip_worktree_only,
++			.help = N_("clear skip-worktree bit"),
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++			.defval = UNMARK_FLAG,
++		},
+ 		OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries,
+ 			 N_("do not touch index-only entries")),
+ 		OPT_SET_INT(0, "info-only", &info_only,
+@@ -995,22 +1017,39 @@ int cmd_update_index(int argc,
+ 			N_("remove named paths even if present in worktree"), 1),
+ 		OPT_BOOL('z', NULL, &nul_term_line,
+ 			 N_("with --stdin: input lines are terminated by null bytes")),
+-		{OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
+-			N_("read list of paths to be updated from standard input"),
+-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+-			NULL, 0, stdin_callback},
+-		{OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL,
+-			N_("add entries from standard input to the index"),
+-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+-			NULL, 0, stdin_cacheinfo_callback},
+-		{OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL,
+-			N_("repopulate stages #2 and #3 for the listed paths"),
+-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+-			NULL, 0, unresolve_callback},
+-		{OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL,
+-			N_("only update entries that differ from HEAD"),
+-			PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+-			NULL, 0, reupdate_callback},
++		{
++			.type = OPTION_LOWLEVEL_CALLBACK,
++			.long_name = "stdin",
++			.value = &read_from_stdin,
++			.help = N_("read list of paths to be updated from standard input"),
++			.flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
++			.ll_callback = stdin_callback,
++		},
++		{
++			.type = OPTION_LOWLEVEL_CALLBACK,
++			.long_name = "index-info",
++			.value = &nul_term_line,
++			.help = N_("add entries from standard input to the index"),
++			.flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
++			.ll_callback = stdin_cacheinfo_callback,
++		},
++		{
++			.type = OPTION_LOWLEVEL_CALLBACK,
++			.long_name = "unresolve",
++			.value = &has_errors,
++			.help = N_("repopulate stages #2 and #3 for the listed paths"),
++			.flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
++			.ll_callback = unresolve_callback,
++		},
++		{
++			.type = OPTION_LOWLEVEL_CALLBACK,
++			.short_name = 'g',
++			.long_name = "again",
++			.value = &has_errors,
++			.help = N_("only update entries that differ from HEAD"),
++			.flags = PARSE_OPT_NONEG | PARSE_OPT_NOARG,
++			.ll_callback = reupdate_callback,
++		},
+ 		OPT_BIT(0, "ignore-missing", &refresh_args.flags,
+ 			N_("ignore files missing from worktree"),
+ 			REFRESH_IGNORE_MISSING),
+@@ -1036,12 +1075,22 @@ int cmd_update_index(int argc,
+ 			N_("write out the index even if is not flagged as changed"), 1),
+ 		OPT_BOOL(0, "fsmonitor", &fsmonitor,
+ 			N_("enable or disable file system monitor")),
+-		{OPTION_SET_INT, 0, "fsmonitor-valid", &mark_fsmonitor_only, NULL,
+-			N_("mark files as fsmonitor valid"),
+-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
+-		{OPTION_SET_INT, 0, "no-fsmonitor-valid", &mark_fsmonitor_only, NULL,
+-			N_("clear fsmonitor valid bit"),
+-			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},
++		{
++			.type = OPTION_SET_INT,
++			.long_name = "fsmonitor-valid",
++			.value = &mark_fsmonitor_only,
++			.help = N_("mark files as fsmonitor valid"),
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++			.defval = MARK_FLAG,
++		},
++		{
++			.type = OPTION_SET_INT,
++			.long_name = "no-fsmonitor-valid",
++			.value = &mark_fsmonitor_only,
++			.help = N_("clear fsmonitor valid bit"),
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++			.defval = UNMARK_FLAG,
++		},
+ 		OPT_END()
+ 	};
+ 
+diff --git a/builtin/write-tree.c b/builtin/write-tree.c
+index 43f233e69b..5a8dc377ec 100644
+--- a/builtin/write-tree.c
++++ b/builtin/write-tree.c
+@@ -31,10 +31,14 @@ int cmd_write_tree(int argc,
+ 			WRITE_TREE_MISSING_OK),
+ 		OPT_STRING(0, "prefix", &tree_prefix, N_("<prefix>/"),
+ 			   N_("write tree object for a subdirectory <prefix>")),
+-		{ OPTION_BIT, 0, "ignore-cache-tree", &flags, NULL,
+-		  N_("only useful for debugging"),
+-		  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, NULL,
+-		  WRITE_TREE_IGNORE_CACHE_TREE },
++		{
++			.type = OPTION_BIT,
++			.long_name = "ignore-cache-tree",
++			.value = &flags,
++			.help = N_("only useful for debugging"),
++			.flags = PARSE_OPT_HIDDEN | PARSE_OPT_NOARG,
++			.defval = WRITE_TREE_IGNORE_CACHE_TREE,
++		},
+ 		OPT_END()
+ 	};
+ 
+diff --git a/diff.c b/diff.c
+index 08f5e00a2c..f2fcc7f3c2 100644
+--- a/diff.c
++++ b/diff.c
+@@ -5892,10 +5892,15 @@ struct option *add_diff_options(const struct option *opts,
+ 		OPT_CALLBACK_F(0, "diff-filter", options, N_("[(A|C|D|M|R|T|U|X|B)...[*]]"),
+ 			       N_("select files by diff type"),
+ 			       PARSE_OPT_NONEG, diff_opt_diff_filter),
+-		{ OPTION_CALLBACK, 0, "output", options, N_("<file>"),
+-		  N_("output to a specific file"),
+-		  PARSE_OPT_NONEG, NULL, 0, diff_opt_output },
+-
++		{
++			.type = OPTION_CALLBACK,
++			.long_name = "output",
++			.value = options,
++			.argh = N_("<file>"),
++			.help = N_("output to a specific file"),
++			.flags = PARSE_OPT_NONEG,
++			.ll_callback = diff_opt_output,
++		},
+ 		OPT_END()
+ 	};
+ 
+diff --git a/ref-filter.h b/ref-filter.h
+index 013d4cfa64..c98c4fbd4c 100644
+--- a/ref-filter.h
++++ b/ref-filter.h
+@@ -114,11 +114,16 @@ struct ref_format {
+ }
+ 
+ /*  Macros for checking --merged and --no-merged options */
+-#define _OPT_MERGED_NO_MERGED(option, filter, h) \
+-	{ OPTION_CALLBACK, 0, option, (filter), N_("commit"), (h), \
+-	  PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
+-	  parse_opt_merge_filter, (intptr_t) "HEAD" \
+-	}
++#define _OPT_MERGED_NO_MERGED(option, filter, h) { \
++	.type = OPTION_CALLBACK, \
++	.long_name = option, \
++	.value = (filter), \
++	.argh = N_("commit"), \
++	.help = (h), \
++	.flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG, \
++	.callback = parse_opt_merge_filter, \
++	.defval = (intptr_t) "HEAD", \
++}
+ #define OPT_MERGED(f, h) _OPT_MERGED_NO_MERGED("merged", f, h)
+ #define OPT_NO_MERGED(f, h) _OPT_MERGED_NO_MERGED("no-merged", f, h)
+ 
+diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
+index bfe45ec68b..997f55fd45 100644
+--- a/t/helper/test-parse-options.c
++++ b/t/helper/test-parse-options.c
+@@ -124,8 +124,15 @@ int cmd__parse_options(int argc, const char **argv)
+ 	struct option options[] = {
+ 		OPT_BOOL(0, "yes", &boolean, "get a boolean"),
+ 		OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"),
+-		{ OPTION_SET_INT, 'B', "no-fear", &boolean, NULL,
+-		  "be brave", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
++		{
++			.type = OPTION_SET_INT,
++			.short_name = 'B',
++			.long_name = "no-fear",
++			.value = &boolean,
++			.help = "be brave",
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++			.defval = 1,
++		},
+ 		OPT_COUNTUP('b', "boolean", &boolean, "increment by one"),
+ 		OPT_BIT('4', "or4", &boolean,
+ 			"bitwise-or boolean with ...0100", 4),
+@@ -155,12 +162,27 @@ int cmd__parse_options(int argc, const char **argv)
+ 		OPT_GROUP("Magic arguments"),
+ 		OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
+ 			number_callback),
+-		{ OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b",
+-		  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH },
+-		{ OPTION_COUNTUP, 0, "ambiguous", &ambiguous, NULL,
+-		  "positive ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
+-		{ OPTION_COUNTUP, 0, "no-ambiguous", &ambiguous, NULL,
+-		  "negative ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
++		{
++			.type = OPTION_COUNTUP,
++			.short_name = '+',
++			.value = &boolean,
++			.help = "same as -b",
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH,
++		},
++		{
++			.type = OPTION_COUNTUP,
++			.long_name = "ambiguous",
++			.value = &ambiguous,
++			.help = "positive ambiguity",
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++		},
++		{
++			.type = OPTION_COUNTUP,
++			.long_name = "no-ambiguous",
++			.value = &ambiguous,
++			.help = "negative ambiguity",
++			.flags = PARSE_OPT_NOARG | PARSE_OPT_NONEG,
++		},
+ 		OPT_GROUP("Standard options"),
+ 		OPT__ABBREV(&abbrev),
+ 		OPT__VERBOSE(&verbose, "be verbose"),
+-- 
+2.39.5
+
diff -Nru git-2.49.0/debian/patches/0003-parse-options-support-unit-factors-in-OPT_INTEGER.patch git-2.49.0/debian/patches/0003-parse-options-support-unit-factors-in-OPT_INTEGER.patch
--- git-2.49.0/debian/patches/0003-parse-options-support-unit-factors-in-OPT_INTEGER.patch	1970-01-01 01:00:00.000000000 +0100
+++ git-2.49.0/debian/patches/0003-parse-options-support-unit-factors-in-OPT_INTEGER.patch	2025-05-29 17:33:17.000000000 +0200
@@ -0,0 +1,110 @@
+From 8ff1a34bdfef0a0689130508388325af1db38237 Mon Sep 17 00:00:00 2001
+From: Patrick Steinhardt <p...@pks.im>
+Date: Thu, 17 Apr 2025 12:49:38 +0200
+Subject: [PATCH 3/7] parse-options: support unit factors in `OPT_INTEGER()`
+
+There are two main differences between `OPT_INTEGER()` and
+`OPT_MAGNITUDE()`:
+
+  - The former parses signed integers whereas the latter parses unsigned
+    integers.
+
+  - The latter parses unit factors like 'k', 'm' or 'g'.
+
+While the first difference makes obvious sense, there isn't really a
+good reason why signed integers shouldn't support unit factors, too.
+
+This inconsistency will also become a bit of a problem with subsequent
+commits, where we will fix a couple of callsites that pass an unsigned
+integer to `OPT_INTEGER()`. There are three options:
+
+  - We could adapt those users to instead pass a signed integer, but
+    this would needlessly extend the range of accepted integer values.
+
+  - We could convert them to use `OPT_MAGNITUDE()`, as it only accepts
+    unsigned integers. But now we have the inconsistency that we also
+    start to accept unit factors.
+
+  - We could introduce `OPT_UNSIGNED()` as equivalent to `OPT_INTEGER()`
+    so that it knows to only accept unsigned integers without unit
+    suffix.
+
+Introducing a whole new option type feels a bit excessive. There also
+isn't really a good reason why `OPT_INTEGER()` cannot be extended to
+also accept unit factors: all valid values passed to such options cannot
+have a unit factors right now, so there wouldn't be any ambiguity.
+
+Refactor `OPT_INTEGER()` to use `git_parse_int()`, which knows to
+interpret unit factors. This removes the inconsistency between the
+signed and unsigned options so that we can easily fix up callsites that
+pass the wrong integer type right now.
+
+Signed-off-by: Patrick Steinhardt <p...@pks.im>
+Signed-off-by: Junio C Hamano <gits...@pobox.com>
+---
+ Documentation/technical/api-parse-options.adoc | 6 ++++--
+ parse-options.c                                | 8 ++++----
+ t/t0040-parse-options.sh                       | 4 +++-
+ 3 files changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/Documentation/technical/api-parse-options.adoc b/Documentation/technical/api-parse-options.adoc
+index 61fa6ee167..63acfb419b 100644
+--- a/Documentation/technical/api-parse-options.adoc
++++ b/Documentation/technical/api-parse-options.adoc
+@@ -211,8 +211,10 @@ There are some macros to easily define options:
+ 	Use of `--no-option` will clear the list of preceding values.
+ 
+ `OPT_INTEGER(short, long, &int_var, description)`::
+-	Introduce an option with integer argument.
+-	The integer is put into `int_var`.
++	Introduce an option with integer argument. The argument must be a
++	integer and may include a suffix of 'k', 'm' or 'g' to
++	scale the provided value by 1024, 1024^2 or 1024^3 respectively.
++	The scaled value is put into `int_var`.
+ 
+ `OPT_MAGNITUDE(short, long, &unsigned_long_var, description)`::
+ 	Introduce an option with a size argument. The argument must be a
+diff --git a/parse-options.c b/parse-options.c
+index 35fbb3b0d6..b287436e81 100644
+--- a/parse-options.c
++++ b/parse-options.c
+@@ -73,7 +73,7 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
+ 					  enum opt_parsed flags,
+ 					  const char **argp)
+ {
+-	const char *s, *arg;
++	const char *arg;
+ 	const int unset = flags & OPT_UNSET;
+ 	int err;
+ 
+@@ -185,9 +185,9 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
+ 		if (!*arg)
+ 			return error(_("%s expects a numerical value"),
+ 				     optname(opt, flags));
+-		*(int *)opt->value = strtol(arg, (char **)&s, 10);
+-		if (*s)
+-			return error(_("%s expects a numerical value"),
++		if (!git_parse_int(arg, opt->value))
++			return error(_("%s expects an integer value"
++				       " with an optional k/m/g suffix"),
+ 				     optname(opt, flags));
+ 		return 0;
+ 
+diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
+index 2fe3522305..0c538c4b43 100755
+--- a/t/t0040-parse-options.sh
++++ b/t/t0040-parse-options.sh
+@@ -111,7 +111,9 @@ test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown_i18n --no-no-fear
+ 
+ test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'
+ 
+-test_expect_success 'OPT_INT() negative' 'check integer: -2345 -i -2345'
++test_expect_success 'OPT_INTEGER() negative' 'check integer: -2345 -i -2345'
++test_expect_success 'OPT_INTEGER() kilo' 'check integer: 239616 -i 234k'
++test_expect_success 'OPT_INTEGER() negative kilo' 'check integer: -239616 -i -234k'
+ 
+ test_expect_success 'OPT_MAGNITUDE() simple' '
+ 	check magnitude: 2345678 -m 2345678
+-- 
+2.39.5
+
diff -Nru git-2.49.0/debian/patches/0004-parse-options-rename-OPT_MAGNITUDE-to-OPT_UNSIGNED.patch git-2.49.0/debian/patches/0004-parse-options-rename-OPT_MAGNITUDE-to-OPT_UNSIGNED.patch
--- git-2.49.0/debian/patches/0004-parse-options-rename-OPT_MAGNITUDE-to-OPT_UNSIGNED.patch	1970-01-01 01:00:00.000000000 +0100
+++ git-2.49.0/debian/patches/0004-parse-options-rename-OPT_MAGNITUDE-to-OPT_UNSIGNED.patch	2025-05-29 17:33:17.000000000 +0200
@@ -0,0 +1,367 @@
+From 785c17df7817df8512d2cb92cfc079ef0b4de27c Mon Sep 17 00:00:00 2001
+From: Patrick Steinhardt <p...@pks.im>
+Date: Thu, 17 Apr 2025 12:49:39 +0200
+Subject: [PATCH 4/7] parse-options: rename `OPT_MAGNITUDE()` to
+ `OPT_UNSIGNED()`
+
+With the preceding commit, `OPT_INTEGER()` has learned to support unit
+factors. Consequently, the major differencen between `OPT_INTEGER()` and
+`OPT_MAGNITUDE()` isn't the support of unit factors anymore, as both of
+them do support them now. Instead, the difference is that one handles
+signed and the other handles unsigned integers.
+
+Adapt the name of `OPT_MAGNITUDE()` accordingly by renaming it to
+`OPT_UNSIGNED()`.
+
+Signed-off-by: Patrick Steinhardt <p...@pks.im>
+Signed-off-by: Junio C Hamano <gits...@pobox.com>
+---
+ .../technical/api-parse-options.adoc          |  4 +-
+ builtin/gc.c                                  |  4 +-
+ builtin/multi-pack-index.c                    |  2 +-
+ builtin/pack-objects.c                        |  8 +--
+ builtin/repack.c                              |  8 +--
+ parse-options.c                               |  6 +--
+ parse-options.h                               |  6 +--
+ t/helper/test-parse-options.c                 |  6 +--
+ t/t0040-parse-options.sh                      | 50 +++++++++----------
+ 9 files changed, 47 insertions(+), 47 deletions(-)
+
+diff --git a/Documentation/technical/api-parse-options.adoc b/Documentation/technical/api-parse-options.adoc
+index 63acfb419b..880eb94642 100644
+--- a/Documentation/technical/api-parse-options.adoc
++++ b/Documentation/technical/api-parse-options.adoc
+@@ -216,8 +216,8 @@ There are some macros to easily define options:
+ 	scale the provided value by 1024, 1024^2 or 1024^3 respectively.
+ 	The scaled value is put into `int_var`.
+ 
+-`OPT_MAGNITUDE(short, long, &unsigned_long_var, description)`::
+-	Introduce an option with a size argument. The argument must be a
++`OPT_UNSIGNED(short, long, &unsigned_long_var, description)`::
++	Introduce an option with an unsigned integer argument. The argument must be a
+ 	non-negative integer and may include a suffix of 'k', 'm' or 'g' to
+ 	scale the provided value by 1024, 1024^2 or 1024^3 respectively.
+ 	The scaled value is put into `unsigned_long_var`.
+diff --git a/builtin/gc.c b/builtin/gc.c
+index 6707a26bc6..b32cf937cd 100644
+--- a/builtin/gc.c
++++ b/builtin/gc.c
+@@ -709,8 +709,8 @@ struct repository *repo UNUSED)
+ 			.defval = (intptr_t)prune_expire_arg,
+ 		},
+ 		OPT_BOOL(0, "cruft", &cfg.cruft_packs, N_("pack unreferenced objects separately")),
+-		OPT_MAGNITUDE(0, "max-cruft-size", &cfg.max_cruft_size,
+-			      N_("with --cruft, limit the size of new cruft packs")),
++		OPT_UNSIGNED(0, "max-cruft-size", &cfg.max_cruft_size,
++			     N_("with --cruft, limit the size of new cruft packs")),
+ 		OPT_BOOL(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
+ 		OPT_BOOL_F(0, "auto", &opts.auto_flag, N_("enable auto-gc mode"),
+ 			   PARSE_OPT_NOCOMPLETE),
+diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
+index 2a938466f5..e4820fd721 100644
+--- a/builtin/multi-pack-index.c
++++ b/builtin/multi-pack-index.c
+@@ -245,7 +245,7 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv,
+ {
+ 	struct option *options;
+ 	static struct option builtin_multi_pack_index_repack_options[] = {
+-		OPT_MAGNITUDE(0, "batch-size", &opts.batch_size,
++		OPT_UNSIGNED(0, "batch-size", &opts.batch_size,
+ 		  N_("during repack, collect pack-files of smaller size into a batch that is larger than this size")),
+ 		OPT_BIT(0, "progress", &opts.flags,
+ 		  N_("force progress reporting"), MIDX_PROGRESS),
+diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
+index 79e1e6fb52..9328812e28 100644
+--- a/builtin/pack-objects.c
++++ b/builtin/pack-objects.c
+@@ -4483,16 +4483,16 @@ int cmd_pack_objects(int argc,
+ 		OPT_CALLBACK_F(0, "index-version", &pack_idx_opts, N_("<version>[,<offset>]"),
+ 		  N_("write the pack index file in the specified idx format version"),
+ 		  PARSE_OPT_NONEG, option_parse_index_version),
+-		OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit,
+-			      N_("maximum size of each output pack file")),
++		OPT_UNSIGNED(0, "max-pack-size", &pack_size_limit,
++			     N_("maximum size of each output pack file")),
+ 		OPT_BOOL(0, "local", &local,
+ 			 N_("ignore borrowed objects from alternate object store")),
+ 		OPT_BOOL(0, "incremental", &incremental,
+ 			 N_("ignore packed objects")),
+ 		OPT_INTEGER(0, "window", &window,
+ 			    N_("limit pack window by objects")),
+-		OPT_MAGNITUDE(0, "window-memory", &window_memory_limit,
+-			      N_("limit pack window by memory in addition to object limit")),
++		OPT_UNSIGNED(0, "window-memory", &window_memory_limit,
++			     N_("limit pack window by memory in addition to object limit")),
+ 		OPT_INTEGER(0, "depth", &depth,
+ 			    N_("maximum length of delta chain allowed in the resulting pack")),
+ 		OPT_BOOL(0, "reuse-delta", &reuse_delta,
+diff --git a/builtin/repack.c b/builtin/repack.c
+index 75e3752353..8bf9941b2c 100644
+--- a/builtin/repack.c
++++ b/builtin/repack.c
+@@ -1202,8 +1202,8 @@ int cmd_repack(int argc,
+ 				   PACK_CRUFT),
+ 		OPT_STRING(0, "cruft-expiration", &cruft_expiration, N_("approxidate"),
+ 				N_("with --cruft, expire objects older than this")),
+-		OPT_MAGNITUDE(0, "max-cruft-size", &cruft_po_args.max_pack_size,
+-				N_("with --cruft, limit the size of new cruft packs")),
++		OPT_UNSIGNED(0, "max-cruft-size", &cruft_po_args.max_pack_size,
++			     N_("with --cruft, limit the size of new cruft packs")),
+ 		OPT_BOOL('d', NULL, &delete_redundant,
+ 				N_("remove redundant packs, and run git-prune-packed")),
+ 		OPT_BOOL('f', NULL, &po_args.no_reuse_delta,
+@@ -1233,8 +1233,8 @@ int cmd_repack(int argc,
+ 				N_("limits the maximum delta depth")),
+ 		OPT_STRING(0, "threads", &opt_threads, N_("n"),
+ 				N_("limits the maximum number of threads")),
+-		OPT_MAGNITUDE(0, "max-pack-size", &po_args.max_pack_size,
+-				N_("maximum size of each packfile")),
++		OPT_UNSIGNED(0, "max-pack-size", &po_args.max_pack_size,
++			     N_("maximum size of each packfile")),
+ 		OPT_PARSE_LIST_OBJECTS_FILTER(&po_args.filter_options),
+ 		OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
+ 				N_("repack objects in packs marked with .keep")),
+diff --git a/parse-options.c b/parse-options.c
+index b287436e81..d23e587e98 100644
+--- a/parse-options.c
++++ b/parse-options.c
+@@ -191,7 +191,7 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
+ 				     optname(opt, flags));
+ 		return 0;
+ 
+-	case OPTION_MAGNITUDE:
++	case OPTION_UNSIGNED:
+ 		if (unset) {
+ 			*(unsigned long *)opt->value = 0;
+ 			return 0;
+@@ -656,7 +656,7 @@ static void show_negated_gitcomp(const struct option *opts, int show_all,
+ 		case OPTION_STRING:
+ 		case OPTION_FILENAME:
+ 		case OPTION_INTEGER:
+-		case OPTION_MAGNITUDE:
++		case OPTION_UNSIGNED:
+ 		case OPTION_CALLBACK:
+ 		case OPTION_BIT:
+ 		case OPTION_NEGBIT:
+@@ -708,7 +708,7 @@ static int show_gitcomp(const struct option *opts, int show_all)
+ 		case OPTION_STRING:
+ 		case OPTION_FILENAME:
+ 		case OPTION_INTEGER:
+-		case OPTION_MAGNITUDE:
++		case OPTION_UNSIGNED:
+ 		case OPTION_CALLBACK:
+ 			if (opts->flags & PARSE_OPT_NOARG)
+ 				break;
+diff --git a/parse-options.h b/parse-options.h
+index 997ffbee80..14e4df1ee2 100644
+--- a/parse-options.h
++++ b/parse-options.h
+@@ -25,7 +25,7 @@ enum parse_opt_type {
+ 	/* options with arguments (usually) */
+ 	OPTION_STRING,
+ 	OPTION_INTEGER,
+-	OPTION_MAGNITUDE,
++	OPTION_UNSIGNED,
+ 	OPTION_CALLBACK,
+ 	OPTION_LOWLEVEL_CALLBACK,
+ 	OPTION_FILENAME
+@@ -270,8 +270,8 @@ struct option {
+ #define OPT_CMDMODE(s, l, v, h, i)  OPT_CMDMODE_F(s, l, v, h, i, 0)
+ 
+ #define OPT_INTEGER(s, l, v, h)     OPT_INTEGER_F(s, l, v, h, 0)
+-#define OPT_MAGNITUDE(s, l, v, h) { \
+-	.type = OPTION_MAGNITUDE, \
++#define OPT_UNSIGNED(s, l, v, h) { \
++	.type = OPTION_UNSIGNED, \
+ 	.short_name = (s), \
+ 	.long_name = (l), \
+ 	.value = (v), \
+diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
+index 997f55fd45..fc3e2861c2 100644
+--- a/t/helper/test-parse-options.c
++++ b/t/helper/test-parse-options.c
+@@ -6,7 +6,7 @@
+ 
+ static int boolean = 0;
+ static int integer = 0;
+-static unsigned long magnitude = 0;
++static unsigned long unsigned_integer = 0;
+ static timestamp_t timestamp;
+ static int abbrev = 7;
+ static int verbose = -1; /* unspecified */
+@@ -140,7 +140,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 		OPT_GROUP(""),
+ 		OPT_INTEGER('i', "integer", &integer, "get a integer"),
+ 		OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
+-		OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
++		OPT_UNSIGNED('u', "unsigned", &unsigned_integer, "get an unsigned integer"),
+ 		OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
+ 		OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
+ 		OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
+@@ -210,7 +210,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 	}
+ 	show(&expect, &ret, "boolean: %d", boolean);
+ 	show(&expect, &ret, "integer: %d", integer);
+-	show(&expect, &ret, "magnitude: %lu", magnitude);
++	show(&expect, &ret, "unsigned: %lu", unsigned_integer);
+ 	show(&expect, &ret, "timestamp: %"PRItime, timestamp);
+ 	show(&expect, &ret, "string: %s", string ? string : "(not set)");
+ 	show(&expect, &ret, "abbrev: %d", abbrev);
+diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
+index 0c538c4b43..65a11c8dbc 100755
+--- a/t/t0040-parse-options.sh
++++ b/t/t0040-parse-options.sh
+@@ -23,7 +23,7 @@ usage: test-tool parse-options <options>
+     -i, --[no-]integer <n>
+                           get a integer
+     -j <n>                get a integer, too
+-    -m, --magnitude <n>   get a magnitude
++    -u, --unsigned <n>    get an unsigned integer
+     --[no-]set23          set integer to 23
+     --mode1               set integer to 1 (cmdmode option)
+     --mode2               set integer to 2 (cmdmode option)
+@@ -115,30 +115,30 @@ test_expect_success 'OPT_INTEGER() negative' 'check integer: -2345 -i -2345'
+ test_expect_success 'OPT_INTEGER() kilo' 'check integer: 239616 -i 234k'
+ test_expect_success 'OPT_INTEGER() negative kilo' 'check integer: -239616 -i -234k'
+ 
+-test_expect_success 'OPT_MAGNITUDE() simple' '
+-	check magnitude: 2345678 -m 2345678
++test_expect_success 'OPT_UNSIGNED() simple' '
++	check unsigned: 2345678 -u 2345678
+ '
+ 
+-test_expect_success 'OPT_MAGNITUDE() kilo' '
+-	check magnitude: 239616 -m 234k
++test_expect_success 'OPT_UNSIGNED() kilo' '
++	check unsigned: 239616 -u 234k
+ '
+ 
+-test_expect_success 'OPT_MAGNITUDE() mega' '
+-	check magnitude: 104857600 -m 100m
++test_expect_success 'OPT_UNSIGNED() mega' '
++	check unsigned: 104857600 -u 100m
+ '
+ 
+-test_expect_success 'OPT_MAGNITUDE() giga' '
+-	check magnitude: 1073741824 -m 1g
++test_expect_success 'OPT_UNSIGNED() giga' '
++	check unsigned: 1073741824 -u 1g
+ '
+ 
+-test_expect_success 'OPT_MAGNITUDE() 3giga' '
+-	check magnitude: 3221225472 -m 3g
++test_expect_success 'OPT_UNSIGNED() 3giga' '
++	check unsigned: 3221225472 -u 3g
+ '
+ 
+ cat >expect <<\EOF
+ boolean: 2
+ integer: 1729
+-magnitude: 16384
++unsigned: 16384
+ timestamp: 0
+ string: 123
+ abbrev: 7
+@@ -149,7 +149,7 @@ file: prefix/my.file
+ EOF
+ 
+ test_expect_success 'short options' '
+-	test-tool parse-options -s123 -b -i 1729 -m 16k -b -vv -n -F my.file \
++	test-tool parse-options -s123 -b -i 1729 -u 16k -b -vv -n -F my.file \
+ 	>output 2>output.err &&
+ 	test_cmp expect output &&
+ 	test_must_be_empty output.err
+@@ -158,7 +158,7 @@ test_expect_success 'short options' '
+ cat >expect <<\EOF
+ boolean: 2
+ integer: 1729
+-magnitude: 16384
++unsigned: 16384
+ timestamp: 0
+ string: 321
+ abbrev: 10
+@@ -169,7 +169,7 @@ file: prefix/fi.le
+ EOF
+ 
+ test_expect_success 'long options' '
+-	test-tool parse-options --boolean --integer 1729 --magnitude 16k \
++	test-tool parse-options --boolean --integer 1729 --unsigned 16k \
+ 		--boolean --string2=321 --verbose --verbose --no-dry-run \
+ 		--abbrev=10 --file fi.le --obsolete \
+ 		>output 2>output.err &&
+@@ -181,7 +181,7 @@ test_expect_success 'abbreviate to something longer than SHA1 length' '
+ 	cat >expect <<-EOF &&
+ 	boolean: 0
+ 	integer: 0
+-	magnitude: 0
++	unsigned: 0
+ 	timestamp: 0
+ 	string: (not set)
+ 	abbrev: 100
+@@ -255,7 +255,7 @@ test_expect_success 'superfluous value provided: cmdmode' '
+ cat >expect <<\EOF
+ boolean: 1
+ integer: 13
+-magnitude: 0
++unsigned: 0
+ timestamp: 0
+ string: 123
+ abbrev: 7
+@@ -278,7 +278,7 @@ test_expect_success 'intermingled arguments' '
+ cat >expect <<\EOF
+ boolean: 0
+ integer: 2
+-magnitude: 0
++unsigned: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -345,7 +345,7 @@ cat >expect <<\EOF
+ Callback: "four", 0
+ boolean: 5
+ integer: 4
+-magnitude: 0
++unsigned: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -370,7 +370,7 @@ test_expect_success 'OPT_CALLBACK() and callback errors work' '
+ cat >expect <<\EOF
+ boolean: 1
+ integer: 23
+-magnitude: 0
++unsigned: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -449,7 +449,7 @@ test_expect_success 'OPT_NUMBER_CALLBACK() works' '
+ cat >expect <<\EOF
+ boolean: 0
+ integer: 0
+-magnitude: 0
++unsigned: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -773,14 +773,14 @@ test_expect_success 'subcommands are incompatible with KEEP_DASHDASH unless in c
+ 	grep ^BUG err
+ '
+ 
+-test_expect_success 'negative magnitude' '
+-	test_must_fail test-tool parse-options --magnitude -1 >out 2>err &&
++test_expect_success 'negative unsigned' '
++	test_must_fail test-tool parse-options --unsigned -1 >out 2>err &&
+ 	grep "non-negative integer" err &&
+ 	test_must_be_empty out
+ '
+ 
+-test_expect_success 'magnitude with units but no numbers' '
+-	test_must_fail test-tool parse-options --magnitude m >out 2>err &&
++test_expect_success 'unsigned with units but no numbers' '
++	test_must_fail test-tool parse-options --unsigned m >out 2>err &&
+ 	grep "non-negative integer" err &&
+ 	test_must_be_empty out
+ '
+-- 
+2.39.5
+
diff -Nru git-2.49.0/debian/patches/0005-parse-options-introduce-precision-handling-for-OPTIO.patch git-2.49.0/debian/patches/0005-parse-options-introduce-precision-handling-for-OPTIO.patch
--- git-2.49.0/debian/patches/0005-parse-options-introduce-precision-handling-for-OPTIO.patch	1970-01-01 01:00:00.000000000 +0100
+++ git-2.49.0/debian/patches/0005-parse-options-introduce-precision-handling-for-OPTIO.patch	2025-05-29 17:33:17.000000000 +0200
@@ -0,0 +1,337 @@
+From 09705696f763bac370ac74926bef137eb712c0c8 Mon Sep 17 00:00:00 2001
+From: Patrick Steinhardt <p...@pks.im>
+Date: Thu, 17 Apr 2025 12:49:40 +0200
+Subject: [PATCH 5/7] parse-options: introduce precision handling for
+ `OPTION_INTEGER`
+
+The `OPTION_INTEGER` option type accepts a signed integer. The type of
+the underlying integer is a simple `int`, which restricts the range of
+values accepted by such options. But there is a catch: because the
+caller provides a pointer to the value via the `.value` field, which is
+a simple void pointer. This has two consequences:
+
+  - There is no check whether the passed value is sufficiently long to
+    store the entire range of `int`. This can lead to integer wraparound
+    in the best case and out-of-bounds writes in the worst case.
+
+  - Even when a caller knows that they want to store a value larger than
+    `INT_MAX` they don't have a way to do so.
+
+In practice this doesn't tend to be a huge issue because users typically
+don't end up passing huge values to most commands. But the parsing logic
+is demonstrably broken, and it is too easy to get the calling convention
+wrong.
+
+Improve the situation by introducing a new `precision` field into the
+structure. This field gets assigned automatically by `OPT_INTEGER_F()`
+and tracks the size of the passed value. Like this it becomes possible
+for the caller to pass arbitrarily-sized integers and the underlying
+logic knows to handle it correctly by doing range checks. Furthermore,
+convert the code to use `strtoimax()` intstead of `strtol()` so that we
+can also parse values larger than `LONG_MAX`.
+
+Note that we do not yet assert signedness of the passed variable, which
+is another source of bugs. This will be handled in a subsequent commit.
+
+Signed-off-by: Patrick Steinhardt <p...@pks.im>
+Signed-off-by: Junio C Hamano <gits...@pobox.com>
+---
+ builtin/fmt-merge-msg.c       |  2 ++
+ builtin/merge.c               |  1 +
+ builtin/show-branch.c         |  1 +
+ builtin/tag.c                 |  1 +
+ parse-options.c               | 52 ++++++++++++++++++++++++++---------
+ parse-options.h               |  6 ++++
+ t/helper/test-parse-options.c |  3 ++
+ t/t0040-parse-options.sh      | 23 +++++++++++++++-
+ 8 files changed, 75 insertions(+), 14 deletions(-)
+
+diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
+index 240cdb474b..3b6aac2cf7 100644
+--- a/builtin/fmt-merge-msg.c
++++ b/builtin/fmt-merge-msg.c
+@@ -24,6 +24,7 @@ int cmd_fmt_merge_msg(int argc,
+ 			.type = OPTION_INTEGER,
+ 			.long_name = "log",
+ 			.value = &shortlog_len,
++			.precision = sizeof(shortlog_len),
+ 			.argh = N_("n"),
+ 			.help = N_("populate log with at most <n> entries from shortlog"),
+ 			.flags = PARSE_OPT_OPTARG,
+@@ -33,6 +34,7 @@ int cmd_fmt_merge_msg(int argc,
+ 			.type = OPTION_INTEGER,
+ 			.long_name = "summary",
+ 			.value = &shortlog_len,
++			.precision = sizeof(shortlog_len),
+ 			.argh = N_("n"),
+ 			.help = N_("alias for --log (deprecated)"),
+ 			.flags = PARSE_OPT_OPTARG | PARSE_OPT_HIDDEN,
+diff --git a/builtin/merge.c b/builtin/merge.c
+index 21787d4516..9ab10c7db0 100644
+--- a/builtin/merge.c
++++ b/builtin/merge.c
+@@ -254,6 +254,7 @@ static struct option builtin_merge_options[] = {
+ 		.type = OPTION_INTEGER,
+ 		.long_name = "log",
+ 		.value = &shortlog_len,
++		.precision = sizeof(shortlog_len),
+ 		.argh = N_("n"),
+ 		.help = N_("add (at most <n>) entries from shortlog to merge commit message"),
+ 		.flags = PARSE_OPT_OPTARG,
+diff --git a/builtin/show-branch.c b/builtin/show-branch.c
+index dab37019d2..b549d8c3f5 100644
+--- a/builtin/show-branch.c
++++ b/builtin/show-branch.c
+@@ -671,6 +671,7 @@ int cmd_show_branch(int ac,
+ 			.type = OPTION_INTEGER,
+ 			.long_name = "more",
+ 			.value = &extra,
++			.precision = sizeof(extra),
+ 			.argh = N_("n"),
+ 			.help = N_("show <n> more commits after the common ancestor"),
+ 			.flags = PARSE_OPT_OPTARG,
+diff --git a/builtin/tag.c b/builtin/tag.c
+index b266f12bb4..7597d93c71 100644
+--- a/builtin/tag.c
++++ b/builtin/tag.c
+@@ -483,6 +483,7 @@ int cmd_tag(int argc,
+ 			.type = OPTION_INTEGER,
+ 			.short_name = 'n',
+ 			.value = &filter.lines,
++			.precision = sizeof(filter.lines),
+ 			.argh = N_("n"),
+ 			.help = N_("print <n> lines of each tag message"),
+ 			.flags = PARSE_OPT_OPTARG,
+diff --git a/parse-options.c b/parse-options.c
+index d23e587e98..768718a397 100644
+--- a/parse-options.c
++++ b/parse-options.c
+@@ -172,25 +172,51 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
+ 			return (*opt->ll_callback)(p, opt, p_arg, p_unset);
+ 	}
+ 	case OPTION_INTEGER:
++	{
++		intmax_t upper_bound = INTMAX_MAX >> (bitsizeof(intmax_t) - CHAR_BIT * opt->precision);
++		intmax_t lower_bound = -upper_bound - 1;
++		intmax_t value;
++
+ 		if (unset) {
+-			*(int *)opt->value = 0;
+-			return 0;
+-		}
+-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+-			*(int *)opt->value = opt->defval;
+-			return 0;
+-		}
+-		if (get_arg(p, opt, flags, &arg))
++			value = 0;
++		} else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
++			value = opt->defval;
++		} else if (get_arg(p, opt, flags, &arg)) {
+ 			return -1;
+-		if (!*arg)
++		} else if (!*arg) {
+ 			return error(_("%s expects a numerical value"),
+ 				     optname(opt, flags));
+-		if (!git_parse_int(arg, opt->value))
+-			return error(_("%s expects an integer value"
+-				       " with an optional k/m/g suffix"),
++		} else if (!git_parse_signed(arg, &value, upper_bound)) {
++			if (errno == ERANGE)
++				return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
++					     arg, optname(opt, flags), lower_bound, upper_bound);
++
++			return error(_("%s expects an integer value with an optional k/m/g suffix"),
+ 				     optname(opt, flags));
+-		return 0;
++		}
++
++		if (value < lower_bound)
++			return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
++				     arg, optname(opt, flags), lower_bound, upper_bound);
+ 
++		switch (opt->precision) {
++		case 1:
++			*(int8_t *)opt->value = value;
++			return 0;
++		case 2:
++			*(int16_t *)opt->value = value;
++			return 0;
++		case 4:
++			*(int32_t *)opt->value = value;
++			return 0;
++		case 8:
++			*(int64_t *)opt->value = value;
++			return 0;
++		default:
++			BUG("invalid precision for option %s",
++			    optname(opt, flags));
++		}
++	}
+ 	case OPTION_UNSIGNED:
+ 		if (unset) {
+ 			*(unsigned long *)opt->value = 0;
+diff --git a/parse-options.h b/parse-options.h
+index 14e4df1ee2..4c430c7273 100644
+--- a/parse-options.h
++++ b/parse-options.h
+@@ -92,6 +92,10 @@ typedef int parse_opt_subcommand_fn(int argc, const char **argv,
+  * `value`::
+  *   stores pointers to the values to be filled.
+  *
++ * `precision`::
++ *   precision of the integer pointed to by `value` in number of bytes. Should
++ *   typically be its `sizeof()`.
++ *
+  * `argh`::
+  *   token to explain the kind of argument this option wants. Does not
+  *   begin in capital letter, and does not end with a full stop.
+@@ -151,6 +155,7 @@ struct option {
+ 	int short_name;
+ 	const char *long_name;
+ 	void *value;
++	size_t precision;
+ 	const char *argh;
+ 	const char *help;
+ 
+@@ -214,6 +219,7 @@ struct option {
+ 	.short_name = (s), \
+ 	.long_name = (l), \
+ 	.value = (v), \
++	.precision = sizeof(*v), \
+ 	.argh = N_("n"), \
+ 	.help = (h), \
+ 	.flags = (f), \
+diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
+index fc3e2861c2..3689aee831 100644
+--- a/t/helper/test-parse-options.c
++++ b/t/helper/test-parse-options.c
+@@ -120,6 +120,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 	};
+ 	struct string_list expect = STRING_LIST_INIT_NODUP;
+ 	struct string_list list = STRING_LIST_INIT_NODUP;
++	int16_t i16 = 0;
+ 
+ 	struct option options[] = {
+ 		OPT_BOOL(0, "yes", &boolean, "get a boolean"),
+@@ -139,6 +140,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 		OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4),
+ 		OPT_GROUP(""),
+ 		OPT_INTEGER('i', "integer", &integer, "get a integer"),
++		OPT_INTEGER(0, "i16", &i16, "get a 16 bit integer"),
+ 		OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
+ 		OPT_UNSIGNED('u', "unsigned", &unsigned_integer, "get an unsigned integer"),
+ 		OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
+@@ -210,6 +212,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 	}
+ 	show(&expect, &ret, "boolean: %d", boolean);
+ 	show(&expect, &ret, "integer: %d", integer);
++	show(&expect, &ret, "i16: %"PRIdMAX, (intmax_t) i16);
+ 	show(&expect, &ret, "unsigned: %lu", unsigned_integer);
+ 	show(&expect, &ret, "timestamp: %"PRItime, timestamp);
+ 	show(&expect, &ret, "string: %s", string ? string : "(not set)");
+diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
+index 65a11c8dbc..be785547ea 100755
+--- a/t/t0040-parse-options.sh
++++ b/t/t0040-parse-options.sh
+@@ -22,6 +22,7 @@ usage: test-tool parse-options <options>
+ 
+     -i, --[no-]integer <n>
+                           get a integer
++    --[no-]i16 <n>        get a 16 bit integer
+     -j <n>                get a integer, too
+     -u, --unsigned <n>    get an unsigned integer
+     --[no-]set23          set integer to 23
+@@ -138,6 +139,7 @@ test_expect_success 'OPT_UNSIGNED() 3giga' '
+ cat >expect <<\EOF
+ boolean: 2
+ integer: 1729
++i16: 0
+ unsigned: 16384
+ timestamp: 0
+ string: 123
+@@ -158,6 +160,7 @@ test_expect_success 'short options' '
+ cat >expect <<\EOF
+ boolean: 2
+ integer: 1729
++i16: 9000
+ unsigned: 16384
+ timestamp: 0
+ string: 321
+@@ -169,7 +172,7 @@ file: prefix/fi.le
+ EOF
+ 
+ test_expect_success 'long options' '
+-	test-tool parse-options --boolean --integer 1729 --unsigned 16k \
++	test-tool parse-options --boolean --integer 1729 --i16 9000 --unsigned 16k \
+ 		--boolean --string2=321 --verbose --verbose --no-dry-run \
+ 		--abbrev=10 --file fi.le --obsolete \
+ 		>output 2>output.err &&
+@@ -181,6 +184,7 @@ test_expect_success 'abbreviate to something longer than SHA1 length' '
+ 	cat >expect <<-EOF &&
+ 	boolean: 0
+ 	integer: 0
++	i16: 0
+ 	unsigned: 0
+ 	timestamp: 0
+ 	string: (not set)
+@@ -255,6 +259,7 @@ test_expect_success 'superfluous value provided: cmdmode' '
+ cat >expect <<\EOF
+ boolean: 1
+ integer: 13
++i16: 0
+ unsigned: 0
+ timestamp: 0
+ string: 123
+@@ -278,6 +283,7 @@ test_expect_success 'intermingled arguments' '
+ cat >expect <<\EOF
+ boolean: 0
+ integer: 2
++i16: 0
+ unsigned: 0
+ timestamp: 0
+ string: (not set)
+@@ -345,6 +351,7 @@ cat >expect <<\EOF
+ Callback: "four", 0
+ boolean: 5
+ integer: 4
++i16: 0
+ unsigned: 0
+ timestamp: 0
+ string: (not set)
+@@ -370,6 +377,7 @@ test_expect_success 'OPT_CALLBACK() and callback errors work' '
+ cat >expect <<\EOF
+ boolean: 1
+ integer: 23
++i16: 0
+ unsigned: 0
+ timestamp: 0
+ string: (not set)
+@@ -449,6 +457,7 @@ test_expect_success 'OPT_NUMBER_CALLBACK() works' '
+ cat >expect <<\EOF
+ boolean: 0
+ integer: 0
++i16: 0
+ unsigned: 0
+ timestamp: 0
+ string: (not set)
+@@ -785,4 +794,16 @@ test_expect_success 'unsigned with units but no numbers' '
+ 	test_must_be_empty out
+ '
+ 
++test_expect_success 'i16 limits range' '
++	test-tool parse-options --i16 32767 >out &&
++	test_grep "i16: 32767" out &&
++	test_must_fail test-tool parse-options --i16 32768 2>err &&
++	test_grep "value 32768 for option .i16. not in range \[-32768,32767\]" err &&
++
++	test-tool parse-options --i16 -32768 >out &&
++	test_grep "i16: -32768" out &&
++	test_must_fail test-tool parse-options --i16 -32769 2>err &&
++	test_grep "value -32769 for option .i16. not in range \[-32768,32767\]" err
++'
++
+ test_done
+-- 
+2.39.5
+
diff -Nru git-2.49.0/debian/patches/0006-parse-options-introduce-precision-handling-for-OPTIO.patch git-2.49.0/debian/patches/0006-parse-options-introduce-precision-handling-for-OPTIO.patch
--- git-2.49.0/debian/patches/0006-parse-options-introduce-precision-handling-for-OPTIO.patch	1970-01-01 01:00:00.000000000 +0100
+++ git-2.49.0/debian/patches/0006-parse-options-introduce-precision-handling-for-OPTIO.patch	2025-05-29 17:33:17.000000000 +0200
@@ -0,0 +1,257 @@
+From bc288c59298f199348418ca08322046c67c9a0a2 Mon Sep 17 00:00:00 2001
+From: Patrick Steinhardt <p...@pks.im>
+Date: Thu, 17 Apr 2025 12:49:41 +0200
+Subject: [PATCH 6/7] parse-options: introduce precision handling for
+ `OPTION_UNSIGNED`
+
+This commit is the equivalent to the preceding commit, but instead of
+introducing precision handling for `OPTION_INTEGER` we introduce it for
+`OPTION_UNSIGNED`.
+
+Signed-off-by: Patrick Steinhardt <p...@pks.im>
+Signed-off-by: Junio C Hamano <gits...@pobox.com>
+---
+ parse-options.c               | 48 +++++++++++++++++++++++++++--------
+ parse-options.h               |  1 +
+ parse.c                       |  2 +-
+ parse.h                       |  1 +
+ t/helper/test-parse-options.c |  3 +++
+ t/t0040-parse-options.sh      | 18 ++++++++++++-
+ 6 files changed, 60 insertions(+), 13 deletions(-)
+
+diff --git a/parse-options.c b/parse-options.c
+index 768718a397..a9a39ecaef 100644
+--- a/parse-options.c
++++ b/parse-options.c
+@@ -197,7 +197,7 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
+ 
+ 		if (value < lower_bound)
+ 			return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
+-				     arg, optname(opt, flags), lower_bound, upper_bound);
++				     arg, optname(opt, flags), (intmax_t)lower_bound, (intmax_t)upper_bound);
+ 
+ 		switch (opt->precision) {
+ 		case 1:
+@@ -218,21 +218,47 @@ static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
+ 		}
+ 	}
+ 	case OPTION_UNSIGNED:
++	{
++		uintmax_t upper_bound = UINTMAX_MAX >> (bitsizeof(uintmax_t) - CHAR_BIT * opt->precision);
++		uintmax_t value;
++
+ 		if (unset) {
+-			*(unsigned long *)opt->value = 0;
+-			return 0;
+-		}
+-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+-			*(unsigned long *)opt->value = opt->defval;
+-			return 0;
+-		}
+-		if (get_arg(p, opt, flags, &arg))
++			value = 0;
++		} else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
++			value = opt->defval;
++		} else if (get_arg(p, opt, flags, &arg)) {
+ 			return -1;
+-		if (!git_parse_ulong(arg, opt->value))
++		} else if (!*arg) {
++			return error(_("%s expects a numerical value"),
++				     optname(opt, flags));
++		} else if (!git_parse_unsigned(arg, &value, upper_bound)) {
++			if (errno == ERANGE)
++				return error(_("value %s for %s not in range [%"PRIdMAX",%"PRIdMAX"]"),
++					     arg, optname(opt, flags), (uintmax_t) 0, upper_bound);
++
+ 			return error(_("%s expects a non-negative integer value"
+ 				       " with an optional k/m/g suffix"),
+ 				     optname(opt, flags));
+-		return 0;
++		}
++
++		switch (opt->precision) {
++		case 1:
++			*(uint8_t *)opt->value = value;
++			return 0;
++		case 2:
++			*(uint16_t *)opt->value = value;
++			return 0;
++		case 4:
++			*(uint32_t *)opt->value = value;
++			return 0;
++		case 8:
++			*(uint64_t *)opt->value = value;
++			return 0;
++		default:
++			BUG("invalid precision for option %s",
++			    optname(opt, flags));
++		}
++	}
+ 
+ 	default:
+ 		BUG("opt->type %d should not happen", opt->type);
+diff --git a/parse-options.h b/parse-options.h
+index 4c430c7273..dc460a26ff 100644
+--- a/parse-options.h
++++ b/parse-options.h
+@@ -281,6 +281,7 @@ struct option {
+ 	.short_name = (s), \
+ 	.long_name = (l), \
+ 	.value = (v), \
++	.precision = sizeof(*v), \
+ 	.argh = N_("n"), \
+ 	.help = (h), \
+ 	.flags = PARSE_OPT_NONEG, \
+diff --git a/parse.c b/parse.c
+index 3c47448ca6..48313571aa 100644
+--- a/parse.c
++++ b/parse.c
+@@ -51,7 +51,7 @@ int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
+ 	return 0;
+ }
+ 
+-static int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
++int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max)
+ {
+ 	if (value && *value) {
+ 		char *end;
+diff --git a/parse.h b/parse.h
+index 6bb9a54d9a..ea32de9a91 100644
+--- a/parse.h
++++ b/parse.h
+@@ -2,6 +2,7 @@
+ #define PARSE_H
+ 
+ int git_parse_signed(const char *value, intmax_t *ret, intmax_t max);
++int git_parse_unsigned(const char *value, uintmax_t *ret, uintmax_t max);
+ int git_parse_ssize_t(const char *, ssize_t *);
+ int git_parse_ulong(const char *, unsigned long *);
+ int git_parse_int(const char *value, int *ret);
+diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
+index 3689aee831..f2663dd0c0 100644
+--- a/t/helper/test-parse-options.c
++++ b/t/helper/test-parse-options.c
+@@ -120,6 +120,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 	};
+ 	struct string_list expect = STRING_LIST_INIT_NODUP;
+ 	struct string_list list = STRING_LIST_INIT_NODUP;
++	uint16_t u16 = 0;
+ 	int16_t i16 = 0;
+ 
+ 	struct option options[] = {
+@@ -143,6 +144,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 		OPT_INTEGER(0, "i16", &i16, "get a 16 bit integer"),
+ 		OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
+ 		OPT_UNSIGNED('u', "unsigned", &unsigned_integer, "get an unsigned integer"),
++		OPT_UNSIGNED(0, "u16", &u16, "get a 16 bit unsigned integer"),
+ 		OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
+ 		OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
+ 		OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
+@@ -214,6 +216,7 @@ int cmd__parse_options(int argc, const char **argv)
+ 	show(&expect, &ret, "integer: %d", integer);
+ 	show(&expect, &ret, "i16: %"PRIdMAX, (intmax_t) i16);
+ 	show(&expect, &ret, "unsigned: %lu", unsigned_integer);
++	show(&expect, &ret, "u16: %"PRIuMAX, (uintmax_t) u16);
+ 	show(&expect, &ret, "timestamp: %"PRItime, timestamp);
+ 	show(&expect, &ret, "string: %s", string ? string : "(not set)");
+ 	show(&expect, &ret, "abbrev: %d", abbrev);
+diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
+index be785547ea..ca55ea8228 100755
+--- a/t/t0040-parse-options.sh
++++ b/t/t0040-parse-options.sh
+@@ -25,6 +25,7 @@ usage: test-tool parse-options <options>
+     --[no-]i16 <n>        get a 16 bit integer
+     -j <n>                get a integer, too
+     -u, --unsigned <n>    get an unsigned integer
++    --u16 <n>             get a 16 bit unsigned integer
+     --[no-]set23          set integer to 23
+     --mode1               set integer to 1 (cmdmode option)
+     --mode2               set integer to 2 (cmdmode option)
+@@ -141,6 +142,7 @@ boolean: 2
+ integer: 1729
+ i16: 0
+ unsigned: 16384
++u16: 0
+ timestamp: 0
+ string: 123
+ abbrev: 7
+@@ -162,6 +164,7 @@ boolean: 2
+ integer: 1729
+ i16: 9000
+ unsigned: 16384
++u16: 32768
+ timestamp: 0
+ string: 321
+ abbrev: 10
+@@ -173,7 +176,7 @@ EOF
+ 
+ test_expect_success 'long options' '
+ 	test-tool parse-options --boolean --integer 1729 --i16 9000 --unsigned 16k \
+-		--boolean --string2=321 --verbose --verbose --no-dry-run \
++		--u16 32k --boolean --string2=321 --verbose --verbose --no-dry-run \
+ 		--abbrev=10 --file fi.le --obsolete \
+ 		>output 2>output.err &&
+ 	test_must_be_empty output.err &&
+@@ -186,6 +189,7 @@ test_expect_success 'abbreviate to something longer than SHA1 length' '
+ 	integer: 0
+ 	i16: 0
+ 	unsigned: 0
++	u16: 0
+ 	timestamp: 0
+ 	string: (not set)
+ 	abbrev: 100
+@@ -261,6 +265,7 @@ boolean: 1
+ integer: 13
+ i16: 0
+ unsigned: 0
++u16: 0
+ timestamp: 0
+ string: 123
+ abbrev: 7
+@@ -285,6 +290,7 @@ boolean: 0
+ integer: 2
+ i16: 0
+ unsigned: 0
++u16: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -353,6 +359,7 @@ boolean: 5
+ integer: 4
+ i16: 0
+ unsigned: 0
++u16: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -379,6 +386,7 @@ boolean: 1
+ integer: 23
+ i16: 0
+ unsigned: 0
++u16: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -459,6 +467,7 @@ boolean: 0
+ integer: 0
+ i16: 0
+ unsigned: 0
++u16: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 7
+@@ -806,4 +815,11 @@ test_expect_success 'i16 limits range' '
+ 	test_grep "value -32769 for option .i16. not in range \[-32768,32767\]" err
+ '
+ 
++test_expect_success 'u16 limits range' '
++	test-tool parse-options --u16 65535 >out &&
++	test_grep "u16: 65535" out &&
++	test_must_fail test-tool parse-options --u16 65536 2>err &&
++	test_grep "value 65536 for option .u16. not in range \[0,65535\]" err
++'
++
+ test_done
+-- 
+2.39.5
+
diff -Nru git-2.49.0/debian/patches/0007-parse-options-detect-mismatches-in-integer-signednes.patch git-2.49.0/debian/patches/0007-parse-options-detect-mismatches-in-integer-signednes.patch
--- git-2.49.0/debian/patches/0007-parse-options-detect-mismatches-in-integer-signednes.patch	1970-01-01 01:00:00.000000000 +0100
+++ git-2.49.0/debian/patches/0007-parse-options-detect-mismatches-in-integer-signednes.patch	2025-05-29 17:33:17.000000000 +0200
@@ -0,0 +1,160 @@
+From 791aeddfa2fdb9e830e24c50c97bb5e8bf3613e6 Mon Sep 17 00:00:00 2001
+From: Patrick Steinhardt <p...@pks.im>
+Date: Thu, 17 Apr 2025 12:49:42 +0200
+Subject: [PATCH 7/7] parse-options: detect mismatches in integer signedness
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It was reported that "t5620-backfill.sh" fails on s390x and sparc64 in a
+test that exercises the "--min-batch-size" command line option. The
+symptom was that the option didn't seem to have an effect: we didn't
+fetch objects with a batch size of 20, but instead fetched all objects
+at once.
+
+As it turns out, the root cause is that `--min-batch-size` uses
+`OPT_INTEGER()` to parse the command line option. While this macro
+expects the caller to pass a pointer to an integer, we instead pass a
+pointer to a `size_t`. This coincidentally works on most platforms, but
+it breaks apart on the mentioned platforms because they are big endian.
+
+This issue isn't specific to git-backfill(1): there are a couple of
+other places where we have the same type confusion going on. This
+indicates that the issue really is the interface that the parse-options
+subsystem provides -- it is simply too easy to get this wrong as there
+isn't any kind of compiler warning, and things just work on the most
+common systems.
+
+Address the systemic issue by introducing two new build asserts
+`BARF_UNLESS_SIGNED()` and `BARF_UNLESS_UNSIGNED()`. As the names
+already hint at, those macros will cause a compiler error when passed a
+value that is not signed or unsigned, respectively.
+
+Adapt `OPT_INTEGER()`, `OPT_UNSIGNED()` as well as `OPT_MAGNITUDE()` to
+use those asserts. This uncovers a small set of sites where we indeed
+have the same bug as in git-backfill(1). Adapt all of them to use the
+correct option.
+
+Reported-by: Todd Zullinger <t...@pobox.com>
+Reported-by: John Paul Adrian Glaubitz <glaub...@physik.fu-berlin.de>
+Helped-by: SZEDER Gábor <szeder....@gmail.com>
+Helped-by: Jeff King <p...@peff.net>
+Signed-off-by: Patrick Steinhardt <p...@pks.im>
+Signed-off-by: Junio C Hamano <gits...@pobox.com>
+---
+ apply.c            | 4 ++--
+ builtin/backfill.c | 4 ++--
+ builtin/column.c   | 2 +-
+ builtin/grep.c     | 4 ++--
+ git-compat-util.h  | 7 +++++++
+ parse-options.h    | 4 ++--
+ 6 files changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/apply.c b/apply.c
+index f274a37948..a850c7d75f 100644
+--- a/apply.c
++++ b/apply.c
+@@ -5123,8 +5123,8 @@ int apply_parse_options(int argc, const char **argv,
+ 		/* Think twice before adding "--nul" synonym to this */
+ 		OPT_SET_INT('z', NULL, &state->line_termination,
+ 			N_("paths are separated with NUL character"), '\0'),
+-		OPT_INTEGER('C', NULL, &state->p_context,
+-				N_("ensure at least <n> lines of context match")),
++		OPT_UNSIGNED('C', NULL, &state->p_context,
++			     N_("ensure at least <n> lines of context match")),
+ 		OPT_CALLBACK(0, "whitespace", state, N_("action"),
+ 			N_("detect new or modified lines that have whitespace errors"),
+ 			apply_option_parse_whitespace),
+diff --git a/builtin/backfill.c b/builtin/backfill.c
+index 33e1ea2f84..d95d7a2d4d 100644
+--- a/builtin/backfill.c
++++ b/builtin/backfill.c
+@@ -123,8 +123,8 @@ int cmd_backfill(int argc, const char **argv, const char *prefix, struct reposit
+ 		.sparse = 0,
+ 	};
+ 	struct option options[] = {
+-		OPT_INTEGER(0, "min-batch-size", &ctx.min_batch_size,
+-			    N_("Minimum number of objects to request at a time")),
++		OPT_UNSIGNED(0, "min-batch-size", &ctx.min_batch_size,
++			     N_("Minimum number of objects to request at a time")),
+ 		OPT_BOOL(0, "sparse", &ctx.sparse,
+ 			 N_("Restrict the missing objects to the current sparse-checkout")),
+ 		OPT_END(),
+diff --git a/builtin/column.c b/builtin/column.c
+index 50314cc255..ce6443d5fa 100644
+--- a/builtin/column.c
++++ b/builtin/column.c
+@@ -31,7 +31,7 @@ int cmd_column(int argc,
+ 	struct option options[] = {
+ 		OPT_STRING(0, "command", &real_command, N_("name"), N_("lookup config vars")),
+ 		OPT_COLUMN(0, "mode", &colopts, N_("layout to use")),
+-		OPT_INTEGER(0, "raw-mode", &colopts, N_("layout to use")),
++		OPT_UNSIGNED(0, "raw-mode", &colopts, N_("layout to use")),
+ 		OPT_INTEGER(0, "width", &copts.width, N_("maximum width")),
+ 		OPT_STRING(0, "indent", &copts.indent, N_("string"), N_("padding space on left border")),
+ 		OPT_STRING(0, "nl", &copts.nl, N_("string"), N_("padding space on right border")),
+diff --git a/builtin/grep.c b/builtin/grep.c
+index c4869733e1..f23a6f1dc8 100644
+--- a/builtin/grep.c
++++ b/builtin/grep.c
+@@ -983,9 +983,9 @@ int cmd_grep(int argc,
+ 		OPT_CALLBACK('C', "context", &opt, N_("n"),
+ 			N_("show <n> context lines before and after matches"),
+ 			context_callback),
+-		OPT_INTEGER('B', "before-context", &opt.pre_context,
++		OPT_UNSIGNED('B', "before-context", &opt.pre_context,
+ 			N_("show <n> context lines before matches")),
+-		OPT_INTEGER('A', "after-context", &opt.post_context,
++		OPT_UNSIGNED('A', "after-context", &opt.post_context,
+ 			N_("show <n> context lines after matches")),
+ 		OPT_INTEGER(0, "threads", &num_threads,
+ 			N_("use <n> worker threads")),
+diff --git a/git-compat-util.h b/git-compat-util.h
+index cf733b38ac..1218fcf81a 100644
+--- a/git-compat-util.h
++++ b/git-compat-util.h
+@@ -110,12 +110,19 @@ DISABLE_WARNING(-Wsign-compare)
+ # define BARF_UNLESS_COPYABLE(dst, src) \
+ 	BUILD_ASSERT_OR_ZERO(__builtin_types_compatible_p(__typeof__(*(dst)), \
+ 							  __typeof__(*(src))))
++
++# define BARF_UNLESS_SIGNED(var)   BUILD_ASSERT_OR_ZERO(((__typeof__(var)) -1) < 0)
++# define BARF_UNLESS_UNSIGNED(var) BUILD_ASSERT_OR_ZERO(((__typeof__(var)) -1) > 0)
+ #else
+ # define BARF_UNLESS_AN_ARRAY(arr) 0
+ # define BARF_UNLESS_COPYABLE(dst, src) \
+ 	BUILD_ASSERT_OR_ZERO(0 ? ((*(dst) = *(src)), 0) : \
+ 				 sizeof(*(dst)) == sizeof(*(src)))
++
++# define BARF_UNLESS_SIGNED(var)   0
++# define BARF_UNLESS_UNSIGNED(var) 0
+ #endif
++
+ /*
+  * ARRAY_SIZE - get the number of elements in a visible array
+  * @x: the array whose size you want.
+diff --git a/parse-options.h b/parse-options.h
+index dc460a26ff..91c3e3c29b 100644
+--- a/parse-options.h
++++ b/parse-options.h
+@@ -218,7 +218,7 @@ struct option {
+ 	.type = OPTION_INTEGER, \
+ 	.short_name = (s), \
+ 	.long_name = (l), \
+-	.value = (v), \
++	.value = (v) + BARF_UNLESS_SIGNED(*(v)), \
+ 	.precision = sizeof(*v), \
+ 	.argh = N_("n"), \
+ 	.help = (h), \
+@@ -280,7 +280,7 @@ struct option {
+ 	.type = OPTION_UNSIGNED, \
+ 	.short_name = (s), \
+ 	.long_name = (l), \
+-	.value = (v), \
++	.value = (v) + BARF_UNLESS_UNSIGNED(*(v)), \
+ 	.precision = sizeof(*v), \
+ 	.argh = N_("n"), \
+ 	.help = (h), \
+-- 
+2.39.5
+
diff -Nru git-2.49.0/debian/patches/series git-2.49.0/debian/patches/series
--- git-2.49.0/debian/patches/series	2025-05-29 17:25:41.000000000 +0200
+++ git-2.49.0/debian/patches/series	2025-06-06 18:07:16.000000000 +0200
@@ -1 +1,7 @@
-0001-parse-options-detect-mismatches-in-integer-signedness.diff
+0001-parse-fix-off-by-one-for-minimum-signed-values.patch
+0002-global-use-designated-initializers-for-options.patch
+0003-parse-options-support-unit-factors-in-OPT_INTEGER.patch
+0004-parse-options-rename-OPT_MAGNITUDE-to-OPT_UNSIGNED.patch
+0005-parse-options-introduce-precision-handling-for-OPTIO.patch
+0006-parse-options-introduce-precision-handling-for-OPTIO.patch
+0007-parse-options-detect-mismatches-in-integer-signednes.patch

Reply via email to