diff --git a/git-hooks/sanitize-commit b/git-hooks/sanitize-commit
index 2d219c0688f39b47fa6e2ddc1555ab099a62102b..1277903af95ec3b31349b675b7c704ada130e4cb 100755
--- a/git-hooks/sanitize-commit
+++ b/git-hooks/sanitize-commit
@@ -11,12 +11,13 @@ use strict;
 use warnings;
 use Cwd;
 
-if ($#ARGV < 0 or $#ARGV > 1 || ($#ARGV == 1 && $ARGV[1] !~ /^(strict|gerrit)$/)) {
+if ($#ARGV < 0 or $#ARGV > 1 || ($#ARGV == 1 && $ARGV[1] !~ /^(strict|gerrit(-rest)?)$/)) {
     print STDERR "Usage: $0 <sha1> [strict]\n";
     exit 2;
 }
 my $sha1 = $ARGV[0];
-my $gerrit = ($#ARGV == 1 && $ARGV[1] eq "gerrit");
+my $gerrit_rest = ($#ARGV == 1 && $ARGV[1] eq "gerrit-rest");
+my $gerrit = $gerrit_rest || ($#ARGV == 1 && $ARGV[1] eq "gerrit");
 my $strict = $gerrit || ($#ARGV == 1 && $ARGV[1] eq "strict");
 
 my $repo = getcwd();
@@ -86,6 +87,12 @@ sub complain_ln($$;$)
     do_complain($lineno, $msg, $key, $level);
 }
 
+sub complain_cln($$;$)
+{
+    my ($msg, $key, $level) = @_;
+    do_complain($gerrit_rest ? $lineno : 0, $msg, $key, $level);
+}
+
 my $clike = 0;
 my $qmake = 0;
 my $iswip = defined($cfg{wip});
@@ -133,11 +140,16 @@ sub check_spelling()
         next if $seen{$word};
         $seen{$word} = 1;
         if (my $correction = $MISTAKES{$word}) {
+            my $sfx = "";
             if (!$MISTAKES_BASE{$word}) {
-                $correction .= ' [*]';
+                $sfx = ' [*]';
                 $footnotes{'[*] Please note, Qt prefers American English.'} = 1;
             }
-            push @spell_fails, "  $lineno: $word -> $correction";
+            if ($gerrit_rest) {
+                complain_ln("$word -> $correction?$sfx", "spell");
+            } else {
+                push @spell_fails, "  $lineno: $word -> $correction$sfx";
+            }
         }
     }
 }
@@ -185,6 +197,7 @@ sub check_apple_terminology()
     }
 }
 
+my $msgline = 0;
 open MSG, "git log -1 --pretty=raw ".$sha1." |" or die "cannot run git: $!";
 while (<MSG>) {
     chomp;
@@ -192,31 +205,33 @@ while (<MSG>) {
         if (/^parent /) {
             $parents++ ;
         } elsif (/^author .*\.\(none\)/) {
-            complain("Bogus author email", "email", 1);
+            do_complain($gerrit_rest ? $parents + 1 : 0, "Bogus author email", "email", 1);
         } elsif (/^commiter .*\.\(none\)/) {
-            complain("Bogus committer email", "email", 1);
+            do_complain($gerrit_rest ? $parents + 3 : 0, "Bogus committer email", "email", 1);
         }
         next
     }
     $lineno++;
-    if ($lineno == 1) {
+    $msgline++;
+    if ($msgline == 1) {
         $summary = $_;
+        $lineno = $parents + 6 if ($gerrit_rest);
         $file = "!!!!!";
         $revert1 = 1 if (/^Revert ".*"$/);
         if (/^revert(ed|ing)? (commit )?[0-9a-f]{7,40}\.?$/i) {
-            complain("Summary of revert mentions only SHA1", "log");
+            complain_cln("Summary of revert mentions only SHA1", "log");
         }
         if (/\bQT[A-Z]+-\d+\b/) {
-            complain("Bug reference in summary", "log");
+            complain_cln("Bug reference in summary", "log");
         }
         if (!$iswip && $parents < 2 && /\bWIP\b|\*{3}|^(?:squash|fixup)! |^(.)\1*$/i) {
-            complain("Apparently pushing a Work In Progress", "wip", 1);
+            complain_cln("Apparently pushing a Work In Progress", "wip", 1);
         } elsif (!$iswip && !$badlog && length($_) < 7) {
-            complain("Summary is too short", "log");
+            complain_cln("Summary is too short", "log");
         } elsif (!$badlog && !$revert1 && length($_) > 120) {
-            complain("Summary is excessively long", "log");
+            complain_cln("Summary is excessively long", "log");
         } elsif ($parents < 2 && !$revert1 && length($_) > 70) {
-            complain("Aim for shorter summaries", "", -1);
+            complain_cln("Aim for shorter summaries", "", -1);
         }
     } else {
         if (/^This reverts commit [[:xdigit:]]{40}\.?$/) {
@@ -224,9 +239,9 @@ while (<MSG>) {
         } elsif (!/^[-\w]+:|^$/) {
             $nonrevert = 1;
         }
-        if ($lineno == 2) {
+        if ($msgline == 2) {
             if (!$badlog && $_ ne "") {
-                complain("2nd line is not empty", "log");
+                complain_cln("2nd line is not empty", "log");
             }
         } elsif ($_ eq "") {
             $cherry = 0;
@@ -405,7 +420,11 @@ my @style_fails = ();
 sub styleFail($)
 {
     my $why = shift;
-    push @style_fails, "  $lineno: ".$why;
+    if ($gerrit_rest) {
+        complain_ln("$why", "style", -1);
+    } else {
+        push @style_fails, "  $lineno: ".$why;
+    }
 }
 
 my $no_copyright = 0;
@@ -636,15 +655,49 @@ if ($mixws_check) {
     flushChunk() if ($chunk);
     if ($nonws and $ws) {
         my @extras;
-        for my $fn (sort keys %ws_lines) {
-            push @extras, "WS-only in ".$fn.": ".join(", ", @{$ws_lines{$fn}});
+        for $file (sort keys %ws_lines) {
+            if ($gerrit_rest) {
+                do_complain($_, "WS-only change", "mixws", -1) foreach (@{$ws_lines{$file}});
+            } else {
+                push @extras, "WS-only in ".$file.": ".join(", ", @{$ws_lines{$file}});
+            }
         }
         $file = "~~~~~";
         do_complain(1e9, "Mixing whitespace-only changes with other changes", "mixws", -1, @extras);
     }
 }
 
-if (%complaints) {
+if ($gerrit_rest) {
+    use JSON;
+    my %gerrit_review;
+    my @cover_texts;
+    foreach my $fn (sort keys %complaints) {
+        my $file;
+        if (length($fn) && ($fn ne "~~~~~")) {
+            $file = ($fn eq "!!!!!") ? "/COMMIT_MSG" : $fn;
+            my @comments = ();
+            foreach my $ln (keys %{$complaints{$fn}}) {
+                my @texts;
+                push @texts, @$_ foreach (@{$complaints{$fn}{$ln}});
+                my %comment;
+                $comment{line} = int($ln) if ($ln && $ln < 1e9);
+                $comment{message} = join "\n\n", @texts;
+                push @comments, \%comment;
+            }
+            $gerrit_review{comments}{$file} = \@comments;
+        } else {
+            foreach my $ln (sort { $a <=> $b } keys %{$complaints{$fn}}) {
+                push @cover_texts, @$_ foreach (@{$complaints{$fn}{$ln}});
+            }
+        }
+    }
+    if (%complaints) {
+        push @cover_texts, $_ for (sort keys %footnotes);
+        push @cover_texts, "See http://qt-project.org/wiki/Early-Warning-System for explanations.";
+        $gerrit_review{message} = join "\n\n", @cover_texts;
+    }
+    print encode_json(\%gerrit_review)."\n";
+} elsif (%complaints) {
     if (!$gerrit) {
         $summary =~ s/^(.{50}).{5,}$/$1\[...]/;
         print "***\n*** Suspicious changes in commit ".$sha1." (".$summary."):\n";