master 56154c939bf: Improve commit log entry creation from ChangeLog (bug#80928)
Stephen Berman via Mailing list for Emacs changes <[email protected]> Sat, 4 Jul 2026 09:57:20 -0400 (EDT)
| Newsgroups | gmane.emacs.diffs |
|---|---|
| Message-ID | <[email protected]> |
branch: master commit 56154c939bf8f3cd7dbadeb91ef0a2fe4294ec65 Author: Stephen Berman <[email protected]> Commit: Stephen Berman <[email protected]> Improve commit log entry creation from ChangeLog (bug#80928) * lisp/vc/log-edit.el (log-edit-insert-changelog-entry): New function. (log-edit-insert-changelog-entries): Use it when all log entries come from the same ChangeLog file or buffer. * test/lisp/vc/vc-tests/vc-test-misc.el (vc-test-log-message-from-changelog): New test. * doc/emacs/maintaining.texi (VC With A Merging VCS): (Log Buffer): Document improved creation of commit messages from ChangeLog. Improve documentation of *vc-log* header lines. Document 'log-edit-hook'. (VC Directory Commands): Correct documentation of 'M' and 'U'. Document determination of current VC fileset without marking. (Format of ChangeLog): Improve documentation of multi-item entries. * etc/NEWS: Announce user-facing changes. --- doc/emacs/maintaining.texi | 212 ++++++++++++++++++++++++---------- etc/NEWS | 9 ++ lisp/vc/log-edit.el | 68 ++++++++++- test/lisp/vc/vc-tests/vc-test-misc.el | 54 +++++++++ 4 files changed, 278 insertions(+), 65 deletions(-) diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index e40ff8e3f26..7e893ab4fdf 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -562,10 +562,12 @@ v}. Note that registering the files doesn't commit them; you must invoke @w{@kbd{C-x v v}} again to commit; see the next point. @item -If every file in the VC fileset has been either newly-added or -modified, commit the changed files. To do this, Emacs pops up a -@file{*vc-log*} buffer; type the desired log entry for the changes, -followed by @kbd{C-c C-c} to commit. @xref{Log Buffer}. +If every file in the VC fileset has been either newly-added or modified, +commit the changed files. To do this, Emacs pops up a @file{*vc-log*} +buffer, in which you can type the log entry for the changes (or, if the +entry has been automatically inserted from a ChangeLog file or buffer, +further edit it). When you are satisfied with the log entry, type +@kbd{C-c C-c} to commit the changes. See @ref{Log Buffer} for details. If @kbd{C-x v v} is invoked from a buffer under Diff mode, the command treats the buffer as holding a set of patches for one or more files. It @@ -715,49 +717,83 @@ out individual files. When you tell VC to commit a change, it pops up a buffer named @file{*vc-log*}. In this buffer, you should write a @dfn{log entry} describing the changes you have made (@pxref{Why Version Control?}). -After you are done, type @kbd{C-c C-c} (@code{log-edit-done}) to exit -the buffer and commit the change, together with your log entry. +Alternatively, you can have the entry automatically inserted from a +ChangeLog file or buffer (see below), which you can further edit in the +@file{*vc-log*} buffer if necessary. After you are done, type @kbd{C-c +C-c} (@code{log-edit-done}) to exit the buffer and commit the change, +together with your log entry. + + In the @file{*vc-log*} buffer, you can also write one or more +@dfn{header lines} specifying additional information to be supplied to +the version control system. For example, the following header line +states that the present change was not written by you, but by another +developer: + +@smallexample +Author: J. R. Hacker <jrh@@example.com> +@end smallexample + +@noindent +Each header line must occupy a single line at the top of the buffer; the +first line that is not a header line is treated as the start of the log +entry. In addition to the @samp{Author} header, most version control +systems also support the headers @samp{Summary} (a one-line summary of +the changeset) and @samp{Date} (a manually specified commit time). +Emacs recognizes these as well as several VCS-specific headers. If you +specify a header for a VCS that does not support it, the header is +treated as part of the log entry. @cindex Log Edit mode @cindex mode, Log Edit @vindex vc-log-mode-hook @c FIXME: Mention log-edit-mode-hook here? --xfq +@vindex log-edit-hook The major mode for the @file{*vc-log*} buffer is Log Edit mode, a variant of Text mode (@pxref{Text Mode}). On entering Log Edit mode, Emacs runs the hooks @code{text-mode-hook} and @code{vc-log-mode-hook} -(@pxref{Hooks}). - - In the @file{*vc-log*} buffer, you can write one or more @dfn{header -lines}, specifying additional information to be supplied to the -version control system. Each header line must occupy a single line at -the top of the buffer; the first line that is not a header line is -treated as the start of the log entry. For example, the following -header line states that the present change was not written by you, but -by another developer: - -@smallexample -Author: J. R. Hacker <jrh@@example.com> -@end smallexample - -@noindent -Apart from the @samp{Author} header, Emacs recognizes the headers -@samp{Summary} (a one-line summary of the changeset), @samp{Date} (a -manually-specified commit time), and @samp{Fixes} (a reference to a -bug fixed by the change). Not all version control systems recognize -all headers. If you specify a header for a system that does not -support it, the header is treated as part of the log entry. +(@pxref{Hooks}). In addition, to set up the @file{*vc-log*} buffer, +Emacs runs the hook @code{log-edit-hook}, which optionally makes several +useful features available. The following paragraphs describe several of +these features, including three that are generally useful and enabled by +default. (To see a complete list of the features and enable or disable +any of them, type @w{@kbd{M-x customize-option RET log-edit-hook RET}}; +@pxref{Specific Customization}.) + +@findex log-edit-insert-message-template + The function @code{log-edit-insert-message-template} produces the +default @file{*vc-log*} buffer setup, containing @samp{Author} and +@samp{Summary} headers, and displays a thick line separating the header +part of the buffer from the log entry part. If you remove +@code{log-edit-insert-message-template} from @code{log-edit-hook}, then +the initial @file{*vc-log*} buffer is simply empty. The two header +lines are initially empty. If you are the author of the change and you +have configured the VCS to use your name and email address in commit +messages, you can leave the @samp{Author} header empty. If you leave +the @samp{Summary} header empty, most systems will use the first line of +the log entry as the summary line (see below for a way to have the +@samp{Summary} header automatically filled). @kindex C-c C-f @r{(Log Edit mode)} @findex log-edit-show-files + When VC pops up the @file{*vc-log*} buffer, a buffer named +@file{*log-edit-files*} listing the current VC fileset, that is, the +files that will be committed if you type @w{@kbd{C-c C-c}}, also pops up +by default. If you have removed the command @code{log-edit-show-files} +from @code{log-edit-hook}, the @file{*log-edit-files*} buffer does not +automatically pop up, but you can invoke the command by typing +@w{@kbd{C-c C-f}}. Likewise, if you kill or bury the +@file{*log-edit-files*} buffer, typing @w{@kbd{C-c C-f}} will pop it up +again. + @kindex C-c C-d @r{(Log Edit mode)} @findex log-edit-show-diff - While in the @file{*vc-log*} buffer, the current VC fileset is -considered to be the fileset that will be committed if you type -@w{@kbd{C-c C-c}}. To view a list of the files in the VC fileset, -type @w{@kbd{C-c C-f}} (@code{log-edit-show-files}). To view a diff -of changes between the VC fileset and the version from which you -started editing (@pxref{Old Revisions}), type @kbd{C-c C-d} -(@code{log-edit-show-diff}). + To view a diff of changes between the VC fileset and the version from +which you started editing (@pxref{Old Revisions}), type @kbd{C-c C-d} +(@code{log-edit-show-diff}). This command also selects the window +displaying the diff. To have VC automatically display the diff when it +pops up the @file{*vc-log*} buffer, add @code{log-edit-maybe-show-diff} +to @code{log-edit-hook}; unlike @kbd{C-c C-d}, this function does not +select the window displaying the diff. @kindex C-c C-w @r{(Log Edit mode)} @findex log-edit-generate-changelog-from-diff @@ -773,15 +809,37 @@ VC root, customize @code{diff-add-log-use-relative-names}. @kindex C-c C-a @r{(Log Edit mode)} @findex log-edit-insert-changelog - If the VC fileset includes one or more @file{ChangeLog} files -(@pxref{Change Log}), type @kbd{C-c C-a} -(@code{log-edit-insert-changelog}) to pull the relevant entries into -the @file{*vc-log*} buffer. If the topmost item in each -@file{ChangeLog} was made under your user name on the current date, -this command searches that item for entries matching the file(s) to be -committed, and inserts them. + If you have added log entries for the current VC fileset to one or +more @file{ChangeLog} files or to a temporary ChangeLog buffer +(@pxref{Change Log}), by default VC automatically inserts these entries +into the @file{*vc-log*} buffer on popping it up. If you have removed +the command @code{log-edit-insert-changelog} from @code{log-edit-hook}, +VC does not automatically insert the log entries, but you can invoke the +command by typing @kbd{C-c C-a}. Likewise, if you delete or otherwise +change the content of this buffer and then decide you want to use the +ChangeLog entries after all, type @kbd{C-c C-a} to repopulate the buffer +with these entries. + + If the relevant log entries are in one or more @file{ChangeLog} files +and the topmost item in each file was made under your user name on the +current date, this command searches that item (or those items) for +entries matching the file(s) to be committed, and inserts them. If you +invoke the command with a prefix argument (@kbd{C-u C-c C-a}) or repeat +it immediately (@kbd{C-c C-a C-c C-a}), it searches the topmost item +regardless of the user name and date of the item. + + If VC detects that all log entries come from the same ChangeLog file +or buffer, then the command simply inserts the entire body of the entry +into the @file{*vc-log*} buffer. In addition, if the first line of the +entry does not begin with @samp{* } (an asterisk followed by a space), +VC considers it to be a summary line and moves it to the @samp{Summary} +header. Finally, if VC detects that the set of changed files listed in +the ChangeLog entry differs from the current VC fileset, it displays a +warning urging you to fix this discrepancy before committing the +changes. + @ifnottex -If you are using CVS or RCS, see @ref{Change Logs and VC}, for the + If you are using CVS or RCS, see @ref{Change Logs and VC}, for the opposite way of working---generating ChangeLog entries from the Log Edit buffer. @end ifnottex @@ -1641,9 +1699,10 @@ cannot be marked with this command if any file in its tree is marked. @item M If point is on a file entry, mark all files with the same status; if -point is on a directory entry, mark all files in that directory tree -(@code{vc-dir-mark-all-files}). With a prefix argument, mark all -listed files and directories. +point is on a directory entry, mark all and only the files that are +immediate descendents (i.e., children) of that directory +(@code{vc-dir-mark-all-files}). With a prefix argument, mark all listed +files. @findex vc-dir-mark-by-regexp @item % m @@ -1680,9 +1739,10 @@ active, unmark all the files in the region (@code{vc-dir-unmark}). @item U If point is on a file entry, unmark all files with the same status; if -point is on a directory entry, unmark all files in that directory tree +point is on a directory entry, unmark all and only the files that are +immediate descendents (i.e., children) of that directory (@code{vc-dir-unmark-all-files}). With a prefix argument, unmark all -files and directories. +listed files and directories. @item x Hide files with @samp{up-to-date} or @samp{ignored} status @@ -1701,13 +1761,22 @@ Quit the VC Directory buffer, and bury it (@code{quit-window}). While in the VC Directory buffer, all the files that you mark with @kbd{m} (@code{vc-dir-mark}) or @kbd{M} (@code{vc-dir-mark-all-files}) are in the current VC fileset. If you mark a directory entry with -@kbd{m}, all the listed files in that directory tree are in the -current VC fileset. The files and directories that belong to the -current VC fileset are indicated with a @samp{*} character in the VC -Directory buffer, next to their VC status. In this way, you can set -up a multi-file VC fileset to be acted on by VC commands like -@w{@kbd{C-x v v}} (@pxref{Basic VC Editing}), @w{@kbd{C-x v =}} -(@pxref{Old Revisions}), and @w{@kbd{C-x v u}} (@pxref{VC Undo}). +@kbd{m}, all the listed files in that directory tree (i.e., not only the +listed files of the directory but also the listed files of its +subdirectories) are in the current VC fileset. The files and +directories that belong to the current VC fileset are indicated with a +@samp{*} character in the VC Directory buffer, next to their VC status. +In this way, you can set up a multi-file VC fileset to be acted on by VC +commands like @w{@kbd{C-x v v}} (@pxref{Basic VC Editing}), @w{@kbd{C-x +v =}} (@pxref{Old Revisions}), and @w{@kbd{C-x v u}} (@pxref{VC Undo}). + + In a VC Directory buffer containing no marked file or directory +entries, the current VC fileset is determined as follows. If point is +on a file entry, the fileset consists of just that file. If point is on +a directory entry, the fileset consists of all files in that directory +tree. Consequently, if point in on (or above) the entry @samp{./} +(representing the working directory), the fileset consists of all listed +files. The VC Directory buffer also defines some single-key shortcuts for VC commands with the @kbd{C-x v} prefix: @kbd{=}, @kbd{+}, @kbd{l}, @@ -2526,13 +2595,36 @@ dated in May 1993, with two items and one item respectively. @end smallexample One entry can describe several changes; each change should have its -own item, or its own line in an item. Normally there should be a -blank line between items. When items are related (parts of the same -change, in different places), group them by leaving no blank line -between them. +own item, or its own line in an item. Normally there should be a blank +line between items. When items are related (parts of the same change, +in different places), group them by leaving no blank line between them. +Such a multi-item entry often begins with a single line of text that +succintly summarizes the whole changeset. The entry may also contain +additional explanatory text between the summary line and the first +change item; the explanatory text should also be bounded by blank lines. +Here is an example: + +@iftex +@medbreak +@end iftex +@smallexample +2026-02-27 Sean Whitton <spwhitton@@spwhitton.name> + + New 'log-outstanding' value for vc-log-view-type + + This fixes vc-hg-print-log's choice of -r arguments to 'hg log'. + + * lisp/vc/vc.el (vc-log-view-type): New 'log-outstanding' value. + (vc-log-outstanding): Pass it. + * lisp/vc/vc-git.el (vc-git-log-view-mode): + * lisp/vc/vc-hg.el (vc-hg-print-log, vc-hg-log-view-mode): Treat + 'log-outstanding' the same as 'log-outgoing'. +@end smallexample - You should put a copyright notice and permission notice at the -end of the change log file. Here is an example: + If you include one or more change log files in a software package that +is distributed to others, you should put a copyright notice and +permission notice at the end of each change log file. Here is an +example: @smallexample Copyright 1997--1998, 2025--2026 Free Software Foundation, Inc. diff --git a/etc/NEWS b/etc/NEWS index 8d89b65a3a4..d39ede2b346 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -119,6 +119,15 @@ are now buttonized, allowing using mouse or 'RET' to follow them. ** VC ++++ +*** Improved creation of commit log entry from ChangeLog. +When VC detects that all log entries for the current changeset come from +the same ChangeLog file or buffer, it now inserts the entire body of the +ChangeLog entry into the *vc-log* buffer. If the ChangeLog entry +contains a summary line, VC inserts it into the *vc-log* Summary header. +If VC detects that the set of changed files listed in the ChangeLog +entry differs from the current VC fileset, it displays a warning. + +++ *** VC-Dir outgoing revisions count is now asynchronous. This means it won't get in your way even if it's slow for your diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index e3c92bd4d28..b7b9c32ad99 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -1367,16 +1367,74 @@ entry." (if (setq entry (assoc key log-entries)) (setcdr entry (append (cdr entry) (list file))) (push (list key file) log-entries))))) - ;; Now map over log-entries, and extract the strings. - (dolist (log-entry (nreverse log-entries)) - (apply 'log-edit-changelog-insert-entries - (append (car log-entry) (cdr log-entry))) - (insert "\n")) + ;; Check whether all log entries come from the same ChangeLog file. + (if (length= (seq-uniq (mapcar #'caar log-entries)) 1) + ;; If so, extract the commit message in toto from that file. + (log-edit-insert-changelog-entry (caaar log-entries)) + ;; Otherwise, map over the entries constructed from each ChangeLog + ;; file used, and extract the strings. + (dolist (log-entry (nreverse log-entries)) + (apply 'log-edit-changelog-insert-entries + (append (car log-entry) (cdr log-entry))) + (insert "\n"))) ;; No newline after the last entry. (when log-entries (delete-char -1)) log-edit-author)) +(declare-function vc-deduce-fileset "vc") + +(defun log-edit-insert-changelog-entry (buffer) + "Use body of ChangeLog entry in BUFFER as commit message. +Insert the body of the latest entry in the ChangeLog file that BUFFER is +visiting into the \"*vc-log*\" buffer. If the first line of the body +does not begin with \"* \", move it to the Summary header in the +\"*vc-log*\" buffer, thus making is the summary line of the commit +message. + +If the set of files listed in the ChangeLog entry differs from the set +of files with changes to commit according to VC, display a warning +urging the user to correct this discrepancy before committing the +changes." + (let (summary beg end files-in-changelog) + (with-current-buffer buffer + (save-restriction + (log-edit-narrow-changelog) + (setq summary (let ((s (buffer-substring-no-properties + (pos-bol) (pos-eol)))) + (and (string-match "^\t\\([^*].+\\)$" s) + (match-string 1 s))) + beg (or (and summary (forward-line) + (skip-syntax-forward "\s-") + (goto-char (pos-bol))) + (point)) + end (point-max)) + ;; List of changed files according to the ChangeLog entry. + (save-excursion + (let* ((bfn (buffer-file-name buffer)) + (bn (buffer-name)) + (fnd (or (and bfn (file-name-directory bfn)) + ;; If ChangeLog buffer is not visiting a file, + ;; extract the directory from the buffer name. + (and + (string-match "\\`\\*changes to \\(.+\\)\\*\\'" bn) + (match-string 1 bn))))) + (while (re-search-forward "\t\\* \\([^ :\n]+\\)[ :\n]" nil t) + (let ((fn (concat fnd (match-string-no-properties 1)))) + (when (file-exists-p fn) + (push fn files-in-changelog)))))))) + (log-edit-changelog-insert-entries buffer beg end) + (when summary (log-edit-set-header "Summary" summary)) + (unless (seq-set-equal-p + (save-current-buffer + (nth 2 (vc-deduce-fileset nil nil 'state-model-only-files))) + files-in-changelog) + (display-warning + 'log-edit + "Files in ChangeLog entry differ from files with changes to commit! +Remove this discrepancy before committing the changes by adjusting as +appropriate either the ChangeLog entry or the selection of files to commit.")))) + (defun log-edit-toggle-header (header value) "Toggle a boolean-type header in the current buffer. See `log-edit-set-header' for details." diff --git a/test/lisp/vc/vc-tests/vc-test-misc.el b/test/lisp/vc/vc-tests/vc-test-misc.el index 4e3f883c1cd..30c5df5b63a 100644 --- a/test/lisp/vc/vc-tests/vc-test-misc.el +++ b/test/lisp/vc/vc-tests/vc-test-misc.el @@ -522,5 +522,59 @@ See bug#80803 and bug#80967." (should-not (seq-intersection directories (vc-dir-marked-files))) (kill-buffer vc-dir-buf)))))) +(ert-deftest vc-test-log-message-from-changelog () ; bug#80928 + "Test automatic insertion of log message from ChangeLog." + (skip-unless (executable-find vc-git-program)) + (vc-test--with-author-identity 'Git + (let ((vc-handled-backends '(Git)) + file-buf vc-dir-buf vc-diff-buf changelog-buf log-edit-buf + changelog-entry log-edit-entry) + (unwind-protect + (ert-with-temp-directory tempdir + (let* ((default-directory tempdir) + (file (expand-file-name "README" default-directory)) + vc-async-checkin) + (vc-test--create-repo-function 'Git) + (write-region "hello\n" nil file) + (with-current-buffer (setq file-buf (find-file-noselect file)) + (vc-register `(Git (,file))) + (vc-checkin (list file) 'Git) + (insert "Initial commit") + (let (vc-async-checkin) + (log-edit-done)) + (write-region "Hello\n" nil "README" nil t)) + (vc-dir default-directory 'Git) + (while (vc-dir-busy) (sit-for 0.05)) + (setq vc-dir-buf (current-buffer)) + (save-window-excursion + (vc-diff) + (setq vc-diff-buf (current-buffer)) + (diff-add-change-log-entries-other-window) + (with-current-buffer (window-buffer (frame-first-window)) + (setq changelog-buf (current-buffer)) + (insert "Change text.") + (forward-line -1) + (newline-and-indent) + (insert "Summary line") + (newline) + (save-restriction + (log-edit-narrow-changelog) + ;; ChangeLog entry ends with "\n\n" so omit last "\n" to + ;; ensure equivalence with to commit log entry in the test. + (let ((s (buffer-substring-no-properties + (point-min) (1- (point-max))))) + (setq changelog-entry + (mapconcat #'concat (string-split s "\t"))))))) + (vc-next-action nil) + (setq log-edit-buf (current-buffer)) + (goto-char (point-min)) + (re-search-forward "^Summary: " nil t) + (setq log-edit-entry + (buffer-substring-no-properties (point) (point-max))) + (should (equal changelog-entry log-edit-entry)))) + (dolist (buf (list file-buf vc-dir-buf vc-diff-buf changelog-buf + log-edit-buf "*log-edit-files*" "*vc*")) + (kill-buffer buf)))))) + (provide 'vc-test-misc) ;;; vc-test-misc.el ends here