diff a/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestCheckIssueVisitor.java b/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestCheckIssueVisitor.java
--- a/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestCheckIssueVisitor.java
+++ b/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestCheckIssueVisitor.java
@@ -189,11 +189,12 @@
         log.fine("ignored: incorrectly formatted commit message");
     }
 
     @Override
     public void visit(IssuesIssue issue) {
-        messages.add("The commit message does not reference any issue");
+        messages.add("The commit message does not reference any issue. To add an issue reference to this PR, " +
+                "edit the title to be of the format <issue number>: <message>.");
         failedChecks.add(issue.check().getClass());
         readyForReview = false;
     }
 
     @Override
diff a/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestInstance.java b/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestInstance.java
--- a/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestInstance.java
+++ b/bots/pr/src/main/java/org/openjdk/skara/bots/pr/PullRequestInstance.java
@@ -79,17 +79,17 @@
                                                                comments).stream()
                                                  .map(email -> Author.fromString(email.toString()))
                                                  .collect(Collectors.toList());
 
         var summary = Summary.summary(pr.repository().host().getCurrentUserDetails(), comments);
-
-        var commitMessage = CommitMessage.title(isMerge ? "Merge" : pr.getTitle())
-                                         .contributors(additionalContributors)
+        var issue = Issue.fromString(pr.getTitle());
+        var commitMessageBuilder = issue.map(CommitMessage::title).orElseGet(() -> CommitMessage.title(isMerge ? "Merge" : pr.getTitle()));
+        commitMessageBuilder.contributors(additionalContributors)
                                          .reviewers(reviewers);
-        summary.ifPresent(commitMessage::summary);
+        summary.ifPresent(commitMessageBuilder::summary);
 
-        return String.join("\n", commitMessage.format(CommitMessageFormatters.v1));
+        return String.join("\n", commitMessageBuilder.format(CommitMessageFormatters.v1));
     }
 
     private Hash commitSquashed(List<Review> activeReviews, Namespace namespace, String censusDomain, String sponsorId) throws IOException {
         localRepo.checkout(baseHash, true);
         localRepo.squash(headHash);
diff a/bots/pr/src/test/java/org/openjdk/skara/bots/pr/CheckTests.java b/bots/pr/src/test/java/org/openjdk/skara/bots/pr/CheckTests.java
--- a/bots/pr/src/test/java/org/openjdk/skara/bots/pr/CheckTests.java
+++ b/bots/pr/src/test/java/org/openjdk/skara/bots/pr/CheckTests.java
@@ -26,11 +26,11 @@
 import org.openjdk.skara.test.*;
 
 import org.junit.jupiter.api.*;
 
 import java.io.IOException;
-import java.nio.file.Files;
+import java.nio.file.*;
 import java.util.*;
 import java.util.regex.Pattern;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.junit.jupiter.api.Assumptions.assumeTrue;
@@ -731,6 +731,53 @@
 
             // The PR should now be ready for review
             assertTrue(pr.getLabels().contains("rfr"));
         }
     }
+
+    @Test
+    void issueIssue(TestInfo testInfo) throws IOException {
+        try (var credentials = new HostCredentials(testInfo);
+             var tempFolder = new TemporaryDirectory()) {
+            var author = credentials.getHostedRepository();
+            var reviewer = credentials.getHostedRepository();
+
+            var censusBuilder = credentials.getCensusBuilder()
+                                           .addAuthor(author.host().getCurrentUserDetails().id())
+                                           .addReviewer(reviewer.host().getCurrentUserDetails().id());
+            var checkBot = new PullRequestBot(author, censusBuilder.build(), "master", Map.of(), Map.of(),
+                                              Map.of(), Set.of(), Map.of());
+
+            // Populate the projects repository
+            var localRepo = CheckableRepository.init(tempFolder.path(), author.getRepositoryType(), Path.of("appendable.txt"),
+                                                     Set.of("issues"));
+            var masterHash = localRepo.resolve("master").orElseThrow();
+            localRepo.push(masterHash, author.getUrl(), "master", true);
+
+            // Make a change with a corresponding PR
+            var editHash = CheckableRepository.appendAndCommit(localRepo);
+            localRepo.push(editHash, author.getUrl(), "edit", true);
+            var pr = credentials.createPullRequest(author, "master", "edit", "This is a pull request");
+
+            // Check the status
+            TestBotRunner.runPeriodicItems(checkBot);
+
+            // Verify that the check failed
+            var checks = pr.getChecks(editHash);
+            assertEquals(1, checks.size());
+            var check = checks.get("jcheck");
+            assertEquals(CheckStatus.FAILURE, check.status());
+
+            // Add an issue to the title
+            pr.setTitle("1234: This is a pull request");
+
+            // Check the status again
+            TestBotRunner.runPeriodicItems(checkBot);
+
+            // The check should now be successful
+            checks = pr.getChecks(editHash);
+            assertEquals(1, checks.size());
+            check = checks.get("jcheck");
+            assertEquals(CheckStatus.SUCCESS, check.status());
+        }
+    }
 }
diff a/host/src/main/java/org/openjdk/skara/host/PullRequest.java b/host/src/main/java/org/openjdk/skara/host/PullRequest.java
--- a/host/src/main/java/org/openjdk/skara/host/PullRequest.java
+++ b/host/src/main/java/org/openjdk/skara/host/PullRequest.java
@@ -107,10 +107,16 @@
      * Title of the request.
      * @return
      */
     String getTitle();
 
+    /**
+     * Update the title of the request.
+     * @param title
+     */
+    void setTitle(String title);
+
     /**
      * The main body of the request.
      * @return
      */
     String getBody();
diff a/host/src/main/java/org/openjdk/skara/host/github/GitHubPullRequest.java b/host/src/main/java/org/openjdk/skara/host/github/GitHubPullRequest.java
--- a/host/src/main/java/org/openjdk/skara/host/github/GitHubPullRequest.java
+++ b/host/src/main/java/org/openjdk/skara/host/github/GitHubPullRequest.java
@@ -210,10 +210,15 @@
     @Override
     public String getTitle() {
         return json.get("title").asString();
     }
 
+    @Override
+    public void setTitle(String title) {
+        throw new RuntimeException("not implemented yet");
+    }
+
     @Override
     public String getBody() {
         var body = json.get("body").asString();
         if (body == null) {
             body = "";
diff a/host/src/main/java/org/openjdk/skara/host/gitlab/GitLabMergeRequest.java b/host/src/main/java/org/openjdk/skara/host/gitlab/GitLabMergeRequest.java
--- a/host/src/main/java/org/openjdk/skara/host/gitlab/GitLabMergeRequest.java
+++ b/host/src/main/java/org/openjdk/skara/host/gitlab/GitLabMergeRequest.java
@@ -252,10 +252,15 @@
     @Override
     public String getTitle() {
         return json.get("title").asString();
     }
 
+    @Override
+    public void setTitle(String title) {
+        throw new RuntimeException("not implemented yet");
+    }
+
     @Override
     public String getBody() {
         var body = json.get("description").asString();
         if (body == null) {
             body = "";
diff a/test/src/main/java/org/openjdk/skara/test/CheckableRepository.java b/test/src/main/java/org/openjdk/skara/test/CheckableRepository.java
--- a/test/src/main/java/org/openjdk/skara/test/CheckableRepository.java
+++ b/test/src/main/java/org/openjdk/skara/test/CheckableRepository.java
@@ -22,13 +22,14 @@
  */
 package org.openjdk.skara.test;
 
 import org.openjdk.skara.vcs.*;
 
-import java.io.*;
+import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.*;
+import java.util.Set;
 
 public class CheckableRepository {
     private static String markerLine = "The very first line\n";
 
     private static Path checkableFile(Path path) throws IOException {
@@ -36,11 +37,11 @@
             var checkableName = checkable.readLine();
             return path.resolve(checkableName);
         }
     }
 
-    public static Repository init(Path path, VCS vcs, Path appendableFilePath) throws IOException {
+    public static Repository init(Path path, VCS vcs, Path appendableFilePath, Set<String> checks) throws IOException {
         var repo = Repository.init(path, vcs);
 
         Files.createDirectories(path.resolve(".checkable"));
         try (var output = Files.newBufferedWriter(path.resolve(".checkable/name.txt"))) {
             output.write(appendableFilePath.toString());
@@ -58,12 +59,13 @@
         try (var output = Files.newBufferedWriter(checkConf)) {
             output.append("[general]\n");
             output.append("project=test\n");
             output.append("\n");
             output.append("[checks]\n");
-            output.append("error=author,reviewers,whitespace\n");
-            output.append("\n");
+            output.append("error=");
+            output.append(String.join(",", checks));
+            output.append("\n\n");
             output.append("[census]\n");
             output.append("version=0\n");
             output.append("domain=openjdk.java.net\n");
             output.append("\n");
             output.append("[checks \"whitespace\"]\n");
@@ -77,10 +79,14 @@
         repo.commit("Initial commit", "testauthor", "ta@none.none");
 
         return repo;
     }
 
+    public static Repository init(Path path, VCS vcs, Path appendableFilePath) throws IOException {
+        return init(path, vcs, appendableFilePath, Set.of("author", "reviewers", "whitespace"));
+    }
+
     public static Repository init(Path path, VCS vcs) throws IOException {
         return init(path, vcs, Path.of("appendable.txt"));
     }
 
     public static Hash appendAndCommit(Repository repo) throws IOException {
diff a/test/src/main/java/org/openjdk/skara/test/TestPullRequest.java b/test/src/main/java/org/openjdk/skara/test/TestPullRequest.java
--- a/test/src/main/java/org/openjdk/skara/test/TestPullRequest.java
+++ b/test/src/main/java/org/openjdk/skara/test/TestPullRequest.java
@@ -37,36 +37,33 @@
     private final String id;
     private final HostUserDetails author;
     private final HostUserDetails user;
     private final String targetRef;
     private final String sourceRef;
-    private final String title;
-    private final List<String> body;
     private final PullRequestData data;
 
     private static class PullRequestData {
         private Hash headHash;
         PullRequest.State state = PullRequest.State.OPEN;
         String body = "";
+        String title = "";
         final List<Comment> comments = new ArrayList<>();
         final List<ReviewComment> reviewComments = new ArrayList<>();
         final Set<Check> checks = new HashSet<>();
         final Set<String> labels = new HashSet<>();
         final List<Review> reviews = new ArrayList<>();
         ZonedDateTime created = ZonedDateTime.now();
         ZonedDateTime lastUpdate = created;
     }
 
-    private TestPullRequest(TestHostedRepository repository, String id, HostUserDetails author, HostUserDetails user, String targetRef, String sourceRef, String title, List<String> body, PullRequestData data) {
+    private TestPullRequest(TestHostedRepository repository, String id, HostUserDetails author, HostUserDetails user, String targetRef, String sourceRef, PullRequestData data) {
         this.repository = repository;
         this.id = id;
         this.author = author;
         this.user = user;
         this.targetRef = targetRef;
-        this.title = title;
-        this.body = body;
         this.data = data;
 
         try {
             var headHash = repository.localRepository().resolve(sourceRef).orElseThrow();
             if (!headHash.equals(data.headHash)) {
@@ -78,17 +75,18 @@
         }
     }
 
     static TestPullRequest createNew(TestHostedRepository repository, String id, String targetRef, String sourceRef, String title, List<String> body) {
         var data = new PullRequestData();
+        data.title = title;
         data.body = String.join("\n", body);
-        var pr = new TestPullRequest(repository, id, repository.host().getCurrentUserDetails(), repository.host().getCurrentUserDetails(), targetRef, sourceRef, title, body, data);
+        var pr = new TestPullRequest(repository, id, repository.host().getCurrentUserDetails(), repository.host().getCurrentUserDetails(), targetRef, sourceRef, data);
         return pr;
     }
 
     static TestPullRequest createFrom(TestHostedRepository repository, TestPullRequest other) {
-        var pr = new TestPullRequest(repository, other.id, other.author, repository.host().getCurrentUserDetails(), other.targetRef, other.sourceRef, other.title, other.body, other.data);
+        var pr = new TestPullRequest(repository, other.id, other.author, repository.host().getCurrentUserDetails(), other.targetRef, other.sourceRef, other.data);
         return pr;
     }
 
     @Override
     public HostedRepository repository() {
@@ -170,11 +168,17 @@
         return repository.getBranchHash(targetRef);
     }
 
     @Override
     public String getTitle() {
-        return title;
+        return data.title;
+    }
+
+    @Override
+    public void setTitle(String title) {
+        data.title = title;
+        data.lastUpdate = ZonedDateTime.now();
     }
 
     @Override
     public String getBody() {
         return data.body;
