gitgithubgitlabcommit-message

Git magic keywords in commit messages (Signed-off-by, Co-authored-by, Fixes, ...)


Git command itself supports the Signed-off-by: Person's name <persons@email> line.

GitHub adds Co-authored-by: line, which then shows both the committer and the referenced person as commit authors in the UI. (See Q: GitHub co-authored-by with private noreply address for discussion how to avoid exposing email addresses.)

Futhermore, GitHub and GitLab each recognize a set of keywords to close issues when a commit is merged.

Is the list of Git magic keywords above complete? Is there a standardization process for adding these lines and keywords? Are these defined to be case insensitive?


Solution

  • From the OP:

    The git command itself supports the Signed-off-by: Person's name <persons@email> line.

    Starting with Git 2.32 (Q2 2021), the git command itself supports... any trailer you want!

    "git commit"(man) learned --trailer <key>[=<value>] option; together with the interpret-trailers command, this will make it easier to support custom trailers.

    See commit 2daae3d (23 Mar 2021) by ZheNing Hu (adlternative).
    (Merged by Junio C Hamano -- gitster -- in commit 68e15e0, 07 Apr 2021)

    commit: add --trailer option

    Signed-off-by: ZheNing Hu

    Historically, Git has supported the 'Signed-off-by' commit trailer using the '--signoff' and the '-s' option from the command line.
    But users may need to provide other trailer information from the command line such as "Helped-by", "Reported-by", "Mentored-by",

    Now implement a new --trailer <token>[(=|:)<value>] option to pass other trailers to interpret-trailers and insert them into commit messages.

    git commit now includes in its man page:

    --trailer <token>[(=|:)<value>]

    Specify a (<token>, <value>) pair that should be applied as a trailer.

    For instance:

    git commit --trailer "Signed-off-by:C O Mitter <committer@example.com>" \
               --trailer "Helped-by:C O Mitter <committer@example.com>"
    

    That will add the "Signed-off-by" trailer and the "Helped-by" trailer to the commit message.

    The trailer.* configuration variables (git interpret-trailers) can be used to define if a duplicated trailer is omitted, where in the run of trailers each trailer would appear, and other details.


    Regarding that trailer.xxx configuration, consider an initial commit that you want to amend with additional trailers:

    Signed-off-by: C O Mitter <committer@example.com>
    Signed-off-by: C1 E1
    Reported-by: C3 E3
    Mentored-by: C4 E4
    Helped-by: C3 E3
    

    A trailer.ifexists="replace" config would, if you amend it by adding the same Reported-by, keep the message unchanged:

    git -c trailer.ifexists="replace" \
        commit   --trailer "Mentored-by: C4 E4" \
                 --trailer "Helped-by: C3 E3" \
                 --amend
    

    But if you amend the same commit with trailer.ifexists="add" would means:

    Signed-off-by: C O Mitter <committer@example.com>
    Signed-off-by: C1 E1
    Helped-by: C2 E2
    Reported-by: C3 E3
    Mentored-by: C4 E4
    Reported-by: C3 E3  <<<< added twice
    Mentored-by: C4 E4  <<<< added twice
    

    And using trailer.ifexists="addIfDifferent"

    git -c trailer.ifexists="addIfDifferent" \
        commit  --trailer "Reported-by: C3 E3" \
                --trailer "Mentored-by: C5 E5" \
                --amend
    

    And you get:

    Signed-off-by: C O Mitter <committer@example.com>
    Signed-off-by: C1 E1
    Helped-by: C2 E2
    Reported-by: C3 E3
    Mentored-by: C4 E4
    Mentored-by: C5 E5  <<<< Only C5 E5 is added
    

    And, still With Git 2.32 (Q2 2021), the way the command line specified by the trailer.<token>.command configuration variable receives the end-user supplied value was both error prone and misleading.
    An alternative to achieve the same goal in a safer and more intuitive way has been added, as the trailer.<token>.cmd configuration variable, to replace it.

    See commit c364b7e, commit 57dcb65 (03 May 2021) by ZheNing Hu (adlternative).
    (Merged by Junio C Hamano -- gitster -- in commit 2cd6ce2, 11 May 2021)

    trailer: add new .cmd config option

    Helped-by: Junio C Hamano
    Helped-by: Christian Couder
    Signed-off-by: ZheNing Hu

    The trailer.<token>.command configuration variable specifies a command (run via the shell, so it does not have to be a single name or path to the command, but can be a shell script), and the first occurrence of substring $ARG is replaced with the value given to the interpret-trailer command for the token in a '--trailer <token>=<value>' argument.

    This has three downsides:

    • The use of $ARG in the mechanism misleads the users that the value is passed in the shell variable, and tempt them to use $ARG more than once, but that would not work, as the second and subsequent $ARG are not replaced.
    • Because $ARG is textually replaced without regard to the shell language syntax, even '$ARG' (inside a single-quote pair), which a user would expect to stay intact, would be replaced, and worse, if the value had an unmatched single quote (imagine a name like "O'Connor", substituted into NAME='$ARG' to make it NAME='O'Connor'), it would result in a broken command that is not syntactically correct (or worse).
    • The first occurrence of substring $ARG will be replaced with the empty string, in the command when the command is first called to add a trailer with the specified <token>.
      This is a bad design, the nature of automatic execution causes it to add a trailer that we don't expect.

    Introduce a new trailer.<token>.cmd configuration that takes higher precedence to deprecate and eventually remove trailer.<token>.command, which passes the value as an argument to the command.
    Instead of "$ARG", users can refer to the value as positional argument, $1, in their scripts.
    At the same time, in order to allow git interpret-trailers(man) to better simulate the behavior of git command -s, 'trailer.<token>.cmd' will not automatically execute.

    git interpret-trailers now includes in its man page:

    This option behaves in the same way as 'trailer.<token>.cmd', except that it doesn't pass anything as argument to the specified command. Instead the first occurrence of substring $ARG is replaced by the value that would be passed as argument.

    The 'trailer.<token>.command' option has been deprecated in favor of 'trailer.<token>.cmd' due to the fact that $ARG in the user's command is only replaced once and that the original way of replacing $ARG is not safe.

    When both 'trailer.<token>.cmd' and 'trailer.<token>.command' are given for the same <token>, 'trailer.<token>.cmd' is used and 'trailer.<token>.command' is ignored.

    trailer.<token>.cmd

    git interpret-trailers now includes in its man page:

    of these arguments, if any, will be passed to the command as its first argument.
    This way the command can produce a computed from the <value> passed in the '--trailer <token>=<value>' argument.

    git interpret-trailers now includes in its man page:

    • Configure a 'help' trailer with a cmd use a script glog-find-author which search specified author identity from git log in git repository and show how it works:
    $ cat ~/bin/glog-find-author
    #!/bin/sh
    test -n "$1" && git log --author="$1" --pretty="%an <%ae>" -1 || true
    $ git config trailer.help.key "Helped-by: "
    $ git config trailer.help.ifExists "addIfDifferentNeighbor"
    $ git config trailer.help.cmd "~/bin/glog-find-author"
    $ git interpret-trailers --trailer="help:Junio" --trailer="help:Couder" <<EOF
    > subject
    >
    > message
    >
    > EOF
    subject
    
    message
    
    Helped-by: Junio C Hamano <gitster@pobox.com>
    Helped-by: Christian Couder <christian.couder@gmail.com>
    
    • Configure a 'ref' trailer with a cmd use a script glog-grep to grep last relevant commit from git log in the git repository and show how it works:
    $ cat ~/bin/glog-grep
    #!/bin/sh
    test -n "$1" && git log --grep "$1" --pretty=reference -1 || true
    $ git config trailer.ref.key "Reference-to: "
    $ git config trailer.ref.ifExists "replace"
    $ git config trailer.ref.cmd "~/bin/glog-grep"
    $ git interpret-trailers --trailer="ref:Add copyright notices." <<EOF
    > subject
    >
    > message
    >
    > EOF
    subject
    
    message
    
    Reference-to: 8bc9a0c769 (Add copyright notices., 2005-04-07)
    

    Bore Git 2.47 (Q4 2024), batch 16, the git interpret-trailers command failed to recognize the end of the message when the commit log ends in an incomplete line.

    See commit c02414a (06 Sep 2024) by Brian Lyles (brianmlyles).
    (Merged by Junio C Hamano -- gitster -- in commit 77cf81e, 13 Sep 2024)

    interpret-trailers: handle message without trailing newline

    Signed-off-by: Brian Lyles

    When git interpret-trailers(man) is used to add a trailer to a message that does not end in a trailing newline, the new trailer is added on the line immediately following the message instead of as a trailer block separated from the message by a blank line.

    For example, if a message's text was exactly "The subject" with no trailing newline present, git interpret-trailers --trailer my-trailer=true will result in the following malformed commit message:

    The subject
    my-trailer: true
    

    While it is generally expected that a commit message should end with a newline character, git interpret-trailers should not be returning an invalid message in this case.

    Use strbuf_complete_line to ensure that the message ends with a newline character when reading the input.