* [PATCH v2 0/2] git pull/merge --compact-summary
@ 2025-06-12 22:25 Junio C Hamano
2025-06-12 22:25 ` [PATCH v2 1/2] merge/pull: --compact-summary Junio C Hamano
2025-06-12 22:25 ` [PATCH v2 2/2] merge/pull: extend merge.stat configuration variable to cover --compact-summary Junio C Hamano
0 siblings, 2 replies; 7+ messages in thread
From: Junio C Hamano @ 2025-06-12 22:25 UTC (permalink / raw)
To: git
By default, "git merge" and "git pull" shows "git diff --stat @{1}"
to show the extent of the changes. While it gives a good overview,
one thing that is missing in this output is which paths are created
and/or deleted.
With these two patches, these commands learn "--compact-summary"
command line option and a new value "compact" for the existing
merge.stat configuration variable, to change that final output to
use "git diff --compact-summary @{1}" instead.
I sent this out with random fix-ups in separate threads but never
made a formal patch series. Here are the earlier messages:
https://lore.kernel.org/git/xmqq5xh6xlpm.fsf@gitster.g/
https://lore.kernel.org/git/xmqqfrg6i57t.fsf@gitster.g/
Junio C Hamano (2):
merge/pull: --compact-summary
merge/pull: extend merge.stat configuration variable to cover
--compact-summary
Documentation/config/merge.adoc | 12 ++++++--
Documentation/git-merge.adoc | 2 +-
Documentation/merge-options.adoc | 3 ++
builtin/merge.c | 53 +++++++++++++++++++++++++++++---
builtin/pull.c | 3 ++
t/t7600-merge.sh | 43 +++++++++++++++++++++++++-
6 files changed, 108 insertions(+), 8 deletions(-)
--
2.50.0-rc2-255-gd84100c98d
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] merge/pull: --compact-summary
2025-06-12 22:25 [PATCH v2 0/2] git pull/merge --compact-summary Junio C Hamano
@ 2025-06-12 22:25 ` Junio C Hamano
2025-06-13 12:07 ` Kristoffer Haugsbakk
2025-06-12 22:25 ` [PATCH v2 2/2] merge/pull: extend merge.stat configuration variable to cover --compact-summary Junio C Hamano
1 sibling, 1 reply; 7+ messages in thread
From: Junio C Hamano @ 2025-06-12 22:25 UTC (permalink / raw)
To: git
By default, "git merge" and "git pull" shows "git diff --stat @{1}"
to show the extent of the changes. While it gives a good overview,
one thing that is missing in this output is which paths are created
and/or deleted.
Introduce "--compact-summary" option to these two commands that
tells it to instead show "git diff --compact-summary @{1}", which
gives the same diffstat but notes the created or deleted paths.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/git-merge.adoc | 2 +-
Documentation/merge-options.adoc | 3 +++
builtin/merge.c | 39 ++++++++++++++++++++++++++++----
builtin/pull.c | 3 +++
t/t7600-merge.sh | 28 ++++++++++++++++++++++-
5 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-merge.adoc b/Documentation/git-merge.adoc
index 12aa859d16..d53923c3b7 100644
--- a/Documentation/git-merge.adoc
+++ b/Documentation/git-merge.adoc
@@ -9,7 +9,7 @@ git-merge - Join two or more development histories together
SYNOPSIS
--------
[synopsis]
-git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
+git merge [-n] [--stat] [--compact-summary] [--no-commit] [--squash] [--[no-]edit]
[--no-verify] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]]
[--[no-]allow-unrelated-histories]
[--[no-]rerere-autoupdate] [-m <msg>] [-F <file>]
diff --git a/Documentation/merge-options.adoc b/Documentation/merge-options.adoc
index 078f4f6157..95ef491be1 100644
--- a/Documentation/merge-options.adoc
+++ b/Documentation/merge-options.adoc
@@ -113,6 +113,9 @@ include::signoff-option.adoc[]
With `-n` or `--no-stat` do not show a diffstat at the end of the
merge.
+`--compact-summary`::
+ Show a compact-summary at the end of the merge.
+
`--squash`::
`--no-squash`::
Produce the working tree and index state as if a real merge
diff --git a/builtin/merge.c b/builtin/merge.c
index ce90e52fe4..736739d3a9 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -69,7 +69,10 @@ static const char * const builtin_merge_usage[] = {
NULL
};
-static int show_diffstat = 1, shortlog_len = -1, squash;
+#define MERGE_SHOW_DIFFSTAT 1
+#define MERGE_SHOW_COMPACTSUMMARY 2
+
+static int show_diffstat = MERGE_SHOW_DIFFSTAT, shortlog_len = -1, squash;
static int option_commit = -1;
static int option_edit = -1;
static int allow_trivial = 1, have_message, verify_signatures;
@@ -243,12 +246,28 @@ static int option_parse_strategy(const struct option *opt UNUSED,
return 0;
}
+static int option_parse_compact_summary(const struct option *opt,
+ const char *name UNUSED, int unset)
+{
+ int *setting = opt->value;
+
+ if (unset)
+ *setting = 0;
+ else
+ *setting = MERGE_SHOW_COMPACTSUMMARY;
+ return 0;
+}
+
static struct option builtin_merge_options[] = {
OPT_SET_INT('n', NULL, &show_diffstat,
N_("do not show a diffstat at the end of the merge"), 0),
OPT_BOOL(0, "stat", &show_diffstat,
N_("show a diffstat at the end of the merge")),
OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
+ OPT_CALLBACK_F(0, "compact-summary", &show_diffstat, N_("compact-summary"),
+ N_("show a compactstat at the end of the merge"),
+ PARSE_OPT_NOARG,
+ option_parse_compact_summary),
{
.type = OPTION_INTEGER,
.long_name = "log",
@@ -494,8 +513,19 @@ static void finish(struct commit *head_commit,
struct diff_options opts;
repo_diff_setup(the_repository, &opts);
init_diffstat_widths(&opts);
- opts.output_format |=
- DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
+
+ switch (show_diffstat) {
+ case MERGE_SHOW_DIFFSTAT: /* 1 */
+ opts.output_format |=
+ DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
+ break;
+ case MERGE_SHOW_COMPACTSUMMARY: /* 2 */
+ opts.output_format |= DIFF_FORMAT_DIFFSTAT;
+ opts.flags.stat_with_summary = 1;
+ break;
+ default:
+ break;
+ }
opts.detect_rename = DIFF_DETECT_RENAME;
diff_setup_done(&opts);
diff_tree_oid(head, new_head, "", &opts);
@@ -643,7 +673,8 @@ static int git_merge_config(const char *k, const char *v,
}
if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat")) {
- show_diffstat = git_config_bool(k, v);
+ show_diffstat = git_config_bool(k, v)
+ ? MERGE_SHOW_DIFFSTAT : 0;
} else if (!strcmp(k, "merge.verifysignatures")) {
verify_signatures = git_config_bool(k, v);
} else if (!strcmp(k, "pull.twohead")) {
diff --git a/builtin/pull.c b/builtin/pull.c
index a1ebc6ad33..6e72a2e9a4 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -143,6 +143,9 @@ static struct option pull_options[] = {
OPT_PASSTHRU(0, "summary", &opt_diffstat, NULL,
N_("(synonym to --stat)"),
PARSE_OPT_NOARG | PARSE_OPT_HIDDEN),
+ OPT_PASSTHRU(0, "compact-summary", &opt_diffstat, NULL,
+ N_("show a compact-summary at the end of the merge"),
+ PARSE_OPT_NOARG),
OPT_PASSTHRU(0, "log", &opt_log, N_("n"),
N_("add (at most <n>) entries from shortlog to merge commit message"),
PARSE_OPT_OPTARG),
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 2a8df29219..2972922b6a 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -185,8 +185,19 @@ test_expect_success 'reject non-strategy with a git-merge-foo name' '
test_expect_success 'merge c0 with c1' '
echo "OBJID HEAD@{0}: merge c1: Fast-forward" >reflog.expected &&
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ create mode 100644 other
+ EOF
+
git reset --hard c0 &&
- git merge c1 &&
+ git merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual &&
verify_merge file result.1 &&
verify_head "$c1" &&
@@ -205,6 +216,21 @@ test_expect_success 'merge c0 with c1 with --ff-only' '
verify_head "$c1"
'
+test_expect_success 'the same merge with compact summary' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git merge --compact-summary c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge from unborn branch' '
--
2.50.0-rc2-255-gd84100c98d
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] merge/pull: extend merge.stat configuration variable to cover --compact-summary
2025-06-12 22:25 [PATCH v2 0/2] git pull/merge --compact-summary Junio C Hamano
2025-06-12 22:25 ` [PATCH v2 1/2] merge/pull: --compact-summary Junio C Hamano
@ 2025-06-12 22:25 ` Junio C Hamano
2025-06-13 12:09 ` Kristoffer Haugsbakk
1 sibling, 1 reply; 7+ messages in thread
From: Junio C Hamano @ 2025-06-12 22:25 UTC (permalink / raw)
To: git
Existing `merge.stat` configuration variable is a Boolean that
defaults to `true` to control `git merge --[no-]stat` behaviour.
Extend it to be "Boolean or text", that takes false, true, or
"compact", with the last one triggering the --compact-summary
option introduced earlier.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/config/merge.adoc | 12 ++++++++++--
builtin/merge.c | 18 ++++++++++++++++--
t/t7600-merge.sh | 15 +++++++++++++++
3 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/Documentation/config/merge.adoc b/Documentation/config/merge.adoc
index 86359f6dd2..251a48fdf8 100644
--- a/Documentation/config/merge.adoc
+++ b/Documentation/config/merge.adoc
@@ -81,8 +81,16 @@ as `false`. Defaults to `conflict`.
attributes" in linkgit:gitattributes[5].
`merge.stat`::
- Whether to print the diffstat between `ORIG_HEAD` and the merge result
- at the end of the merge. True by default.
+ What, if anything, to print between `ORIG_HEAD` and the merge result
+ at the end of the merge. Possible values are:
++
+--
+`false`;; Show nothing.
+`true`;; Show `git diff --diffstat ORIG_HEAD`.
+`compact`;; Show `git diff --compact-summary ORIG_HEAD`.
+--
++
+If this variable is left unspecified, it defaults to `true`.
`merge.autoStash`::
When set to `true`, automatically create a temporary stash entry
diff --git a/builtin/merge.c b/builtin/merge.c
index 736739d3a9..65fed4b687 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -673,8 +673,22 @@ static int git_merge_config(const char *k, const char *v,
}
if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat")) {
- show_diffstat = git_config_bool(k, v)
- ? MERGE_SHOW_DIFFSTAT : 0;
+ int val = git_parse_maybe_bool_text(v);
+ switch (val) {
+ case 0:
+ show_diffstat = 0;
+ break;
+ case 1:
+ show_diffstat = MERGE_SHOW_DIFFSTAT;
+ break;
+ default:
+ if (!strcmp(v, "compact"))
+ show_diffstat = MERGE_SHOW_COMPACTSUMMARY;
+ else
+ /* setting from the future -- use the default */
+ show_diffstat = MERGE_SHOW_DIFFSTAT;
+ break;
+ }
} else if (!strcmp(k, "merge.verifysignatures")) {
verify_signatures = git_config_bool(k, v);
} else if (!strcmp(k, "pull.twohead")) {
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 2972922b6a..8046c6bb54 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -231,6 +231,21 @@ test_expect_success 'the same merge with compact summary' '
test_cmp expect actual
'
+test_expect_success 'the same merge with merge.stat=compact' '
+ cat >expect <<-\EOF &&
+ Updating FROM..TO
+ Fast-forward
+ file | 2 +-
+ other (new) | 9 +++++++++
+ 2 files changed, 10 insertions(+), 1 deletion(-)
+ EOF
+
+ git reset --hard c0 &&
+ git -c merge.stat=compact merge c1 >out &&
+ sed -e "1s/^Updating [0-9a-f.]*/Updating FROM..TO/" out >actual &&
+ test_cmp expect actual
+'
+
test_debug 'git log --graph --decorate --oneline --all'
test_expect_success 'merge from unborn branch' '
--
2.50.0-rc2-255-gd84100c98d
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] merge/pull: --compact-summary
2025-06-12 22:25 ` [PATCH v2 1/2] merge/pull: --compact-summary Junio C Hamano
@ 2025-06-13 12:07 ` Kristoffer Haugsbakk
2025-06-13 16:26 ` Junio C Hamano
0 siblings, 1 reply; 7+ messages in thread
From: Kristoffer Haugsbakk @ 2025-06-13 12:07 UTC (permalink / raw)
To: Junio C Hamano, git
On Fri, Jun 13, 2025, at 00:25, Junio C Hamano wrote:
> static struct option builtin_merge_options[] = {
> OPT_SET_INT('n', NULL, &show_diffstat,
> N_("do not show a diffstat at the end of the merge"), 0),
> OPT_BOOL(0, "stat", &show_diffstat,
> N_("show a diffstat at the end of the merge")),
> OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
> + OPT_CALLBACK_F(0, "compact-summary", &show_diffstat, N_("compact-summary"),
> + N_("show a compactstat at the end of the merge"),
> + PARSE_OPT_NOARG,
> + option_parse_compact_summary),
`compactstat` is very dense. s/compactstat/compact stat/ ?
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] merge/pull: extend merge.stat configuration variable to cover --compact-summary
2025-06-12 22:25 ` [PATCH v2 2/2] merge/pull: extend merge.stat configuration variable to cover --compact-summary Junio C Hamano
@ 2025-06-13 12:09 ` Kristoffer Haugsbakk
2025-06-13 16:38 ` Junio C Hamano
0 siblings, 1 reply; 7+ messages in thread
From: Kristoffer Haugsbakk @ 2025-06-13 12:09 UTC (permalink / raw)
To: Junio C Hamano, git
On Fri, Jun 13, 2025, at 00:25, Junio C Hamano wrote:
> Extend it to be "Boolean or text", that takes false, true, or
> "compact", with the last one triggering the --compact-summary
> option introduced earlier.
Would it make sense to make `diffstat` an alias for `true`? I’m not
sure since you need to keep `true` anyway so you still have that
historical artifact (?)[1] of `true` meaning `diffstat`.
† 1: In the sense of what was added first
Also
> "compact", with the last one triggering the --compact-summary
> option introduced earlier.
So `merge.stat` can be used instead of `--compact-summary`. But now the
option does not mention `merge.stat`?
> `merge.stat`::
> - Whether to print the diffstat between `ORIG_HEAD` and the merge result
> - at the end of the merge. True by default.
> + What, if anything, to print between `ORIG_HEAD` and the merge result
> + at the end of the merge. Possible values are:
> ++
> +--
> +`false`;; Show nothing.
> +`true`;; Show `git diff --diffstat ORIG_HEAD`.
> +`compact`;; Show `git diff --compact-summary ORIG_HEAD`.
I can’t run `git diff --diffstat ORIG_HEAD`. `--diffstat` is not
an option.
> +If this variable is left unspecified, it defaults to `true`.
I think this is simpler:
Defaults to `true`.
There’s also several places in this doc which uses something similar
judging by a search for “defaults to”. Only exception is
`merge.renameLimit`:
If not specified, defaults to
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] merge/pull: --compact-summary
2025-06-13 12:07 ` Kristoffer Haugsbakk
@ 2025-06-13 16:26 ` Junio C Hamano
0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2025-06-13 16:26 UTC (permalink / raw)
To: Kristoffer Haugsbakk; +Cc: git
"Kristoffer Haugsbakk" <kristofferhaugsbakk@fastmail.com> writes:
> On Fri, Jun 13, 2025, at 00:25, Junio C Hamano wrote:
>> static struct option builtin_merge_options[] = {
>> OPT_SET_INT('n', NULL, &show_diffstat,
>> N_("do not show a diffstat at the end of the merge"), 0),
>> OPT_BOOL(0, "stat", &show_diffstat,
>> N_("show a diffstat at the end of the merge")),
>> OPT_BOOL(0, "summary", &show_diffstat, N_("(synonym to --stat)")),
>> + OPT_CALLBACK_F(0, "compact-summary", &show_diffstat, N_("compact-summary"),
>> + N_("show a compactstat at the end of the merge"),
>> + PARSE_OPT_NOARG,
>> + option_parse_compact_summary),
>
> `compactstat` is very dense. s/compactstat/compact stat/ ?
Nice spotting. I think "compact summary" (to match the diff option
"--compact-summary") may be even better.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] merge/pull: extend merge.stat configuration variable to cover --compact-summary
2025-06-13 12:09 ` Kristoffer Haugsbakk
@ 2025-06-13 16:38 ` Junio C Hamano
0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2025-06-13 16:38 UTC (permalink / raw)
To: Kristoffer Haugsbakk; +Cc: git
"Kristoffer Haugsbakk" <kristofferhaugsbakk@fastmail.com> writes:
> On Fri, Jun 13, 2025, at 00:25, Junio C Hamano wrote:
>> Extend it to be "Boolean or text", that takes false, true, or
>> "compact", with the last one triggering the --compact-summary
>> option introduced earlier.
>
> Would it make sense to make `diffstat` an alias for `true`? I’m not
> sure since you need to keep `true` anyway so you still have that
> historical artifact (?)[1] of `true` meaning `diffstat`.
Correct. But people can bikeshed about adding such synonyms later
without breaking existing users, so I would not consider such a
tweak for the initial version.
> There’s also several places in this doc which uses something similar
> judging by a search for “defaults to”. Only exception is
> `merge.renameLimit`:
>
> If not specified, defaults to
Having something before "Defaults to X" (like "if left unspecified"
etc.) may not be logically and technically needed, as that is the
definion of what the "default" is.
Having said that, I somehow find the resulting sentence easier to
read with such an introducer, but perhaps it is just me.
Among the output of
$ git grep -E -i ', default' Documentation/
we already have quite a few of them.
Thanks.
Documentation/config/commitgraph.adoc:repository, defaulting to 1 if there are none.
Documentation/config/merge.adoc: rename detection during a merge. If not specified, defaults
Documentation/fetch-options.adoc:is set (see linkgit:git-config[1]), defaulting to 'on-demand' if unset.
Documentation/git-init.adoc:The option can have the following values, defaulting to `group` if no value
Documentation/git-send-email.adoc:value; if that is unspecified, default to `auto`.
Documentation/git-send-email.adoc: value; if that is unspecified, default to --signed-off-by-cc.
Documentation/git-send-email.adoc: configuration value; if that is unspecified, default to --no-cc-cover.
Documentation/git-send-email.adoc: configuration value; if that is unspecified, default to --no-to-cover.
Documentation/git-send-email.adoc:that is unspecified, default to 'self' if --suppress-from is
Documentation/git-send-email.adoc: value; if that is unspecified, default to --no-suppress-from.
Documentation/git-send-email.adoc:is unspecified, default to 'auto' unless any of the suppress options
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-06-13 16:38 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-12 22:25 [PATCH v2 0/2] git pull/merge --compact-summary Junio C Hamano
2025-06-12 22:25 ` [PATCH v2 1/2] merge/pull: --compact-summary Junio C Hamano
2025-06-13 12:07 ` Kristoffer Haugsbakk
2025-06-13 16:26 ` Junio C Hamano
2025-06-12 22:25 ` [PATCH v2 2/2] merge/pull: extend merge.stat configuration variable to cover --compact-summary Junio C Hamano
2025-06-13 12:09 ` Kristoffer Haugsbakk
2025-06-13 16:38 ` Junio C Hamano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox