A typical "git revert" commit uses the full title of the original
commit in its title, and starts its body of the message with:
This reverts commit
8fa7f667cf61386257c00d6e954855cc3215ae91.
This does not encourage the best practice of describing not just
"what" (i.e. "Revert X" on the title says what we did) but "why"
(i.e. and it does not say why X was undesirable).
We can instead phrase this first line of the body to be more like
This reverts commit
8fa7f667 (do this and that, 2022-04-25)
so that the title does not have to be
Revert "do this and that"
We can instead use the title to describe "why" we are reverting the
original commit.
Introduce the "--reference" option to "git revert", and also the
revert.reference configuration variable, which defaults to false, to
tweak the title and the first line of the draft commit message for
when creating a "revert" commit.
When this option is in use, the first line of the pre-filled editor
buffer becomes a comment line that tells the user to say _why_. If
the user exits the editor without touching this line by mistake,
what we prepare to become the first line of the body, i.e. "This
reverts commit
8fa7f667 (do this and that, 2022-04-25)", ends up to
be the title of the resulting commit. This behaviour is designed to
help such a user to identify such a revert in "git log --oneline"
easily so that it can be further reworded with "git rebase -i" later.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
--- /dev/null
+revert.reference::
+ Setting this variable to true makes `git revert` to behave
+ as if the `--reference` option is given.
Allow the rerere mechanism to update the index with the
result of auto-conflict resolution if possible.
+--reference::
+ Instead of starting the body of the log message with "This
+ reverts <full object name of the commit being reverted>.",
+ refer to the commit using "--pretty=reference" format
+ (cf. linkgit:git-log[1]). The `revert.reference`
+ configuration variable can be used to enable this option by
+ default.
+
+
SEQUENCER SUBCOMMANDS
---------------------
include::sequencer.txt[]
N_("option for merge strategy"), option_parse_x),
{ OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"),
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+ OPT_BOOL(0, "reference", &opts->commit_use_reference,
+ N_("use the 'reference' format to refer to commits")),
OPT_END()
};
struct option *options = base_options;
return ret;
}
+ if (!strcmp(k, "revert.reference"))
+ opts->commit_use_reference = git_config_bool(k, v);
+
status = git_gpg_config(k, v, NULL);
if (status)
return status;
return opts->edit;
}
+static void refer_to_commit(struct replay_opts *opts,
+ struct strbuf *msgbuf, struct commit *commit)
+{
+ if (opts->commit_use_reference) {
+ struct pretty_print_context ctx = {
+ .abbrev = DEFAULT_ABBREV,
+ .date_mode.type = DATE_SHORT,
+ };
+ format_commit_message(commit, "%h (%s, %ad)", msgbuf, &ctx);
+ } else {
+ strbuf_addstr(msgbuf, oid_to_hex(&commit->object.oid));
+ }
+}
+
static int do_pick_commit(struct repository *r,
struct todo_item *item,
struct replay_opts *opts,
base_label = msg.label;
next = parent;
next_label = msg.parent_label;
- strbuf_addstr(&msgbuf, "Revert \"");
- strbuf_addstr(&msgbuf, msg.subject);
- strbuf_addstr(&msgbuf, "\"\n\nThis reverts commit ");
- strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
+ if (opts->commit_use_reference) {
+ strbuf_addstr(&msgbuf,
+ "# *** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
+ } else {
+ strbuf_addstr(&msgbuf, "Revert \"");
+ strbuf_addstr(&msgbuf, msg.subject);
+ strbuf_addstr(&msgbuf, "\"");
+ }
+ strbuf_addstr(&msgbuf, "\n\nThis reverts commit ");
+ refer_to_commit(opts, &msgbuf, commit);
if (commit->parents && commit->parents->next) {
strbuf_addstr(&msgbuf, ", reversing\nchanges made to ");
- strbuf_addstr(&msgbuf, oid_to_hex(&parent->object.oid));
+ refer_to_commit(opts, &msgbuf, parent);
}
strbuf_addstr(&msgbuf, ".\n");
} else {
int reschedule_failed_exec;
int committer_date_is_author_date;
int ignore_date;
+ int commit_use_reference;
int mainline;
'
test_expect_success 'advice from failed revert' '
+ test_when_finished "git reset --hard" &&
test_commit --no-tag "add dream" dream dream &&
dream_oid=$(git rev-parse --short HEAD) &&
cat <<-EOF >expected &&
test_must_fail git revert HEAD^ 2>actual &&
test_cmp expected actual
'
+
+test_expect_success 'identification of reverted commit (default)' '
+ test_commit to-ident &&
+ test_when_finished "git reset --hard to-ident" &&
+ git checkout --detach to-ident &&
+ git revert --no-edit HEAD &&
+ git cat-file commit HEAD >actual.raw &&
+ grep "^This reverts " actual.raw >actual &&
+ echo "This reverts commit $(git rev-parse HEAD^)." >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'identification of reverted commit (--reference)' '
+ git checkout --detach to-ident &&
+ git revert --reference --no-edit HEAD &&
+ git cat-file commit HEAD >actual.raw &&
+ grep "^This reverts " actual.raw >actual &&
+ echo "This reverts commit $(git show -s --pretty=reference HEAD^)." >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'identification of reverted commit (revert.reference)' '
+ git checkout --detach to-ident &&
+ git -c revert.reference=true revert --no-edit HEAD &&
+ git cat-file commit HEAD >actual.raw &&
+ grep "^This reverts " actual.raw >actual &&
+ echo "This reverts commit $(git show -s --pretty=reference HEAD^)." >expect &&
+ test_cmp expect actual
+'
+
test_done