{"thread":{"id":"56316","subject":"[filter-repo PATCH] filter-repo: add new --replace-message option","startedAt":"2021-08-18T04:38:57Z","lastAt":"2021-08-25T15:08:36Z","messageCount":5,"participants":["Gwyneth Morgan","Elijah Newren"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"433039","messageId":"20210818043749.85274-1-gwymor@tilde.club","threadId":"56316","inReplyTo":null,"subject":"[filter-repo PATCH] filter-repo: add new --replace-message option","fromName":"Gwyneth Morgan","fromEmail":"gwymor@tilde.club","sentAt":"2021-08-18T04:37:49Z","receivedAt":"2021-08-18T04:38:57Z","isPatch":true,"sender":{"key":"gwymor@tilde.club","avatar":"https://avatars.githubusercontent.com/u/87623694?v=4"},"body":"Like --replace-text, add an option --replace-message which replaces text\nin commit message bodies, so that users can easily replace text without\nconstructing a --message-callback.\n---\n Documentation/git-filter-repo.txt | 19 +++++++-\n git-filter-repo                   | 12 ++++-\n t/t9390-filter-repo.sh            |  1 +\n t/t9390/basic-message             | 78 +++++++++++++++++++++++++++++++\n t/t9390/sample-message            |  2 +\n 5 files changed, 110 insertions(+), 2 deletions(-)\n create mode 100644 t/t9390/basic-message\n create mode 100644 t/t9390/sample-message\n\ndiff --git a/Documentation/git-filter-repo.txt b/Documentation/git-filter-repo.txt\nindex 2798378..7a71375 100644\n--- a/Documentation/git-filter-repo.txt\n+++ b/Documentation/git-filter-repo.txt\n@@ -181,6 +181,10 @@ Renaming of refs (see also --refname-callback)\n Filtering of commit messages (see also --message-callback)\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \n+--replace-message <expressions_file>::\n+\tA file with expressions that, if found in commit messages, will\n+\tbe replaced. This file uses the same syntax as --replace-text.\n+\n --preserve-commit-hashes::\n \tBy default, since commits are rewritten and thus gain new\n \thashes, references to old commit hashes in commit messages are\n@@ -894,7 +898,20 @@ YYYY-MM-DD.  In the expressions file, there are a few things to note:\n     beginning and ends of lines rather than the beginning and end of file.\n     See https://docs.python.org/3/library/re.html for details.\n \n-See also the `--blob-callback` from <<CALLBACKS>>.\n+See also the `--blob-callback` from <<CALLBACKS>>.  Similarly, if you\n+want to modify commit messages, you can do so with the same syntax.  For\n+example, with a file named expressions.txt containing\n+\n+--------------------------------------------------\n+foo==>bar\n+--------------------------------------------------\n+\n+then running\n+--------------------------------------------------\n+git filter-repo --replace-message expressions.txt\n+--------------------------------------------------\n+\n+will replace `foo` in commit messages with `bar`.\n \n Refname based filtering\n ~~~~~~~~~~~~~~~~~~~~~~~\ndiff --git a/git-filter-repo b/git-filter-repo\nindex b91bd96..5fe0f91 100755\n--- a/git-filter-repo\n+++ b/git-filter-repo\n@@ -1843,6 +1843,10 @@ EXAMPLES\n \n     messages = parser.add_argument_group(title=_(\"Filtering of commit messages \"\n                                                \"(see also --message-callback)\"))\n+    messages.add_argument('--replace-message', metavar='EXPRESSIONS_FILE',\n+        help=_(\"A file with expressions that, if found in commit messages, \"\n+               \"will be replaced. This file uses the same syntax as \"\n+               \"--replace-text.\"))\n     messages.add_argument('--preserve-commit-hashes', action='store_true',\n         help=_(\"By default, since commits are rewritten and thus gain new \"\n                \"hashes, references to old commit hashes in commit messages \"\n@@ -2189,6 +2193,8 @@ EXAMPLES\n       args.mailmap = MailmapInfo(args.mailmap)\n     if args.replace_text:\n       args.replace_text = FilteringOptions.get_replace_text(args.replace_text)\n+    if args.replace_message:\n+      args.replace_message = FilteringOptions.get_replace_text(args.replace_message)\n     if args.strip_blobs_with_ids:\n       with open(args.strip_blobs_with_ids, 'br') as f:\n         args.strip_blobs_with_ids = set(f.read().split())\n@@ -3374,9 +3380,13 @@ class RepoFilter(object):\n     if not self._args.preserve_commit_hashes:\n       commit.message = self._hash_re.sub(self._translate_commit_hash,\n                                          commit.message)\n+    if self._args.replace_message:\n+      for literal, replacement in self._args.replace_message['literals']:\n+        commit.message = commit.message.replace(literal, replacement)\n+      for regex,   replacement in self._args.replace_message['regexes']:\n+        commit.message = regex.sub(replacement, commit.message)\n     if self._message_callback:\n       commit.message = self._message_callback(commit.message)\n-\n     # Change the author & committer according to mailmap rules\n     args = self._args\n     if args.mailmap:\ndiff --git a/t/t9390-filter-repo.sh b/t/t9390-filter-repo.sh\nindex 3f567e7..6d2d985 100755\n--- a/t/t9390-filter-repo.sh\n+++ b/t/t9390-filter-repo.sh\n@@ -39,6 +39,7 @@ filter_testcase basic basic-filename --invert-paths --path-glob 't*en*'\n filter_testcase basic basic-numbers  --invert-paths --path-regex 'f.*e.*e'\n filter_testcase basic basic-mailmap  --mailmap ../t9390/sample-mailmap\n filter_testcase basic basic-replace  --replace-text ../t9390/sample-replace\n+filter_testcase basic basic-message  --replace-message ../t9390/sample-message\n filter_testcase empty empty-keepme   --path keepme\n filter_testcase empty more-empty-keepme --path keepme --prune-empty=always \\\n \t\t                                   --prune-degenerate=always\ndiff --git a/t/t9390/basic-message b/t/t9390/basic-message\nnew file mode 100644\nindex 0000000..4ac1968\n--- /dev/null\n+++ b/t/t9390/basic-message\n@@ -0,0 +1,78 @@\n+feature done\n+blob\n+mark :1\n+data 8\n+initial\n+\n+reset refs/heads/B\n+commit refs/heads/B\n+mark :2\n+author Little O. Me <me@little.net> 1535228562 -0700\n+committer Little O. Me <me@little.net> 1535228562 -0700\n+data 9\n+Modified\n+M 100644 :1 filename\n+M 100644 :1 ten\n+M 100644 :1 twenty\n+\n+blob\n+mark :3\n+data 11\n+twenty-mod\n+\n+commit refs/heads/B\n+mark :4\n+author Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n+committer Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n+data 18\n+add the number 20\n+from :2\n+M 100644 :3 twenty\n+\n+blob\n+mark :5\n+data 8\n+ten-mod\n+\n+commit refs/heads/A\n+mark :6\n+author Little O. Me <me@machine52.little.net> 1535229523 -0700\n+committer Little O. Me <me@machine52.little.net> 1535229523 -0700\n+data 8\n+add ten\n+from :2\n+M 100644 :5 ten\n+\n+commit refs/heads/master\n+mark :7\n+author Lit.e Me <me@fire.com> 1535229559 -0700\n+committer Lit.e Me <me@fire.com> 1535229580 -0700\n+data 24\n+Merge branch 'A' into B\n+from :4\n+merge :6\n+M 100644 :5 ten\n+\n+blob\n+mark :8\n+data 6\n+final\n+\n+commit refs/heads/master\n+mark :9\n+author Little Me <me@bigcompany.com> 1535229601 -0700\n+committer Little Me <me@bigcompany.com> 1535229601 -0700\n+data 9\n+whatever\n+from :7\n+M 100644 :8 filename\n+M 100644 :8 ten\n+M 100644 :8 twenty\n+\n+tag v1.0\n+from :9\n+tagger Little John <second@merry.men> 1535229618 -0700\n+data 5\n+v1.0\n+\n+done\ndiff --git a/t/t9390/sample-message b/t/t9390/sample-message\nnew file mode 100644\nindex 0000000..a374d61\n--- /dev/null\n+++ b/t/t9390/sample-message\n@@ -0,0 +1,2 @@\n+Initial==>Modified\n+regex:tw.nty==>the number 20\n-- \n2.32.0\n\n"},{"id":"433467","messageId":"CABPp-BF3EopyXGtKomnVjuavg2dX+79qLwkPjjyX+PO5JBSXtg@mail.gmail.com","threadId":"56316","inReplyTo":"20210818043749.85274-1-gwymor@tilde.club","subject":"Re: [filter-repo PATCH] filter-repo: add new --replace-message option","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-08-23T17:34:07Z","receivedAt":"2021-08-23T17:34:22Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"Hi,\n\nOn Tue, Aug 17, 2021 at 9:38 PM Gwyneth Morgan <gwymor@tilde.club> wrote:\n>\n> Like --replace-text, add an option --replace-message which replaces text\n> in commit message bodies, so that users can easily replace text without\n> constructing a --message-callback.\n\nInteresting idea.\n\nMissing a Signed-off-by trailer.\n\n> ---\n>  Documentation/git-filter-repo.txt | 19 +++++++-\n>  git-filter-repo                   | 12 ++++-\n>  t/t9390-filter-repo.sh            |  1 +\n>  t/t9390/basic-message             | 78 +++++++++++++++++++++++++++++++\n>  t/t9390/sample-message            |  2 +\n>  5 files changed, 110 insertions(+), 2 deletions(-)\n>  create mode 100644 t/t9390/basic-message\n>  create mode 100644 t/t9390/sample-message\n>\n> diff --git a/Documentation/git-filter-repo.txt b/Documentation/git-filter-repo.txt\n> index 2798378..7a71375 100644\n> --- a/Documentation/git-filter-repo.txt\n> +++ b/Documentation/git-filter-repo.txt\n> @@ -181,6 +181,10 @@ Renaming of refs (see also --refname-callback)\n>  Filtering of commit messages (see also --message-callback)\n>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n>\n> +--replace-message <expressions_file>::\n> +       A file with expressions that, if found in commit messages, will\n> +       be replaced. This file uses the same syntax as --replace-text.\n> +\n\nJust commit messages?  What about tag messages?\n\n>  --preserve-commit-hashes::\n>         By default, since commits are rewritten and thus gain new\n>         hashes, references to old commit hashes in commit messages are\n> @@ -894,7 +898,20 @@ YYYY-MM-DD.  In the expressions file, there are a few things to note:\n>      beginning and ends of lines rather than the beginning and end of file.\n>      See https://docs.python.org/3/library/re.html for details.\n>\n> -See also the `--blob-callback` from <<CALLBACKS>>.\n> +See also the `--blob-callback` from <<CALLBACKS>>.  Similarly, if you\n> +want to modify commit messages, you can do so with the same syntax.  For\n> +example, with a file named expressions.txt containing\n> +\n> +--------------------------------------------------\n> +foo==>bar\n> +--------------------------------------------------\n> +\n> +then running\n> +--------------------------------------------------\n> +git filter-repo --replace-message expressions.txt\n> +--------------------------------------------------\n> +\n> +will replace `foo` in commit messages with `bar`.\n\nYou've added this text to the \"Content based filtering\" section of the\nmanual, which doesn't make sense.  It should go in a section about\nupdating commit/tag messages.\n\n>  Refname based filtering\n>  ~~~~~~~~~~~~~~~~~~~~~~~\n> diff --git a/git-filter-repo b/git-filter-repo\n> index b91bd96..5fe0f91 100755\n> --- a/git-filter-repo\n> +++ b/git-filter-repo\n> @@ -1843,6 +1843,10 @@ EXAMPLES\n>\n>      messages = parser.add_argument_group(title=_(\"Filtering of commit messages \"\n>                                                 \"(see also --message-callback)\"))\n> +    messages.add_argument('--replace-message', metavar='EXPRESSIONS_FILE',\n> +        help=_(\"A file with expressions that, if found in commit messages, \"\n> +               \"will be replaced. This file uses the same syntax as \"\n> +               \"--replace-text.\"))\n>      messages.add_argument('--preserve-commit-hashes', action='store_true',\n>          help=_(\"By default, since commits are rewritten and thus gain new \"\n>                 \"hashes, references to old commit hashes in commit messages \"\n> @@ -2189,6 +2193,8 @@ EXAMPLES\n>        args.mailmap = MailmapInfo(args.mailmap)\n>      if args.replace_text:\n>        args.replace_text = FilteringOptions.get_replace_text(args.replace_text)\n> +    if args.replace_message:\n> +      args.replace_message = FilteringOptions.get_replace_text(args.replace_message)\n>      if args.strip_blobs_with_ids:\n>        with open(args.strip_blobs_with_ids, 'br') as f:\n>          args.strip_blobs_with_ids = set(f.read().split())\n> @@ -3374,9 +3380,13 @@ class RepoFilter(object):\n>      if not self._args.preserve_commit_hashes:\n>        commit.message = self._hash_re.sub(self._translate_commit_hash,\n>                                           commit.message)\n> +    if self._args.replace_message:\n> +      for literal, replacement in self._args.replace_message['literals']:\n> +        commit.message = commit.message.replace(literal, replacement)\n> +      for regex,   replacement in self._args.replace_message['regexes']:\n> +        commit.message = regex.sub(replacement, commit.message)\n\nMakes sense.\n\n>      if self._message_callback:\n>        commit.message = self._message_callback(commit.message)\n> -\n\nWhy this stray line removal?\n\n>      # Change the author & committer according to mailmap rules\n>      args = self._args\n>      if args.mailmap:\n\nAs noted above, just as --message-callback affects both commit and tag\nmessages, shouldn't this option affect both (i.e. should there also be\na section in tweak_tag() similar to the one you added to\ntweak_commit())?\n\n> diff --git a/t/t9390-filter-repo.sh b/t/t9390-filter-repo.sh\n> index 3f567e7..6d2d985 100755\n> --- a/t/t9390-filter-repo.sh\n> +++ b/t/t9390-filter-repo.sh\n> @@ -39,6 +39,7 @@ filter_testcase basic basic-filename --invert-paths --path-glob 't*en*'\n>  filter_testcase basic basic-numbers  --invert-paths --path-regex 'f.*e.*e'\n>  filter_testcase basic basic-mailmap  --mailmap ../t9390/sample-mailmap\n>  filter_testcase basic basic-replace  --replace-text ../t9390/sample-replace\n> +filter_testcase basic basic-message  --replace-message ../t9390/sample-message\n>  filter_testcase empty empty-keepme   --path keepme\n>  filter_testcase empty more-empty-keepme --path keepme --prune-empty=always \\\n>                                                    --prune-degenerate=always\n> diff --git a/t/t9390/basic-message b/t/t9390/basic-message\n> new file mode 100644\n> index 0000000..4ac1968\n> --- /dev/null\n> +++ b/t/t9390/basic-message\n> @@ -0,0 +1,78 @@\n> +feature done\n> +blob\n> +mark :1\n> +data 8\n> +initial\n> +\n> +reset refs/heads/B\n> +commit refs/heads/B\n> +mark :2\n> +author Little O. Me <me@little.net> 1535228562 -0700\n> +committer Little O. Me <me@little.net> 1535228562 -0700\n> +data 9\n> +Modified\n> +M 100644 :1 filename\n> +M 100644 :1 ten\n> +M 100644 :1 twenty\n> +\n> +blob\n> +mark :3\n> +data 11\n> +twenty-mod\n> +\n> +commit refs/heads/B\n> +mark :4\n> +author Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n> +committer Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n> +data 18\n> +add the number 20\n> +from :2\n> +M 100644 :3 twenty\n> +\n> +blob\n> +mark :5\n> +data 8\n> +ten-mod\n> +\n> +commit refs/heads/A\n> +mark :6\n> +author Little O. Me <me@machine52.little.net> 1535229523 -0700\n> +committer Little O. Me <me@machine52.little.net> 1535229523 -0700\n> +data 8\n> +add ten\n> +from :2\n> +M 100644 :5 ten\n> +\n> +commit refs/heads/master\n> +mark :7\n> +author Lit.e Me <me@fire.com> 1535229559 -0700\n> +committer Lit.e Me <me@fire.com> 1535229580 -0700\n> +data 24\n> +Merge branch 'A' into B\n> +from :4\n> +merge :6\n> +M 100644 :5 ten\n> +\n> +blob\n> +mark :8\n> +data 6\n> +final\n> +\n> +commit refs/heads/master\n> +mark :9\n> +author Little Me <me@bigcompany.com> 1535229601 -0700\n> +committer Little Me <me@bigcompany.com> 1535229601 -0700\n> +data 9\n> +whatever\n> +from :7\n> +M 100644 :8 filename\n> +M 100644 :8 ten\n> +M 100644 :8 twenty\n> +\n> +tag v1.0\n> +from :9\n> +tagger Little John <second@merry.men> 1535229618 -0700\n> +data 5\n> +v1.0\n> +\n> +done\n> diff --git a/t/t9390/sample-message b/t/t9390/sample-message\n> new file mode 100644\n> index 0000000..a374d61\n> --- /dev/null\n> +++ b/t/t9390/sample-message\n> @@ -0,0 +1,2 @@\n> +Initial==>Modified\n> +regex:tw.nty==>the number 20\n> --\n> 2.32.0\n\nTestcase looks good.\n\nThanks for sending this along; if you fix up the issues I pointed out,\nI'd be happy to apply this to git-filter-repo.\n"},{"id":"433495","messageId":"YSQK0JeaXtKWPgU2@tilde.club","threadId":"56316","inReplyTo":"CABPp-BF3EopyXGtKomnVjuavg2dX+79qLwkPjjyX+PO5JBSXtg@mail.gmail.com","subject":"Re: [filter-repo PATCH] filter-repo: add new --replace-message option","fromName":"Gwyneth Morgan","fromEmail":"gwymor@tilde.club","sentAt":"2021-08-23T20:53:36Z","receivedAt":"2021-08-23T20:54:12Z","isPatch":true,"sender":{"key":"gwymor@tilde.club","avatar":"https://avatars.githubusercontent.com/u/87623694?v=4"},"body":"On 2021-08-23 10:34:07-0700, Elijah Newren wrote:\n> Hi,\n> \n> On Tue, Aug 17, 2021 at 9:38 PM Gwyneth Morgan <gwymor@tilde.club> wrote:\n> >\n> > Like --replace-text, add an option --replace-message which replaces text\n> > in commit message bodies, so that users can easily replace text without\n> > constructing a --message-callback.\n> \n> Interesting idea.\n> \n> Missing a Signed-off-by trailer.\n\nWill fix.\n\n> > @@ -894,7 +898,20 @@ YYYY-MM-DD.  In the expressions file, there are a few things to note:\n> >      beginning and ends of lines rather than the beginning and end of file.\n> >      See https://docs.python.org/3/library/re.html for details.\n> >\n> > -See also the `--blob-callback` from <<CALLBACKS>>.\n> > +See also the `--blob-callback` from <<CALLBACKS>>.  Similarly, if you\n> > +want to modify commit messages, you can do so with the same syntax.  For\n> > +example, with a file named expressions.txt containing\n> > +\n> > +--------------------------------------------------\n> > +foo==>bar\n> > +--------------------------------------------------\n> > +\n> > +then running\n> > +--------------------------------------------------\n> > +git filter-repo --replace-message expressions.txt\n> > +--------------------------------------------------\n> > +\n> > +will replace `foo` in commit messages with `bar`.\n> \n> You've added this text to the \"Content based filtering\" section of the\n> manual, which doesn't make sense.  It should go in a section about\n> updating commit/tag messages.\n\nAh, got it. I'll move that into a new section.\n\n> >      if self._message_callback:\n> >        commit.message = self._message_callback(commit.message)\n> > -\n> \n> Why this stray line removal?\n\nThat was accidental. Will fix.\n\n> >      # Change the author & committer according to mailmap rules\n> >      args = self._args\n> >      if args.mailmap:\n> \n> As noted above, just as --message-callback affects both commit and tag\n> messages, shouldn't this option affect both (i.e. should there also be\n> a section in tweak_tag() similar to the one you added to\n> tweak_commit())?\n\nYes, it should. I'll change that.\n"},{"id":"433496","messageId":"20210823205549.18566-1-gwymor@tilde.club","threadId":"56316","inReplyTo":"20210818043749.85274-1-gwymor@tilde.club","subject":"[filter-repo PATCH v2] filter-repo: add new --replace-message option","fromName":"Gwyneth Morgan","fromEmail":"gwymor@tilde.club","sentAt":"2021-08-23T20:55:51Z","receivedAt":"2021-08-23T20:58:04Z","isPatch":true,"sender":{"key":"gwymor@tilde.club","avatar":"https://avatars.githubusercontent.com/u/87623694?v=4"},"body":"Like --replace-text, add an option --replace-message which replaces text\nin commit/tag message bodies, so that users can easily replace text\nwithout constructing a --message-callback.\n\nSigned-off-by: Gwyneth Morgan <gwymor@tilde.club>\n---\n Documentation/git-filter-repo.txt | 25 ++++++++++\n git-filter-repo                   | 16 +++++++\n t/t9390-filter-repo.sh            |  1 +\n t/t9390/basic-message             | 78 +++++++++++++++++++++++++++++++\n t/t9390/sample-message            |  4 ++\n 5 files changed, 124 insertions(+)\n create mode 100644 t/t9390/basic-message\n create mode 100644 t/t9390/sample-message\n\ndiff --git a/Documentation/git-filter-repo.txt b/Documentation/git-filter-repo.txt\nindex 2798378..1e590c7 100644\n--- a/Documentation/git-filter-repo.txt\n+++ b/Documentation/git-filter-repo.txt\n@@ -181,6 +181,11 @@ Renaming of refs (see also --refname-callback)\n Filtering of commit messages (see also --message-callback)\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n \n+--replace-message <expressions_file>::\n+\tA file with expressions that, if found in commit or tag\n+\tmessages, will be replaced. This file uses the same syntax as\n+\t--replace-text.\n+\n --preserve-commit-hashes::\n \tBy default, since commits are rewritten and thus gain new\n \thashes, references to old commit hashes in commit messages are\n@@ -896,6 +901,26 @@ YYYY-MM-DD.  In the expressions file, there are a few things to note:\n \n See also the `--blob-callback` from <<CALLBACKS>>.\n \n+Updating commit/tag messages\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+If you want to modify commit or tag messages, you can do so with the\n+same syntax as `--replace-text`, explained above.  For example, with a\n+file named expressions.txt containing\n+\n+--------------------------------------------------\n+foo==>bar\n+--------------------------------------------------\n+\n+then running\n+--------------------------------------------------\n+git filter-repo --replace-message expressions.txt\n+--------------------------------------------------\n+\n+will replace `foo` in commit or tag messages with `bar`.\n+\n+See also the `--message-callback` from <<CALLBACKS>>.\n+\n Refname based filtering\n ~~~~~~~~~~~~~~~~~~~~~~~\n \ndiff --git a/git-filter-repo b/git-filter-repo\nindex b91bd96..5e726c9 100755\n--- a/git-filter-repo\n+++ b/git-filter-repo\n@@ -1843,6 +1843,10 @@ EXAMPLES\n \n     messages = parser.add_argument_group(title=_(\"Filtering of commit messages \"\n                                                \"(see also --message-callback)\"))\n+    messages.add_argument('--replace-message', metavar='EXPRESSIONS_FILE',\n+        help=_(\"A file with expressions that, if found in commit messages, \"\n+               \"will be replaced. This file uses the same syntax as \"\n+               \"--replace-text.\"))\n     messages.add_argument('--preserve-commit-hashes', action='store_true',\n         help=_(\"By default, since commits are rewritten and thus gain new \"\n                \"hashes, references to old commit hashes in commit messages \"\n@@ -2189,6 +2193,8 @@ EXAMPLES\n       args.mailmap = MailmapInfo(args.mailmap)\n     if args.replace_text:\n       args.replace_text = FilteringOptions.get_replace_text(args.replace_text)\n+    if args.replace_message:\n+      args.replace_message = FilteringOptions.get_replace_text(args.replace_message)\n     if args.strip_blobs_with_ids:\n       with open(args.strip_blobs_with_ids, 'br') as f:\n         args.strip_blobs_with_ids = set(f.read().split())\n@@ -3374,6 +3380,11 @@ class RepoFilter(object):\n     if not self._args.preserve_commit_hashes:\n       commit.message = self._hash_re.sub(self._translate_commit_hash,\n                                          commit.message)\n+    if self._args.replace_message:\n+      for literal, replacement in self._args.replace_message['literals']:\n+        commit.message = commit.message.replace(literal, replacement)\n+      for regex,   replacement in self._args.replace_message['regexes']:\n+        commit.message = regex.sub(replacement, commit.message)\n     if self._message_callback:\n       commit.message = self._message_callback(commit.message)\n \n@@ -3474,6 +3485,11 @@ class RepoFilter(object):\n \n   def _tweak_tag(self, tag):\n     # Tweak the tag message according to callbacks\n+    if self._args.replace_message:\n+      for literal, replacement in self._args.replace_message['literals']:\n+        tag.message = tag.message.replace(literal, replacement)\n+      for regex,   replacement in self._args.replace_message['regexes']:\n+        tag.message = regex.sub(replacement, tag.message)\n     if self._message_callback:\n       tag.message = self._message_callback(tag.message)\n \ndiff --git a/t/t9390-filter-repo.sh b/t/t9390-filter-repo.sh\nindex 3f567e7..6d2d985 100755\n--- a/t/t9390-filter-repo.sh\n+++ b/t/t9390-filter-repo.sh\n@@ -39,6 +39,7 @@ filter_testcase basic basic-filename --invert-paths --path-glob 't*en*'\n filter_testcase basic basic-numbers  --invert-paths --path-regex 'f.*e.*e'\n filter_testcase basic basic-mailmap  --mailmap ../t9390/sample-mailmap\n filter_testcase basic basic-replace  --replace-text ../t9390/sample-replace\n+filter_testcase basic basic-message  --replace-message ../t9390/sample-message\n filter_testcase empty empty-keepme   --path keepme\n filter_testcase empty more-empty-keepme --path keepme --prune-empty=always \\\n \t\t                                   --prune-degenerate=always\ndiff --git a/t/t9390/basic-message b/t/t9390/basic-message\nnew file mode 100644\nindex 0000000..5b6b41b\n--- /dev/null\n+++ b/t/t9390/basic-message\n@@ -0,0 +1,78 @@\n+feature done\n+blob\n+mark :1\n+data 8\n+initial\n+\n+reset refs/heads/B\n+commit refs/heads/B\n+mark :2\n+author Little O. Me <me@little.net> 1535228562 -0700\n+committer Little O. Me <me@little.net> 1535228562 -0700\n+data 9\n+Modified\n+M 100644 :1 filename\n+M 100644 :1 ten\n+M 100644 :1 twenty\n+\n+blob\n+mark :3\n+data 11\n+twenty-mod\n+\n+commit refs/heads/B\n+mark :4\n+author Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n+committer Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n+data 18\n+add the number 20\n+from :2\n+M 100644 :3 twenty\n+\n+blob\n+mark :5\n+data 8\n+ten-mod\n+\n+commit refs/heads/A\n+mark :6\n+author Little O. Me <me@machine52.little.net> 1535229523 -0700\n+committer Little O. Me <me@machine52.little.net> 1535229523 -0700\n+data 8\n+add ten\n+from :2\n+M 100644 :5 ten\n+\n+commit refs/heads/master\n+mark :7\n+author Lit.e Me <me@fire.com> 1535229559 -0700\n+committer Lit.e Me <me@fire.com> 1535229580 -0700\n+data 24\n+Merge branch 'A' into B\n+from :4\n+merge :6\n+M 100644 :5 ten\n+\n+blob\n+mark :8\n+data 6\n+final\n+\n+commit refs/heads/master\n+mark :9\n+author Little Me <me@bigcompany.com> 1535229601 -0700\n+committer Little Me <me@bigcompany.com> 1535229601 -0700\n+data 9\n+whatever\n+from :7\n+M 100644 :8 filename\n+M 100644 :8 ten\n+M 100644 :8 twenty\n+\n+tag v1.0\n+from :9\n+tagger Little John <second@merry.men> 1535229618 -0700\n+data 15\n+version one :)\n+\n+done\ndiff --git a/t/t9390/sample-message b/t/t9390/sample-message\nnew file mode 100644\nindex 0000000..0412c3c\n--- /dev/null\n+++ b/t/t9390/sample-message\n@@ -0,0 +1,4 @@\n+Initial==>Modified\n+regex:tw.nty==>the number 20\n+v1.0==>version one!\n+regex:!$==> :)\n-- \n2.33.0\n\n"},{"id":"433743","messageId":"CABPp-BFrYzCeuq18nTgq_+Znb313_77bED+zyapadyOrKHGBSw@mail.gmail.com","threadId":"56316","inReplyTo":"20210823205549.18566-1-gwymor@tilde.club","subject":"Re: [filter-repo PATCH v2] filter-repo: add new --replace-message option","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2021-08-25T15:08:19Z","receivedAt":"2021-08-25T15:08:36Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Mon, Aug 23, 2021 at 1:58 PM Gwyneth Morgan <gwymor@tilde.club> wrote:\n>\n> Like --replace-text, add an option --replace-message which replaces text\n> in commit/tag message bodies, so that users can easily replace text\n> without constructing a --message-callback.\n>\n> Signed-off-by: Gwyneth Morgan <gwymor@tilde.club>\n> ---\n>  Documentation/git-filter-repo.txt | 25 ++++++++++\n>  git-filter-repo                   | 16 +++++++\n>  t/t9390-filter-repo.sh            |  1 +\n>  t/t9390/basic-message             | 78 +++++++++++++++++++++++++++++++\n>  t/t9390/sample-message            |  4 ++\n>  5 files changed, 124 insertions(+)\n>  create mode 100644 t/t9390/basic-message\n>  create mode 100644 t/t9390/sample-message\n>\n> diff --git a/Documentation/git-filter-repo.txt b/Documentation/git-filter-repo.txt\n> index 2798378..1e590c7 100644\n> --- a/Documentation/git-filter-repo.txt\n> +++ b/Documentation/git-filter-repo.txt\n> @@ -181,6 +181,11 @@ Renaming of refs (see also --refname-callback)\n>  Filtering of commit messages (see also --message-callback)\n>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n>\n> +--replace-message <expressions_file>::\n> +       A file with expressions that, if found in commit or tag\n> +       messages, will be replaced. This file uses the same syntax as\n> +       --replace-text.\n> +\n>  --preserve-commit-hashes::\n>         By default, since commits are rewritten and thus gain new\n>         hashes, references to old commit hashes in commit messages are\n> @@ -896,6 +901,26 @@ YYYY-MM-DD.  In the expressions file, there are a few things to note:\n>\n>  See also the `--blob-callback` from <<CALLBACKS>>.\n>\n> +Updating commit/tag messages\n> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n> +\n> +If you want to modify commit or tag messages, you can do so with the\n> +same syntax as `--replace-text`, explained above.  For example, with a\n> +file named expressions.txt containing\n> +\n> +--------------------------------------------------\n> +foo==>bar\n> +--------------------------------------------------\n> +\n> +then running\n> +--------------------------------------------------\n> +git filter-repo --replace-message expressions.txt\n> +--------------------------------------------------\n> +\n> +will replace `foo` in commit or tag messages with `bar`.\n> +\n> +See also the `--message-callback` from <<CALLBACKS>>.\n> +\n>  Refname based filtering\n>  ~~~~~~~~~~~~~~~~~~~~~~~\n>\n> diff --git a/git-filter-repo b/git-filter-repo\n> index b91bd96..5e726c9 100755\n> --- a/git-filter-repo\n> +++ b/git-filter-repo\n> @@ -1843,6 +1843,10 @@ EXAMPLES\n>\n>      messages = parser.add_argument_group(title=_(\"Filtering of commit messages \"\n>                                                 \"(see also --message-callback)\"))\n> +    messages.add_argument('--replace-message', metavar='EXPRESSIONS_FILE',\n> +        help=_(\"A file with expressions that, if found in commit messages, \"\n> +               \"will be replaced. This file uses the same syntax as \"\n> +               \"--replace-text.\"))\n>      messages.add_argument('--preserve-commit-hashes', action='store_true',\n>          help=_(\"By default, since commits are rewritten and thus gain new \"\n>                 \"hashes, references to old commit hashes in commit messages \"\n> @@ -2189,6 +2193,8 @@ EXAMPLES\n>        args.mailmap = MailmapInfo(args.mailmap)\n>      if args.replace_text:\n>        args.replace_text = FilteringOptions.get_replace_text(args.replace_text)\n> +    if args.replace_message:\n> +      args.replace_message = FilteringOptions.get_replace_text(args.replace_message)\n>      if args.strip_blobs_with_ids:\n>        with open(args.strip_blobs_with_ids, 'br') as f:\n>          args.strip_blobs_with_ids = set(f.read().split())\n> @@ -3374,6 +3380,11 @@ class RepoFilter(object):\n>      if not self._args.preserve_commit_hashes:\n>        commit.message = self._hash_re.sub(self._translate_commit_hash,\n>                                           commit.message)\n> +    if self._args.replace_message:\n> +      for literal, replacement in self._args.replace_message['literals']:\n> +        commit.message = commit.message.replace(literal, replacement)\n> +      for regex,   replacement in self._args.replace_message['regexes']:\n> +        commit.message = regex.sub(replacement, commit.message)\n>      if self._message_callback:\n>        commit.message = self._message_callback(commit.message)\n>\n> @@ -3474,6 +3485,11 @@ class RepoFilter(object):\n>\n>    def _tweak_tag(self, tag):\n>      # Tweak the tag message according to callbacks\n> +    if self._args.replace_message:\n> +      for literal, replacement in self._args.replace_message['literals']:\n> +        tag.message = tag.message.replace(literal, replacement)\n> +      for regex,   replacement in self._args.replace_message['regexes']:\n> +        tag.message = regex.sub(replacement, tag.message)\n>      if self._message_callback:\n>        tag.message = self._message_callback(tag.message)\n>\n> diff --git a/t/t9390-filter-repo.sh b/t/t9390-filter-repo.sh\n> index 3f567e7..6d2d985 100755\n> --- a/t/t9390-filter-repo.sh\n> +++ b/t/t9390-filter-repo.sh\n> @@ -39,6 +39,7 @@ filter_testcase basic basic-filename --invert-paths --path-glob 't*en*'\n>  filter_testcase basic basic-numbers  --invert-paths --path-regex 'f.*e.*e'\n>  filter_testcase basic basic-mailmap  --mailmap ../t9390/sample-mailmap\n>  filter_testcase basic basic-replace  --replace-text ../t9390/sample-replace\n> +filter_testcase basic basic-message  --replace-message ../t9390/sample-message\n>  filter_testcase empty empty-keepme   --path keepme\n>  filter_testcase empty more-empty-keepme --path keepme --prune-empty=always \\\n>                                                    --prune-degenerate=always\n> diff --git a/t/t9390/basic-message b/t/t9390/basic-message\n> new file mode 100644\n> index 0000000..5b6b41b\n> --- /dev/null\n> +++ b/t/t9390/basic-message\n> @@ -0,0 +1,78 @@\n> +feature done\n> +blob\n> +mark :1\n> +data 8\n> +initial\n> +\n> +reset refs/heads/B\n> +commit refs/heads/B\n> +mark :2\n> +author Little O. Me <me@little.net> 1535228562 -0700\n> +committer Little O. Me <me@little.net> 1535228562 -0700\n> +data 9\n> +Modified\n> +M 100644 :1 filename\n> +M 100644 :1 ten\n> +M 100644 :1 twenty\n> +\n> +blob\n> +mark :3\n> +data 11\n> +twenty-mod\n> +\n> +commit refs/heads/B\n> +mark :4\n> +author Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n> +committer Little 'ol Me <me@laptop.(none)> 1535229544 -0700\n> +data 18\n> +add the number 20\n> +from :2\n> +M 100644 :3 twenty\n> +\n> +blob\n> +mark :5\n> +data 8\n> +ten-mod\n> +\n> +commit refs/heads/A\n> +mark :6\n> +author Little O. Me <me@machine52.little.net> 1535229523 -0700\n> +committer Little O. Me <me@machine52.little.net> 1535229523 -0700\n> +data 8\n> +add ten\n> +from :2\n> +M 100644 :5 ten\n> +\n> +commit refs/heads/master\n> +mark :7\n> +author Lit.e Me <me@fire.com> 1535229559 -0700\n> +committer Lit.e Me <me@fire.com> 1535229580 -0700\n> +data 24\n> +Merge branch 'A' into B\n> +from :4\n> +merge :6\n> +M 100644 :5 ten\n> +\n> +blob\n> +mark :8\n> +data 6\n> +final\n> +\n> +commit refs/heads/master\n> +mark :9\n> +author Little Me <me@bigcompany.com> 1535229601 -0700\n> +committer Little Me <me@bigcompany.com> 1535229601 -0700\n> +data 9\n> +whatever\n> +from :7\n> +M 100644 :8 filename\n> +M 100644 :8 ten\n> +M 100644 :8 twenty\n> +\n> +tag v1.0\n> +from :9\n> +tagger Little John <second@merry.men> 1535229618 -0700\n> +data 15\n> +version one :)\n> +\n> +done\n> diff --git a/t/t9390/sample-message b/t/t9390/sample-message\n> new file mode 100644\n> index 0000000..0412c3c\n> --- /dev/null\n> +++ b/t/t9390/sample-message\n> @@ -0,0 +1,4 @@\n> +Initial==>Modified\n> +regex:tw.nty==>the number 20\n> +v1.0==>version one!\n> +regex:!$==> :)\n> --\n> 2.33.0\n\nApplied; thanks!\n"}]}