Improve reject message if Change-Id is in subject

Some users that are new to Git and Gerrit manage to create commits
without subject and message, but with a Change-Id footer. This happens
mainly from EGit where the Change-Id footer is inserted automatically
and users just confirm the commit dialog without typing any subject or
message. This results in a commit message that looks like this:
"
Change-Id: I4bcf4f0bd8ed8da41ce53efd7298b80cec492d64
"

Pushing this change for review if Change-Id is required results in the
following error message:

"remote: ERROR: missing Change-Id in commit message footer
remote: Suggestion for commit message:
remote:
remote: Change-Id: I4bcf4f0bd8ed8da41ce53efd7298b80cec492d64"

This confuses the users since
a) they have a Change-Id in the commit message and
b) the suggested commit message looks like the existing commit message.

Handle this special case and provide a specific error message:
"missing subject, Change-Id must be in commit message footer"

Change-Id: I4bcf4f0bd8ed8da41ce53efd7298b80cec492d64
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/error-messages.txt b/Documentation/error-messages.txt
index 7679470..16bc37b 100644
--- a/Documentation/error-messages.txt
+++ b/Documentation/error-messages.txt
@@ -18,6 +18,7 @@
 * link:error-invalid-changeid-line.html[invalid Change-Id line format in commit message footer]
 * link:error-invalid-committer.html[invalid committer]
 * link:error-missing-changeid.html[missing Change-Id in commit message footer]
+* link:error-missing-subject.html[missing subject; Change-Id must be in commit message footer]
 * link:error-multiple-changeid-lines.html[multiple Change-Id lines in commit message footer]
 * link:error-no-changes-made.html[no changes made]
 * link:error-no-common-ancestry.html[no common ancestry]
diff --git a/Documentation/error-missing-changeid.txt b/Documentation/error-missing-changeid.txt
index 4034ee5..714d65e 100644
--- a/Documentation/error-missing-changeid.txt
+++ b/Documentation/error-missing-changeid.txt
@@ -10,7 +10,6 @@
 . missing Change-Id in the commit message
 . Change-Id is contained in the commit message but not in the last
   paragraph
-. Change-Id is the only line in the commit message
 
 You can see the commit messages for existing commits in the history
 by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log].
@@ -49,19 +48,6 @@
 Change-ID into the last paragraph. How to update the commit message
 is explained link:error-push-fails-due-to-commit-message.html[here].
 
-== Change-Id is the only line in the commit message
-
-Gerrit does not parse the subject of a commit message for the
-Change-Id even if this is the only and last paragraph of the commit
-message.
-
-If the Change-Id is the only line in the commit message you must update
-the commit message and insert a subject as the first line in the commit
-message. The Change-Id must be in the last paragraph of the commit
-message, i.e. separated from the subject by a blank line. How to update
-the commit message is explained
-link:error-push-fails-due-to-commit-message.html[here].
-
 
 GERRIT
 ------
diff --git a/Documentation/error-missing-subject.txt b/Documentation/error-missing-subject.txt
new file mode 100644
index 0000000..3703ade
--- /dev/null
+++ b/Documentation/error-missing-subject.txt
@@ -0,0 +1,33 @@
+= missing subject; Change-Id must be in commit message footer
+
+With this error message Gerrit rejects to push a commit to a project
+which is configured to always require a Change-Id in the commit
+message if the commit message of the pushed commit does not contain
+a subject and a message, but only a Change-Id.
+
+This error happens if the Change-Id is the only line in the commit
+message.
+
+You can see the commit messages for existing commits in the history
+by doing a link:http://www.kernel.org/pub/software/scm/git/docs/git-log.html[git log].
+
+== Change-Id is the only line in the commit message
+
+Gerrit does not parse the subject of a commit message for the
+Change-Id even if this is the only and last paragraph of the commit
+message.
+
+If the Change-Id is the only line in the commit message you must update
+the commit message and insert a subject as the first line in the commit
+message. The Change-Id must be in the last paragraph of the commit
+message, i.e. separated from the subject by a blank line. How to update
+the commit message is explained
+link:error-push-fails-due-to-commit-message.html[here].
+
+
+GERRIT
+------
+Part of link:error-messages.html[Gerrit Error Messages]
+
+SEARCHBOX
+---------
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
index 3c6c9ea..1bf754a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/validators/CommitValidators.java
@@ -186,10 +186,19 @@
 
       if (idList.isEmpty()) {
         if (projectControl.getProjectState().isRequireChangeID()) {
-          String errMsg = "missing Change-Id in commit message footer";
-          messages.add(getFixedCommitMsgWithChangeId(
-              errMsg, receiveEvent.commit));
-          throw new CommitValidationException(errMsg, messages);
+          String shortMsg = receiveEvent.commit.getShortMessage();
+          String changeIdPrefix = CHANGE_ID.getName() + ":";
+          if (shortMsg.startsWith(changeIdPrefix)
+              && shortMsg.substring(changeIdPrefix.length()).trim()
+                  .matches("^I[0-9a-f]{8,}.*$")) {
+            throw new CommitValidationException(
+                "missing subject; Change-Id must be in commit message footer");
+          } else {
+            String errMsg = "missing Change-Id in commit message footer";
+            messages.add(getFixedCommitMsgWithChangeId(
+                errMsg, receiveEvent.commit));
+            throw new CommitValidationException(errMsg, messages);
+          }
         }
       } else if (idList.size() > 1) {
         throw new CommitValidationException(