add-patch: allow disabling editing of hunks

The "add-patch" mode allows the user to edit hunks to apply custom changes. This is incompatible with a new `git history split` command that we're about to introduce in a subsequent commit, so we need a way to disable this mode. Add a new flag to disable editing hunks. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Mar 2, 2026 at 13:13 UTC 48f6d9232834be661f0d1dc4f187b324124ccbe0
7 files changed +28 -15
add-interactive.c
+1 -1
@@ -927,7 +927,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
927 parse_pathspec(&ps_selected,
928 PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
929 PATHSPEC_LITERAL_PATH, "", args.v);
930 - res = run_add_p(s->r, ADD_P_ADD, &opts, NULL, &ps_selected);
930 + res = run_add_p(s->r, ADD_P_ADD, &opts, NULL, &ps_selected, 0);
931 strvec_clear(&args);
932 clear_pathspec(&ps_selected);
933 }
add-patch.c
+14 -8
@@ -1604,7 +1604,9 @@ static bool get_first_undecided(const struct file_diff *file_diff, size_t *idx)
1604 return false;
1605 }
1606
1607 -static size_t patch_update_file(struct add_p_state *s, size_t idx)
1607 +static size_t patch_update_file(struct add_p_state *s,
1608 + size_t idx,
1609 + unsigned flags)
1610 {
1611 size_t hunk_index = 0;
1612 ssize_t i, undecided_previous, undecided_next, rendered_hunk_index = -1;
@@ -1715,7 +1717,8 @@ static size_t patch_update_file(struct add_p_state *s, size_t idx)
1717 permitted |= ALLOW_SPLIT;
1718 strbuf_addstr(&s->buf, ",s");
1719 }
1718 - if (hunk_index + 1 > file_diff->mode_change &&
1720 + if (!(flags & ADD_P_DISALLOW_EDIT) &&
1721 + hunk_index + 1 > file_diff->mode_change &&
1722 !file_diff->deleted) {
1723 permitted |= ALLOW_EDIT;
1724 strbuf_addstr(&s->buf, ",e");
@@ -2003,7 +2006,8 @@ soft_increment:
2006 }
2007
2008 static int run_add_p_common(struct add_p_state *state,
2006 - const struct pathspec *ps)
2009 + const struct pathspec *ps,
2010 + unsigned flags)
2011 {
2012 size_t binary_count = 0;
2013 size_t i;
@@ -2017,7 +2021,7 @@ static int run_add_p_common(struct add_p_state *state,
2021 i++;
2022 continue;
2023 }
2020 - if ((i = patch_update_file(state, i)) == state->file_diff_nr)
2024 + if ((i = patch_update_file(state, i, flags)) == state->file_diff_nr)
2025 break;
2026 }
2027
@@ -2035,7 +2039,8 @@ static int run_add_p_common(struct add_p_state *state,
2039
2040 int run_add_p(struct repository *r, enum add_p_mode mode,
2041 struct interactive_options *opts, const char *revision,
2038 - const struct pathspec *ps)
2042 + const struct pathspec *ps,
2043 + unsigned flags)
2044 {
2045 struct add_p_state s = {
2046 .r = r,
@@ -2084,7 +2089,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
2089 goto out;
2090 }
2091
2087 - ret = run_add_p_common(&s, ps);
2092 + ret = run_add_p_common(&s, ps, flags);
2093 if (ret < 0)
2094 goto out;
2095
@@ -2100,7 +2105,8 @@ int run_add_p_index(struct repository *r,
2105 const char *index_file,
2106 struct interactive_options *opts,
2107 const char *revision,
2103 - const struct pathspec *ps)
2108 + const struct pathspec *ps,
2109 + unsigned flags)
2110 {
2111 struct patch_mode mode = {
2112 .apply_args = { "--cached", NULL },
@@ -2156,7 +2162,7 @@ int run_add_p_index(struct repository *r,
2162 mode.diff_cmd[1] = "-r";
2163 mode.diff_cmd[2] = parent_tree_oid;
2164
2159 - ret = run_add_p_common(&s, ps);
2165 + ret = run_add_p_common(&s, ps, flags);
2166 if (ret < 0)
2167 goto out;
2168
add-patch.h
+9 -2
@@ -53,15 +53,22 @@ enum add_p_mode {
53 ADD_P_WORKTREE,
54 };
55
56 +enum add_p_flags {
57 + /* Disallow "editing" hunks. */
58 + ADD_P_DISALLOW_EDIT = (1 << 0),
59 +};
60 +
61 int run_add_p(struct repository *r, enum add_p_mode mode,
62 struct interactive_options *opts, const char *revision,
58 - const struct pathspec *ps);
63 + const struct pathspec *ps,
64 + unsigned flags);
65
66 int run_add_p_index(struct repository *r,
67 struct index_state *index,
68 const char *index_file,
69 struct interactive_options *opts,
70 const char *revision,
65 - const struct pathspec *ps);
71 + const struct pathspec *ps,
72 + unsigned flags);
73
74 #endif
builtin/add.c
+1 -1
@@ -172,7 +172,7 @@ int interactive_add(struct repository *repo,
172 prefix, argv);
173
174 if (patch)
175 - ret = !!run_add_p(repo, ADD_P_ADD, interactive_opts, NULL, &pathspec);
175 + ret = !!run_add_p(repo, ADD_P_ADD, interactive_opts, NULL, &pathspec, 0);
176 else
177 ret = !!run_add_i(repo, &pathspec, interactive_opts);
178
builtin/checkout.c
+1 -1
@@ -563,7 +563,7 @@ static int checkout_paths(const struct checkout_opts *opts,
563 BUG("either flag must have been set, worktree=%d, index=%d",
564 opts->checkout_worktree, opts->checkout_index);
565 return !!run_add_p(the_repository, patch_mode, &interactive_opts,
566 - rev, &opts->pathspec);
566 + rev, &opts->pathspec, 0);
567 }
568
569 repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
builtin/reset.c
+1 -1
@@ -438,7 +438,7 @@ int cmd_reset(int argc,
438 die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
439 trace2_cmd_mode("patch-interactive");
440 update_ref_status = !!run_add_p(the_repository, ADD_P_RESET,
441 - &interactive_opts, rev, &pathspec);
441 + &interactive_opts, rev, &pathspec, 0);
442 goto cleanup;
443 } else {
444 if (interactive_opts.context != -1)
builtin/stash.c
+1 -1
@@ -1331,7 +1331,7 @@ static int stash_patch(struct stash_info *info, const struct pathspec *ps,
1331 old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
1332 setenv(INDEX_ENVIRONMENT, the_repository->index_file, 1);
1333
1334 - ret = !!run_add_p(the_repository, ADD_P_STASH, interactive_opts, NULL, ps);
1334 + ret = !!run_add_p(the_repository, ADD_P_STASH, interactive_opts, NULL, ps, 0);
1335
1336 the_repository->index_file = old_repo_index_file;
1337 if (old_index_env && *old_index_env)