OK here is a less constroversal attempt to add new trailers. Instead
of changing the default behavior (which could be done incrementally
later), this patch simply adds a new option --append-trailer to revert
and cherry-pick.
Both will show either
Reverts: <commit>[~<num>]
or
Cherry-picked-from: <commit>[~<num>]
--append-trailer could be added to more commands (e.g. merge) that
generate commit messages if they have something for machine
consumption.
After this, perhaps we could have a config key to turn this on by
default (for revert; for cherry-pick it will turn off "-x" too). Then
after a couple releases, the we got good reception, we'll make it
default?
No tests, no proper commit message since I think we're still going to
discuss a bit more before settling down.
PS. maybe --append-trailer is too generic? We have --signoff which is
also a trailer. But that one carries more weights than just "machine
generated tags".
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]>
---
Documentation/git-cherry-pick.txt | 6 +++++
Documentation/git-revert.txt | 6 +++++
builtin/revert.c | 7 ++++++
sequencer.c | 39 +++++++++++++++++++++++++++----
sequencer.h | 1 +
5 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-cherry-pick.txt
b/Documentation/git-cherry-pick.txt
index d35d771fc8..b5dff29ead 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -102,6 +102,12 @@ effect to your index in a row.
Add Signed-off-by line at the end of the commit message.
See the signoff option in linkgit:git-commit[1] for more information.
+--append-trailer::
+ When recording a commit, append a "Cherry-picked-from:" line
+ with object name of the cherry-picked commit. If a merge is
+ cherry-picked with `-m`, the extended SHA-1 syntax is used
+ to indicate the side of the merge to be cherry-picked.
+
-S[<keyid>]::
--gpg-sign[=<keyid>]::
GPG-sign commits. The `keyid` argument is optional and
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index 837707a8fd..e08010b200 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -91,6 +91,12 @@ effect to your index in a row.
Add Signed-off-by line at the end of the commit message.
See the signoff option in linkgit:git-commit[1] for more information.
+--append-trailer::
+ When recording a commit, append a "Cherry-picked-from:" line
+ with object name of the cherry-picked commit. If a merge is
+ cherry-picked with `-m`, the extended SHA-1 syntax is used
+ to indicate the side of the merge to be cherry-picked.
+
--strategy=<strategy>::
Use the given merge strategy. Should only be used once.
See the MERGE STRATEGIES section in linkgit:git-merge[1]
diff --git a/builtin/revert.c b/builtin/revert.c
index c93393c89b..3bd8f57b90 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -119,6 +119,7 @@ static int run_sequencer(int argc, const char **argv,
struct replay_opts *opts)
if (opts->action == REPLAY_PICK) {
struct option cp_extra[] = {
OPT_BOOL('x', NULL, &opts->record_origin, N_("append
commit name")),
+ OPT_BOOL(0, "append-trailer", &opts->append_trailer,
N_("record cherry picked commit as trailer")),
OPT_BOOL(0, "ff", &opts->allow_ff, N_("allow
fast-forward")),
OPT_BOOL(0, "allow-empty", &opts->allow_empty,
N_("preserve initially empty commits")),
OPT_BOOL(0, "allow-empty-message",
&opts->allow_empty_message, N_("allow commits with empty messages")),
@@ -126,6 +127,12 @@ static int run_sequencer(int argc, const char **argv,
struct replay_opts *opts)
OPT_END(),
};
options = parse_options_concat(options, cp_extra);
+ } else if (opts->action == REPLAY_REVERT) {
+ struct option cp_extra[] = {
+ OPT_BOOL(0, "append-trailer", &opts->append_trailer,
N_("record reverted commit as trailer")),
+ OPT_END(),
+ };
+ options = parse_options_concat(options, cp_extra);
}
argc = parse_options(argc, argv, NULL, options, usage_str,
diff --git a/sequencer.c b/sequencer.c
index 9e1ab3a2a7..e8fa307109 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -911,7 +911,7 @@ static int run_git_commit(const char *defmsg, struct
replay_opts *opts,
if ((flags & EDIT_MSG))
argv_array_push(&cmd.args, "-e");
else if (!(flags & CLEANUP_MSG) &&
- !opts->signoff && !opts->record_origin &&
+ !opts->signoff && !opts->record_origin &&
!opts->append_trailer &&
git_config_get_value("commit.cleanup", &value))
argv_array_push(&cmd.args, "--cleanup=verbatim");
@@ -1669,7 +1669,7 @@ static int do_pick_commit(enum todo_command command,
struct commit *commit,
char *author = NULL;
struct commit_message msg = { NULL, NULL, NULL, NULL };
struct strbuf msgbuf = STRBUF_INIT;
- int res, unborn = 0, allow;
+ int res, unborn = 0, allow, parent_id = -1;
if (opts->no_commit) {
/*
@@ -1716,6 +1716,7 @@ static int do_pick_commit(enum todo_command command,
struct commit *commit,
return error(_("commit %s does not have parent %d"),
oid_to_hex(&commit->object.oid),
opts->mainline);
parent = p->item;
+ parent_id = cnt;
} else if (0 < opts->mainline)
return error(_("mainline was specified but commit %s is not a
merge."),
oid_to_hex(&commit->object.oid));
@@ -1768,6 +1769,17 @@ static int do_pick_commit(enum todo_command command,
struct commit *commit,
strbuf_addstr(&msgbuf, oid_to_hex(&parent->object.oid));
}
strbuf_addstr(&msgbuf, ".\n");
+
+ if (opts->append_trailer) {
+ strbuf_addstr(&msgbuf, "\n");
+ if (parent_id != -1)
+ strbuf_addf(&msgbuf, "Reverts: %s~%d\n",
+ oid_to_hex(&commit->object.oid),
+ parent_id);
+ else
+ strbuf_addf(&msgbuf, "Reverts: %s\n",
+ oid_to_hex(&commit->object.oid));
+ }
} else {
const char *p;
@@ -1780,14 +1792,28 @@ static int do_pick_commit(enum todo_command command,
struct commit *commit,
if (find_commit_subject(msg.message, &p))
strbuf_addstr(&msgbuf, p);
- if (opts->record_origin) {
+ if (opts->record_origin || opts->append_trailer) {
strbuf_complete_line(&msgbuf);
if (!has_conforming_footer(&msgbuf, NULL, 0))
strbuf_addch(&msgbuf, '\n');
+ }
+
+ if (opts->record_origin) {
strbuf_addstr(&msgbuf, cherry_picked_prefix);
strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
strbuf_addstr(&msgbuf, ")\n");
}
+ if (opts->append_trailer) {
+ if (opts->record_origin)
+ strbuf_addstr(&msgbuf, "\n");
+ if (parent_id != -1)
+ strbuf_addf(&msgbuf, "Cherry-picked-from:
%s~%d\n",
+ oid_to_hex(&commit->object.oid),
+ parent_id);
+ else
+ strbuf_addf(&msgbuf, "Cherry-picked-from: %s\n",
+ oid_to_hex(&commit->object.oid));
+ }
if (!is_fixup(command))
author = get_author(msg.message);
}
@@ -2227,6 +2253,8 @@ static int populate_opts_cb(const char *key, const char
*value, void *data)
opts->signoff = git_config_bool_or_int(key, value, &error_flag);
else if (!strcmp(key, "options.record-origin"))
opts->record_origin = git_config_bool_or_int(key, value,
&error_flag);
+ else if (!strcmp(key, "options.append-trailer"))
+ opts->append_trailer = git_config_bool_or_int(key, value,
&error_flag);
else if (!strcmp(key, "options.allow-ff"))
opts->allow_ff = git_config_bool_or_int(key, value,
&error_flag);
else if (!strcmp(key, "options.mainline"))
@@ -2618,6 +2646,8 @@ static int save_opts(struct replay_opts *opts)
res |= git_config_set_in_file_gently(opts_file,
"options.signoff", "true");
if (opts->record_origin)
res |= git_config_set_in_file_gently(opts_file,
"options.record-origin", "true");
+ if (opts->append_trailer)
+ res |= git_config_set_in_file_gently(opts_file,
"options.append-trailer", "true");
if (opts->allow_ff)
res |= git_config_set_in_file_gently(opts_file,
"options.allow-ff", "true");
if (opts->mainline) {
@@ -3432,7 +3462,8 @@ static int pick_commits(struct todo_list *todo_list,
struct replay_opts *opts)
setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
if (opts->allow_ff)
assert(!(opts->signoff || opts->no_commit ||
- opts->record_origin || opts->edit));
+ opts->record_origin || opts->append_trailer ||
+ opts->edit));
if (read_and_refresh_cache(opts))
return -1;
diff --git a/sequencer.h b/sequencer.h
index 660cff5050..7d7c1fe6b4 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -31,6 +31,7 @@ struct replay_opts {
/* Boolean options */
int edit;
int record_origin;
+ int append_trailer;
int no_commit;
int signoff;
int allow_ff;
--
2.19.1.1005.gac84295441