diff --git a/mercurial/help/templates.txt b/mercurial/help/templates.txt
--- a/mercurial/help/templates.txt
+++ b/mercurial/help/templates.txt
@@ -47,6 +47,10 @@ Also, for any expression that returns a 
 
 - expr % "{template}"
 
+As seen in the above example, "{template}" is interpreted as a template.
+To prevent it from being interpreted, you can use an escape character "\{"
+or a raw string prefix, "r'...'".
+
 Some sample command line templates:
 
 - Format lists, e.g. files::
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -22,7 +22,7 @@ elements = {
     ")": (0, None, None),
     "integer": (0, ("integer",), None),
     "symbol": (0, ("symbol",), None),
-    "string": (0, ("string",), None),
+    "string": (0, ("template",), None),
     "rawstring": (0, ("rawstring",), None),
     "end": (0, None, None),
 }
@@ -144,7 +144,9 @@ def getfilter(exp, context):
     return context._filters[f]
 
 def gettemplate(exp, context):
-    if exp[0] == 'string' or exp[0] == 'rawstring':
+    if exp[0] == 'template':
+        return compiletemplate(exp[1], context)
+    if exp[0] == 'rawstring':
         return compiletemplate(exp[1], context, strtoken=exp[0])
     if exp[0] == 'symbol':
         return context._load(exp[1])
@@ -174,6 +176,12 @@ def runsymbol(context, mapping, key):
         v = list(v)
     return v
 
+def buildtemplate(exp, context):
+    ctmpl = compiletemplate(exp[1], context)
+    if len(ctmpl) == 1:
+        return ctmpl[0]  # fast path for string with no template fragment
+    return (runtemplate, ctmpl)
+
 def runtemplate(context, mapping, template):
     for func, data in template:
         yield func(context, mapping, data)
@@ -362,7 +370,7 @@ def get(context, mapping, args):
 
 def _evalifliteral(arg, context, mapping):
     # get back to token tag to reinterpret string as template
-    strtoken = {runstring: 'string', runrawstring: 'rawstring'}.get(arg[0])
+    strtoken = {runrawstring: 'rawstring'}.get(arg[0])
     if strtoken:
         yield runtemplate(context, mapping,
                           compiletemplate(arg[1], context, strtoken))
@@ -606,6 +614,7 @@ exprmethods = {
     "string": lambda e, c: (runstring, e[1]),
     "rawstring": lambda e, c: (runrawstring, e[1]),
     "symbol": lambda e, c: (runsymbol, e[1]),
+    "template": buildtemplate,
     "group": lambda e, c: compileexp(e[1], c, exprmethods),
 #    ".": buildmember,
     "|": buildfilter,
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -2803,6 +2803,15 @@ unless explicit symbol is expected:
   hg: parse error: expected a symbol, got 'integer'
   [255]
 
+Test string literal:
+
+  $ hg log -Ra -r0 -T '{"string with no template fragment"}\n'
+  string with no template fragment
+  $ hg log -Ra -r0 -T '{"template: {rev}"}\n'
+  template: 0
+  $ hg log -Ra -r0 -T '{r"rawstring: {rev}"}\n'
+  rawstring: {rev}
+
 Test string escaping:
 
   $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'