diff --git a/examples/index.html b/examples/index.html
index f2bdf7225..d0788851e 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -25,6 +25,7 @@ <h1>Vue Router Examples</h1>
     <li><a href="auth-flow">Auth Flow</a></li>
     <li><a href="discrete-components">Discrete Components</a></li>
     <li><a href="nested-router">Nested Routers</a></li>
+    <li><a href="push-or-replace">Push Or Replace</a></li>
   </ul>
 </body>
 </html>
diff --git a/examples/push-or-replace/app.js b/examples/push-or-replace/app.js
new file mode 100644
index 000000000..30439a261
--- /dev/null
+++ b/examples/push-or-replace/app.js
@@ -0,0 +1,73 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+
+Vue.use(VueRouter)
+
+const Home = { template: '<div>home {{$route.query.time}}</div>' }
+const Page = { template: '<div>page {{$route.query.time}}</div>' }
+const Detail = { template: '<div>detail {{$route.query.time}}</div>' }
+
+const router = new VueRouter({
+  mode: 'history',
+  base: __dirname,
+  routes: [
+    { path: '/', component: Home },
+
+    { path: '/page', component: Page },
+
+    { path: '/detail', component: Detail }
+
+  ]
+})
+
+// User can check the replace type in navigation guard, and do anything they want.
+router.beforeEach((to, from, next) => {
+  if (to.replace) {
+    to.query.replace = true
+  } else {
+    to.query.replace = false
+  }
+
+  if (to && to.query && !to.query.time) {
+    to.query.time = new Date().getTime()
+    next(to)
+  } else {
+    next()
+  }
+})
+
+new Vue({
+  router,
+  template: `
+    <div id="app">
+      <h1>Push Or Replace</h1>
+      <p>User can check the replace type in navigation guard, and do anything they want.</p>
+      <pre>
+router.beforeEach((to, from, next) => {
+  if (to.replace) {
+    to.query.replace = true
+  }
+  else {
+    to.query.replace = false
+  }
+
+  if (to && to.query && !to.query.time) {
+    to.query.time = new Date().getTime()
+    next(to)
+  } else {
+    next()
+  }
+})
+      </pre>
+      <ul>
+        <li><router-link to="/">/</router-link></li>
+        <li><router-link to="/page">/page</router-link> ( push )</li>
+        <li><a @click="$router.push('/page')">/page</a> $router.push('/page') </li>
+        <li><router-link to="/detail" replace>/detail</router-link> ( replace )</li>
+        <li><a @click="$router.replace('/detail')">/detail</a> $router.replace('/detail') </li>
+        <li><a @click="$router.go(-1)">back</a> $router.go(-1) </li>
+      </ul>
+      <router-view class="view"></router-view>
+    </div>
+  `
+}).$mount('#app')
diff --git a/examples/push-or-replace/index.html b/examples/push-or-replace/index.html
new file mode 100644
index 000000000..ffb26c918
--- /dev/null
+++ b/examples/push-or-replace/index.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<link rel="stylesheet" href="/global.css">
+<a href="/">&larr; Examples index</a>
+<div id="app"></div>
+<script src="/__build__/shared.js"></script>
+<script src="/__build__/push-or-replace.js"></script>
diff --git a/src/history/hash.js b/src/history/hash.js
index f4a2f3828..5a02c7958 100644
--- a/src/history/hash.js
+++ b/src/history/hash.js
@@ -55,6 +55,12 @@ export class HashHistory extends History {
 
   replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
     const { current: fromRoute } = this
+    if (typeof location === 'string') {
+      location = { path: location }
+    }
+    if (typeof location === 'object' && !location.replace) {
+      (location: Object).replace = true
+    }
     this.transitionTo(location, route => {
       replaceHash(route.fullPath)
       handleScroll(this.router, route, fromRoute, false)
diff --git a/src/history/html5.js b/src/history/html5.js
index 95c47344c..2dfc30297 100644
--- a/src/history/html5.js
+++ b/src/history/html5.js
@@ -52,6 +52,12 @@ export class HTML5History extends History {
 
   replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
     const { current: fromRoute } = this
+    if (typeof location === 'string') {
+      location = { path: location }
+    }
+    if (typeof location === 'object' && !location.replace) {
+      (location: Object).replace = true
+    }
     this.transitionTo(location, route => {
       replaceState(cleanPath(this.base + route.fullPath))
       handleScroll(this.router, route, fromRoute, false)
diff --git a/src/util/location.js b/src/util/location.js
index 5e482aebe..316df9340 100644
--- a/src/util/location.js
+++ b/src/util/location.js
@@ -52,10 +52,13 @@ export function normalizeLocation (
     hash = `#${hash}`
   }
 
+  const replace = next.replace || false
+
   return {
     _normalized: true,
     path,
     query,
+    replace,
     hash
   }
 }
diff --git a/src/util/route.js b/src/util/route.js
index 54a91a738..13ce80f9e 100644
--- a/src/util/route.js
+++ b/src/util/route.js
@@ -23,6 +23,7 @@ export function createRoute (
     meta: (record && record.meta) || {},
     path: location.path || '/',
     hash: location.hash || '',
+    replace: location.replace || false,
     query,
     params: location.params || {},
     fullPath: getFullPath(location, stringifyQuery),