{"thread":{"id":"65524","subject":"[PATCH] commit -v: add --word-diff opt to commit template","startedAt":"2026-04-20T20:14:02Z","lastAt":"2026-04-20T20:14:02Z","messageCount":1,"participants":["Kraktus via GitGitGadget"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"541991","messageId":"pull.2276.git.git.1776716038088.gitgitgadget@gmail.com","threadId":"65524","inReplyTo":null,"subject":"[PATCH] commit -v: add --word-diff opt to commit template","fromName":"Kraktus via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2026-04-20T20:13:58Z","receivedAt":"2026-04-20T20:14:02Z","isPatch":true,"body":"From: kraktus <rinses-riotous8n@icloud.com>\n\n`--word-diff` was available for the `diff` command, but not for\nthe `commit` one, whereas it is very useful when updating column-based\ndata-format like CSV for example.\n\nOnly support the PORCELAIN mode for now, but if deemed necessary can\nadd plain too, I don't think COLOR makes sense when outputting a file.\n\nSigned-off-by: kraktus <rinses-riotous8n@icloud.com>\n---\n    commit -v: add --word-diff opt to commit template\n\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2276%2Fkraktus%2Fgdiff_word_commit-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2276/kraktus/gdiff_word_commit-v1\nPull-Request: https://github.com/git/git/pull/2276\n\n Documentation/git-commit.adoc |  4 ++++\n builtin/commit.c              |  4 ++++\n t/t7507-commit-verbose.sh     | 45 +++++++++++++++++++++++++++++++++++\n wt-status.c                   |  2 ++\n wt-status.h                   |  1 +\n 5 files changed, 56 insertions(+)\n\ndiff --git a/Documentation/git-commit.adoc b/Documentation/git-commit.adoc\nindex 8329c1034b..6cb5359b52 100644\n--- a/Documentation/git-commit.adoc\n+++ b/Documentation/git-commit.adoc\n@@ -371,6 +371,10 @@ If specified twice, show in addition the unified diff between\n what would be committed and the worktree files, i.e. the unstaged\n changes to tracked files.\n \n+`--word-diff`::\n+\tShow a word diff instead of a line diff in the verbose commit\n+\ttemplate (requires `-v`).\n+\n `-q`::\n `--quiet`::\n \tSuppress commit summary message.\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex a3e52ac9ca..b24f086fd2 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -126,6 +126,7 @@ static int all, also, interactive, patch_interactive, only, amend, signoff;\n static struct interactive_options interactive_opts = INTERACTIVE_OPTIONS_INIT;\n static int edit_flag = -1; /* unspecified */\n static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;\n+static int commit_word_diff;\n static int config_commit_verbose = -1; /* unspecified */\n static int no_post_rewrite, allow_empty_message, pathspec_file_nul;\n static const char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;\n@@ -573,6 +574,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int\n \t\ts->reference = \"HEAD^1\";\n \t}\n \ts->verbose = verbose;\n+\ts->word_diff = commit_word_diff;\n \ts->index_file = index_file;\n \ts->fp = fp;\n \ts->nowarn = nowarn;\n@@ -1705,6 +1707,8 @@ int cmd_commit(int argc,\n \tstatic struct option builtin_commit_options[] = {\n \t\tOPT__QUIET(&quiet, N_(\"suppress summary after successful commit\")),\n \t\tOPT__VERBOSE(&verbose, N_(\"show diff in commit message template\")),\n+\t\tOPT_BOOL(0, \"word-diff\", &commit_word_diff,\n+\t\t\tN_(\"show word diff in verbose commit template\")),\n \n \t\tOPT_GROUP(N_(\"Commit message options\")),\n \t\tOPT_FILENAME('F', \"file\", &logfile, N_(\"read message from file\")),\ndiff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh\nindex b53d71c086..98693d22f2 100755\n--- a/t/t7507-commit-verbose.sh\n+++ b/t/t7507-commit-verbose.sh\n@@ -166,4 +166,49 @@ test_expect_success \"status ignores commit.verbose=true\" '\n \t! grep \"^diff --git actual\"\n '\n \n+write_script \"check-for-word-diff\" <<\\EOF\n+cp \"$1\" template_out\n+exit 0\n+EOF\n+test_set_editor \"$PWD/check-for-word-diff\"\n+\n+test_expect_success 'setup for word-diff tests' '\n+\techo \"the quick brown fox\" >wordfile &&\n+\tgit add wordfile &&\n+\tgit commit -F message &&\n+\techo \"the slow brown fox\" >wordfile &&\n+\tgit add wordfile &&\n+\tgit commit -F message\n+'\n+\n+test_expect_success '--word-diff with -v shows word diff' '\n+\tgit commit --amend -v --word-diff &&\n+\tgrep \"^-quick$\" template_out &&\n+\tgrep \"^+slow$\" template_out\n+'\n+\n+test_expect_success '--word-diff without -v is a no-op' '\n+\tgit commit --amend --word-diff &&\n+\t! grep \"^~$\" template_out\n+'\n+\n+test_expect_success '-v -v --word-diff shows word diff in both sections' '\n+\techo \"the fast brown fox\" >wordfile &&\n+\tgit commit --amend -v -v --word-diff &&\n+\tgrep \"^-quick$\" template_out &&\n+\tgrep \"^+slow$\" template_out &&\n+\tgrep \"^-slow$\" template_out &&\n+\tgrep \"^+fast$\" template_out\n+'\n+\n+test_expect_success 'word-diff markers stripped from saved commit message' '\n+\tgit commit --amend -v --word-diff &&\n+\tcheck_message message\n+'\n+\n+test_expect_success 'no --word-diff produces line diff without markers' '\n+\tgit commit --amend -v &&\n+\t! grep \"^~$\" template_out\n+'\n+\n test_done\ndiff --git a/wt-status.c b/wt-status.c\nindex 479ccc3304..086275bae3 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1177,6 +1177,8 @@ static void wt_longstatus_print_verbose(struct wt_status *s)\n \trev.diffopt.detect_rename = s->detect_rename >= 0 ? s->detect_rename : rev.diffopt.detect_rename;\n \trev.diffopt.rename_limit = s->rename_limit >= 0 ? s->rename_limit : rev.diffopt.rename_limit;\n \trev.diffopt.rename_score = s->rename_score >= 0 ? s->rename_score : rev.diffopt.rename_score;\n+\tif (s->word_diff)\n+\t\trev.diffopt.word_diff = DIFF_WORDS_PORCELAIN;\n \trev.diffopt.file = s->fp;\n \trev.diffopt.close_file = 0;\n \t/*\ndiff --git a/wt-status.h b/wt-status.h\nindex e9fe32e98c..90883d2c28 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -130,6 +130,7 @@ struct wt_status {\n \tint detect_rename;\n \tint rename_score;\n \tint rename_limit;\n+\tint word_diff;\n \tenum wt_status_format status_format;\n \tunsigned char added_cut_line; /* boolean */\n \tstruct wt_status_state state;\n\nbase-commit: e8955061076952cc5eab0300424fc48b601fe12d\n-- \ngitgitgadget\n"}]}