builtin/history: split out extended function to create commits

In the next commit we're about to introduce a new command that splits up a commit into two. Most of the logic will be shared with rewording commits, except that we also need to have control over the parents and the old/new trees. Extract a new function `commit_tree_with_edited_message_ext()` to prepare for this commit. 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 98f839425db94eb8d4c1f773e923ba1cff622d66
1 file changed +40 -27
builtin/history.c
+40 -27
@@ -83,10 +83,13 @@ static int fill_commit_message(struct repository *repo,
83 return 0;
84 }
85
86 -static int commit_tree_with_edited_message(struct repository *repo,
87 - const char *action,
88 - struct commit *original,
89 - struct commit **out)
86 +static int commit_tree_with_edited_message_ext(struct repository *repo,
87 + const char *action,
88 + struct commit *commit_with_message,
89 + const struct commit_list *parents,
90 + const struct object_id *old_tree,
91 + const struct object_id *new_tree,
92 + struct commit **out)
93 {
94 const char *exclude_gpgsig[] = {
95 /* We reencode the message, so the encoding needs to be stripped. */
@@ -100,44 +103,27 @@ static int commit_tree_with_edited_message(struct repository *repo,
103 struct commit_extra_header *original_extra_headers = NULL;
104 struct strbuf commit_message = STRBUF_INIT;
105 struct object_id rewritten_commit_oid;
103 - struct object_id original_tree_oid;
104 - struct object_id parent_tree_oid;
106 char *original_author = NULL;
106 - struct commit *parent;
107 size_t len;
108 int ret;
109
110 - original_tree_oid = repo_get_commit_tree(repo, original)->object.oid;
111 -
112 - parent = original->parents ? original->parents->item : NULL;
113 - if (parent) {
114 - if (repo_parse_commit(repo, parent)) {
115 - ret = error(_("unable to parse parent commit %s"),
116 - oid_to_hex(&parent->object.oid));
117 - goto out;
118 - }
119 -
120 - parent_tree_oid = repo_get_commit_tree(repo, parent)->object.oid;
121 - } else {
122 - oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree);
123 - }
124 -
110 /* We retain authorship of the original commit. */
126 - original_message = repo_logmsg_reencode(repo, original, NULL, NULL);
111 + original_message = repo_logmsg_reencode(repo, commit_with_message, NULL, NULL);
112 ptr = find_commit_header(original_message, "author", &len);
113 if (ptr)
114 original_author = xmemdupz(ptr, len);
115 find_commit_subject(original_message, &original_body);
116
132 - ret = fill_commit_message(repo, &parent_tree_oid, &original_tree_oid,
117 + ret = fill_commit_message(repo, old_tree, new_tree,
118 original_body, action, &commit_message);
119 if (ret < 0)
120 goto out;
121
137 - original_extra_headers = read_commit_extra_headers(original, exclude_gpgsig);
122 + original_extra_headers = read_commit_extra_headers(commit_with_message,
123 + exclude_gpgsig);
124
139 - ret = commit_tree_extended(commit_message.buf, commit_message.len, &original_tree_oid,
140 - original->parents, &rewritten_commit_oid, original_author,
125 + ret = commit_tree_extended(commit_message.buf, commit_message.len, new_tree,
126 + parents, &rewritten_commit_oid, original_author,
127 NULL, NULL, original_extra_headers);
128 if (ret < 0)
129 goto out;
@@ -151,6 +137,33 @@ out:
137 return ret;
138 }
139
140 +static int commit_tree_with_edited_message(struct repository *repo,
141 + const char *action,
142 + struct commit *original,
143 + struct commit **out)
144 +{
145 + struct object_id parent_tree_oid;
146 + const struct object_id *tree_oid;
147 + struct commit *parent;
148 +
149 + tree_oid = &repo_get_commit_tree(repo, original)->object.oid;
150 +
151 + parent = original->parents ? original->parents->item : NULL;
152 + if (parent) {
153 + if (repo_parse_commit(repo, parent)) {
154 + return error(_("unable to parse parent commit %s"),
155 + oid_to_hex(&parent->object.oid));
156 + }
157 +
158 + parent_tree_oid = repo_get_commit_tree(repo, parent)->object.oid;
159 + } else {
160 + oidcpy(&parent_tree_oid, repo->hash_algo->empty_tree);
161 + }
162 +
163 + return commit_tree_with_edited_message_ext(repo, action, original, original->parents,
164 + &parent_tree_oid, tree_oid, out);
165 +}
166 +
167 enum ref_action {
168 REF_ACTION_DEFAULT,
169 REF_ACTION_BRANCHES,