Teach git-commit about commit message templates.
authorSteven Grimm <koreth@midwinter.com>
Mon, 23 Jul 2007 04:17:42 +0000 (21:17 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 Jul 2007 03:46:54 +0000 (20:46 -0700)
These are useful in organizations that enforce particular formats
for commit messages, e.g., to specify bug IDs or test plans.
Use of the template is not enforced; it is simply used as the
initial content when the editor is invoked.

Signed-off-by: Steven Grimm <koreth@midwinter.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-commit.txt
git-commit.sh
t/t7500-commit.sh [new file with mode: 0755]
t/t7500/add-comments [new file with mode: 0755]
t/t7500/add-content [new file with mode: 0755]
t/t7500/add-signed-off [new file with mode: 0755]

index 8e0e7e2d0400b85b05c7e684bc87d9f5f1279e4a..3f36c6782fff2993d83fb2134234f263b0f33120 100644 (file)
@@ -74,6 +74,14 @@ OPTIONS
 -m <msg>|--message=<msg>::
        Use the given <msg> as the commit message.
 
+-t <file>|--template=<file>::
+       Use the contents of the given file as the initial version
+       of the commit message. The editor is invoked and you can
+       make subsequent changes. If a message is specified using
+       the `-m` or `-F` options, this option has no effect. The
+       template file may also be specified using the `commit.template`
+       configuration variable.
+
 -s|--signoff::
        Add Signed-off-by line at the end of the commit message.
 
index 92749df1e75de9af6c60a65866f1f68a21b799fe..4290ae2dd2747b26c521300af1ed5e46ab839264 100755 (executable)
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Linus Torvalds
 # Copyright (c) 2006 Junio C Hamano
 
-USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [[-i | -o] <path>...]'
+USAGE='[-a | --interactive] [-s] [-v] [--no-verify] [-m <message> | -F <logfile> | (-C|-c) <commit> | --amend] [-u] [-e] [--author <author>] [--template <file>] [[-i | -o] <path>...]'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
 require_work_tree
@@ -87,6 +87,7 @@ signoff=
 force_author=
 only_include_assumed=
 untracked_files=
+templatefile="`git config commit.template`"
 while case "$#" in 0) break;; esac
 do
        case "$1" in
@@ -248,6 +249,13 @@ $1"
                signoff=t
                shift
                ;;
+       -t|--t|--te|--tem|--temp|--templ|--templa|--templat|--template)
+               case "$#" in 1) usage ;; esac
+               shift
+               templatefile="$1"
+               no_edit=
+               shift
+               ;;
        -q|--q|--qu|--qui|--quie|--quiet)
                quiet=t
                shift
@@ -321,6 +329,14 @@ t,,[1-9]*)
        die "No paths with -i does not make sense." ;;
 esac
 
+if test ! -z "$templatefile" -a -z "$log_given"
+then
+       if test ! -f "$templatefile"
+       then
+               die "Commit template file does not exist."
+       fi
+fi
+
 ################################################################
 # Prepare index to have a tree to be committed
 
@@ -454,6 +470,9 @@ then
 elif test -f "$GIT_DIR/SQUASH_MSG"
 then
        cat "$GIT_DIR/SQUASH_MSG"
+elif test "$templatefile" != ""
+then
+       cat "$templatefile"
 fi | git stripspace >"$GIT_DIR"/COMMIT_EDITMSG
 
 case "$signoff" in
@@ -572,10 +591,35 @@ else
 fi |
 git stripspace >"$GIT_DIR"/COMMIT_MSG
 
-if cnt=`grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
-       git stripspace |
-       wc -l` &&
-   test 0 -lt $cnt
+# Test whether the commit message has any content we didn't supply.
+have_commitmsg=
+grep -v -i '^Signed-off-by' "$GIT_DIR"/COMMIT_MSG |
+       git stripspace > "$GIT_DIR"/COMMIT_BAREMSG
+
+# Is the commit message totally empty?
+if test -s "$GIT_DIR"/COMMIT_BAREMSG
+then
+       if test "$templatefile" != ""
+       then
+               # Test whether this is just the unaltered template.
+               if cnt=`sed -e '/^#/d' < "$templatefile" |
+                       git stripspace |
+                       diff "$GIT_DIR"/COMMIT_BAREMSG - |
+                       wc -l` &&
+                  test 0 -lt $cnt
+               then
+                       have_commitmsg=t
+               fi
+       else
+               # No template, so the content in the commit message must
+               # have come from the user.
+               have_commitmsg=t
+       fi
+fi
+
+rm -f "$GIT_DIR"/COMMIT_BAREMSG
+
+if test "$have_commitmsg" = "t"
 then
        if test -z "$TMP_INDEX"
        then
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
new file mode 100755 (executable)
index 0000000..f11ada8
--- /dev/null
@@ -0,0 +1,96 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Steven Grimm
+#
+
+test_description='git-commit
+
+Tests for selected commit options.'
+
+. ./test-lib.sh
+
+commit_msg_is () {
+       test "`git log --pretty=format:%s%b -1`" = "$1"
+}
+
+# A sanity check to see if commit is working at all.
+test_expect_success 'a basic commit in an empty tree should succeed' '
+       echo content > foo &&
+       git add foo &&
+       git commit -m "initial commit"
+'
+
+test_expect_success 'nonexistent template file should return error' '
+       echo changes >> foo &&
+       git add foo &&
+       ! git commit --template "$PWD"/notexist
+'
+
+test_expect_success 'nonexistent template file in config should return error' '
+       git config commit.template "$PWD"/notexist &&
+       ! git commit &&
+       git config --unset commit.template
+'
+
+# From now on we'll use a template file that exists.
+TEMPLATE="$PWD"/template
+
+test_expect_success 'unedited template should not commit' '
+       echo "template line" > "$TEMPLATE" &&
+       ! git commit --template "$TEMPLATE"
+'
+
+test_expect_success 'unedited template with comments should not commit' '
+       echo "# comment in template" >> "$TEMPLATE" &&
+       ! git commit --template "$TEMPLATE"
+'
+
+test_expect_success 'a Signed-off-by line by itself should not commit' '
+       ! GIT_EDITOR=../t7500/add-signed-off git commit --template "$TEMPLATE"
+'
+
+test_expect_success 'adding comments to a template should not commit' '
+       ! GIT_EDITOR=../t7500/add-comments git commit --template "$TEMPLATE"
+'
+
+test_expect_success 'adding real content to a template should commit' '
+       GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" &&
+       commit_msg_is "template linecommit message"
+'
+
+test_expect_success '-t option should be short for --template' '
+       echo "short template" > "$TEMPLATE" &&
+       echo "new content" >> foo &&
+       git add foo &&
+       GIT_EDITOR=../t7500/add-content git commit -t "$TEMPLATE" &&
+       commit_msg_is "short templatecommit message"
+'
+
+test_expect_success 'config-specified template should commit' '
+       echo "new template" > "$TEMPLATE" &&
+       git config commit.template "$TEMPLATE" &&
+       echo "more content" >> foo &&
+       git add foo &&
+       GIT_EDITOR=../t7500/add-content git commit &&
+       git config --unset commit.template &&
+       commit_msg_is "new templatecommit message"
+'
+
+test_expect_success 'explicit commit message should override template' '
+       echo "still more content" >> foo &&
+       git add foo &&
+       GIT_EDITOR=../t7500/add-content git commit --template "$TEMPLATE" \
+               -m "command line msg" &&
+       commit_msg_is "command line msg<unknown>"
+'
+
+test_expect_success 'commit message from file should override template' '
+       echo "content galore" >> foo &&
+       git add foo &&
+       echo "standard input msg" |
+               GIT_EDITOR=../t7500/add-content git commit \
+                       --template "$TEMPLATE" --file - &&
+       commit_msg_is "standard input msg<unknown>"
+'
+
+test_done
diff --git a/t/t7500/add-comments b/t/t7500/add-comments
new file mode 100755 (executable)
index 0000000..a72e65c
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+echo "# this is a new comment" >> "$1"
+echo "# and so is this" >> "$1"
+exit 0
diff --git a/t/t7500/add-content b/t/t7500/add-content
new file mode 100755 (executable)
index 0000000..2fa3d86
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo "commit message" >> "$1"
+exit 0
diff --git a/t/t7500/add-signed-off b/t/t7500/add-signed-off
new file mode 100755 (executable)
index 0000000..e1d856a
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+echo "Signed-off-by: foo <bar@frotz>" >> "$1"
+exit 0