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 <pclo...@gmail.com>
---
 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

Reply via email to