Home > Net >  Building a commit message out of partial commit messages
Building a commit message out of partial commit messages

Time:10-19

Is there any way to automatically compose a commit message from "partial" commit messages instead of writing it as a whole when you actually do the commit?

Say we have 3 files with changes to be committed: file1, file2, file3. We want the commit message to have a comment describing why we did each change in a file. Is there a way to do something like this?:

git add file1 Message: "Changed file1..."

git add file2 Message: "Changed file2..."

git add file3 Message: "Changed file3..."

Edit: As pointed out in the comments, we do not write commit messages when using git add , this is just an example to help clarify the question.

When commiting, the commit message will be a concatenation of previous messages. The whole commit message will be:

  • Changed file1...
  • Changed file2...
  • Changed file3...

Is this even possible? Thanks in advance

CodePudding user response:

You can create three commits

git add file1 && git commit -m "Changes to file1..."
git add file2 && git commit -m "Changes to file2..."
git add file3 && git commit -m "Changes to file3..."

Then do an interactive rebase

git rebase -i HEAD~3

You will be presented with an editor containing

pick 9c67656 Changes to file1...
pick b54fa87 Changes to file2...
pick e5cf43d Changes to file3...

Change the second and third pick to squash

pick 9c67656 Changes to file1...
squash b54fa87 Changes to file2...
squash e5cf43d Changes to file3...

and exit. You will be presented with

# This is a combination of 3 commits.
# This is the 1st commit message:

Changes to file1...

# This is the commit message #2:

Changes to file2...

# This is the commit message #3:

Changes to file3...

Which you can change to anything you like, e.g.

Changes to file1...
Changes to file2...
Changes to file3...

CodePudding user response:

I would use Nils Werner's method, or more precisely my own variant on this (make three commits with at-least-halfway-OK commit messages: "modify file 1" is not a useful commit message1), to do this, but there is another method. The git commit command has numerous options for messages:

  • -c or -C, both of which take anything that resolves (via git rev-parse) to a commit hash ID: that commit supplies the message;
  • -m, which takes an argument: this makes up part of the message; multiple -m options can be concatenated to provide the complete message;
  • -F, which takes a file (path) name or - as an argument: the commit message is read from the given file, or from standard input if the file name is -.

In all cases the message can be edited further: -C means --edit -c and you can use an explicit --edit. These all work by creating a file (.git/COMMIT_EDITMSG or similar, depending on added worktree state) and then running your chosen editor on the file.

So, to have an alias that runs git add and builds up a message, you would select your own file location—you can pick one inside .git if you don't mind living slightly dangerously, or you can use one in some other location to keep it away from Git in case Git should decide to munch on it for some reason—and use that to build up the message-so-far. You'd then run git commit --edit -F path so that Git starts with the message-so-far, but lets you edit it further. You'll need to decide how and when to empty out this accumulation file: presumably, after a successful commit would be a good time.


1A good commit message should never repeat what the commit does. That's easily discovered by the computer for you, using git log -p or git show --name-status or whatever. The commit message should explain why you made the changes you made:

commit 637799bf0ab72a509e1f2b29ee6ab3367eefbff9
Author: Carlo Marcelo Arenas Belón <carenas gmail.com>
Date:   Thu Sep 16 01:55:22 2021 -0700

    tree-diff: fix leak when not HAVE_ALLOCA_H
    
    b8ba412bf7 (tree-diff: avoid alloca for large allocations, 2016-06-07)
    adds a way to route some bigger allocations out of the stack and free
    them through the addition of two conveniently named macros, but leaves
    the calls to free the xalloca part, which could be also in the heap,
    if the system doesn't HAVE_ALLOCA_H (ex: macOS and other BSD).
    
    Add the missing free call, xalloca_free(), which is a noop if we
    allocated memory in the stack frame, but a real free() if we
    allocated in the heap instead, and while at it, change the expression
    to match in both macros for ease of readability.
    
    This avoids a leak reported by LSAN while running t0000 but that
    wouldn't fail the test (which is fixed in the next patch):
    
      SUMMARY: LeakSanitizer: 1034 byte(s) leaked in 15 allocation(s).
    
    Signed-off-by: Carlo Marcelo Arenas Belón <[email protected]>
    Signed-off-by: Junio C Hamano <[email protected]>

Compare this to the actual diff:

diff --git a/tree-diff.c b/tree-diff.c
index 1572615bd9..437c98a70e 100644
--- a/tree-diff.c
    b/tree-diff.c
@@ -21,7  21,9 @@
                ALLOC_ARRAY((x), nr); \
 } while(0)
 #define FAST_ARRAY_FREE(x, nr) do { \
-       if ((nr) > 2) \
        if ((nr) <= 2) \
                xalloca_free((x)); \
        else \
                free((x)); \
 } while(0)

The diff shows the simple mechanics of the change. The commit text provides context: the FAST_ARRAY_FREE macro had a bug due to the special use of xalloca when n <= 2, and that special use was added in an earlier commit whose hash ID is provided, so that one can look at that commit as well. The actual bad behavior, and the specifics of where, when, and how it can be observed to show that this fix fixes it, is also given.

A commit message that said only "fix bug in tree-diff.c" would not be useful; one that said "fix leak when not HAVE_ALLOCA_H"—the one line summary—would be; but this one is good.

CodePudding user response:

Well - actually you created 3 commits so what you will need to do is : git rebase -i HEAD~3 which open an interactive rebase of the last 3 commits ( the 3 after HEAD~ ).

in the interactive rebase screen you can squash all 3 commits into 1 ( the last one) and there you can write a custom commit message or concatenate the 3 commits messages to 1.

  •  Tags:  
  • git
  • Related