diff --git a/mercurial/formatter.py b/mercurial/formatter.py
index 20dbca5817272e8beb5c6228d3ca781a5ae9a97d_bWVyY3VyaWFsL2Zvcm1hdHRlci5weQ==..34ecc0a09c76d31b5a3edaa86c934761a22da64f_bWVyY3VyaWFsL2Zvcm1hdHRlci5weQ== 100644
--- a/mercurial/formatter.py
+++ b/mercurial/formatter.py
@@ -579,5 +579,5 @@
         if self._hasnodespec(origmapping) and self._hasnodespec(newmapping):
             orignode = templateutil.runsymbol(context, origmapping, 'node')
             mapping['originalnode'] = orignode
-        # put marker to override 'fctx' in mapping if any, and flag
+        # put marker to override 'ctx'/'fctx' in mapping if any, and flag
         # its existence to be reported by availablekeys()
@@ -583,4 +583,6 @@
         # its existence to be reported by availablekeys()
+        if 'ctx' not in newmapping and self._hasliteral(newmapping, 'node'):
+            mapping['ctx'] = _placeholder
         if 'fctx' not in newmapping and self._hasliteral(newmapping, 'path'):
             mapping['fctx'] = _placeholder
         return mapping
@@ -606,6 +608,16 @@
         """Test if context revision is set or unset in the given mapping"""
         return 'node' in mapping or 'ctx' in mapping
 
+    def _loadctx(self, mapping):
+        repo = self._getsome(mapping, 'repo')
+        node = self._getliteral(mapping, 'node')
+        if repo is None or node is None:
+            return
+        try:
+            return repo[node]
+        except error.RepoLookupError:
+            return None # maybe hidden/non-existent node
+
     def _loadfctx(self, mapping):
         ctx = self._getsome(mapping, 'ctx')
         path = self._getliteral(mapping, 'path')
@@ -617,6 +629,7 @@
             return None # maybe removed file?
 
     _loadermap = {
+        'ctx': _loadctx,
         'fctx': _loadfctx,
     }
 
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
index 20dbca5817272e8beb5c6228d3ca781a5ae9a97d_bWVyY3VyaWFsL3RlbXBsYXRla3cucHk=..34ecc0a09c76d31b5a3edaa86c934761a22da64f_bWVyY3VyaWFsL3RlbXBsYXRla3cucHk= 100644
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -481,8 +481,6 @@
     mhex = hex(mnode)
     mapping = context.overlaymap(mapping, {'rev': mrev, 'node': mhex})
     f = context.process('manifest', mapping)
-    # TODO: perhaps 'ctx' should be dropped from mapping because manifest
-    # rev and node are completely different from changeset's.
     return templateutil.hybriditem(f, None, f,
                                    lambda x: {'rev': mrev, 'node': mhex})
 
diff --git a/tests/test-template-keywords.t b/tests/test-template-keywords.t
index 20dbca5817272e8beb5c6228d3ca781a5ae9a97d_dGVzdHMvdGVzdC10ZW1wbGF0ZS1rZXl3b3Jkcy50..34ecc0a09c76d31b5a3edaa86c934761a22da64f_dGVzdHMvdGVzdC10ZW1wbGF0ZS1rZXl3b3Jkcy50 100644
--- a/tests/test-template-keywords.t
+++ b/tests/test-template-keywords.t
@@ -58,6 +58,11 @@
   $ hg log -r 'wdir()' -T '{manifest}\n'
   
 
+Changectx-derived keywords are disabled within {manifest} as {node} changes:
+
+  $ hg log -r0 -T 'outer:{p1node} {manifest % "inner:{p1node}"}\n'
+  outer:0000000000000000000000000000000000000000 inner:
+
 Check that {phase} works correctly on parents:
 
   $ cat << EOF > parentphase
diff --git a/tests/test-template-map.t b/tests/test-template-map.t
index 20dbca5817272e8beb5c6228d3ca781a5ae9a97d_dGVzdHMvdGVzdC10ZW1wbGF0ZS1tYXAudA==..34ecc0a09c76d31b5a3edaa86c934761a22da64f_dGVzdHMvdGVzdC10ZW1wbGF0ZS1tYXAudA== 100644
--- a/tests/test-template-map.t
+++ b/tests/test-template-map.t
@@ -1756,5 +1756,5 @@
 
   $ hg -R latesttag log -r tip --style=style1989
   M|test
-  11,test
+  11,
   branch: test