diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index c3435d386eb57974a86d2df8019dad409a134efc..ec5ad8b3d3e7a6bbe6afd11536dfaccb6be82636 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -638,6 +638,13 @@ const options = [
     type: 'boolean',
     default: null,
   },
+  {
+    name: 'rebaseLabel',
+    description:
+      'Label to use to instruct Renovate to rebase a PR manually (GitHub only)',
+    type: 'string',
+    default: 'rebase',
+  },
   {
     name: 'statusCheckVerify',
     description: '`Set a "renovate/verify" status check for all PRs`',
diff --git a/lib/platform/bitbucket/index.js b/lib/platform/bitbucket/index.js
index acb4484973a3c15dff8dcd846a68521fe5bb99a1..333f41da9dd05f12751e9826f8c1d5490cd1c680 100644
--- a/lib/platform/bitbucket/index.js
+++ b/lib/platform/bitbucket/index.js
@@ -26,10 +26,12 @@ module.exports = {
   deleteBranch,
   mergeBranch,
   getBranchLastCommitTime,
+  // Issue
   ensureIssue,
   ensureIssueClosing,
   addAssignees,
   addReviewers,
+  deleteLabel,
   // Comments
   ensureComment,
   ensureCommentRemoval,
@@ -316,6 +318,11 @@ function addReviewers() {
   return Promise.resolve();
 }
 
+// istanbul ignore next
+function deleteLabel() {
+  throw new Error('deleteLabel not implemented');
+}
+
 function ensureComment() {
   // https://developer.atlassian.com/bitbucket/api/2/reference/search?q=pullrequest+comment
   logger.warn('Comment functionality not implemented yet');
diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js
index 767b0e52277f437d95df7fa3562054cea63eb994..ab5bd1fc3071d6c80cec36bd179c019bdb276401 100644
--- a/lib/platform/github/index.js
+++ b/lib/platform/github/index.js
@@ -40,6 +40,7 @@ module.exports = {
   ensureIssueClosing,
   addAssignees,
   addReviewers,
+  deleteLabel,
   // Comments
   ensureComment,
   ensureCommentRemoval,
@@ -637,6 +638,16 @@ async function addLabels(issueNo, labels) {
   }
 }
 
+async function deleteLabel(issueNo, label) {
+  logger.debug(`Deleting label ${label} from #${issueNo}`);
+  const repository = config.parentRepo || config.repository;
+  try {
+    await get.delete(`repos/${repository}/issues/${issueNo}/labels/${label}`);
+  } catch (err) /* istanbul ignore next */ {
+    logger.warn({ issueNo, label }, 'Failed to delte label');
+  }
+}
+
 async function getComments(issueNo) {
   const pr = (await getClosedPrs())[issueNo];
   if (pr) {
@@ -865,6 +876,11 @@ async function getOpenPrs() {
               title
               mergeable
               mergeStateStatus
+              labels(last: 100) {
+                nodes {
+                  name
+                }
+              }
               commits(first: 2) {
                 nodes {
                   commit {
@@ -952,6 +968,9 @@ async function getOpenPrs() {
             pr.isStale = true;
           }
         }
+        if (pr.labels) {
+          pr.labels = pr.labels.nodes.map(label => label.name);
+        }
         delete pr.mergeable;
         delete pr.mergeStateStatus;
         delete pr.commits;
diff --git a/lib/platform/github/storage.js b/lib/platform/github/storage.js
index 289f3657ed5173651392e2fe97a57144f0851731..cd491ebb4f33085acb23f54b3945696a4fafdaf9 100644
--- a/lib/platform/github/storage.js
+++ b/lib/platform/github/storage.js
@@ -281,7 +281,7 @@ class Storage {
       try {
         if (isBranchExisting) {
           await updateBranch(branchName, commit);
-          logger.info({ branchName }, 'Branch updated');
+          logger.debug({ branchName }, 'Branch updated');
           return 'updated';
         }
         await createBranch(branchName, commit);
diff --git a/lib/platform/gitlab/index.js b/lib/platform/gitlab/index.js
index ed320929a54d3b923ea5e0e34b14701e3a38ecbd..ecb55aaa01c3c8ea2a2d3518ef822c87f1539885 100644
--- a/lib/platform/gitlab/index.js
+++ b/lib/platform/gitlab/index.js
@@ -35,6 +35,7 @@ module.exports = {
   ensureIssueClosing,
   addAssignees,
   addReviewers,
+  deleteLabel,
   // Comments
   ensureComment,
   ensureCommentRemoval,
@@ -487,6 +488,11 @@ function addReviewers(iid, reviewers) {
   logger.warn('Unimplemented in GitLab: approvals');
 }
 
+// istanbul ignore next
+function deleteLabel() {
+  throw new Error('deleteLabel not implemented');
+}
+
 async function getComments(issueNo) {
   // GET projects/:owner/:repo/merge_requests/:number/notes
   logger.debug(`Getting comments for #${issueNo}`);
diff --git a/lib/platform/vsts/index.js b/lib/platform/vsts/index.js
index d637c85ab4340c561a00f3fad80c41b068040c4b..c0ad16b4735fbe7f4527709a9a57469a9b79ab62 100644
--- a/lib/platform/vsts/index.js
+++ b/lib/platform/vsts/index.js
@@ -31,6 +31,7 @@ module.exports = {
   ensureIssueClosing,
   addAssignees,
   addReviewers,
+  deleteLabel,
   // Comments
   ensureComment,
   ensureCommentRemoval,
@@ -576,6 +577,11 @@ async function addReviewers(prNo, reviewers) {
   );
 }
 
+// istanbul ignore next
+function deleteLabel() {
+  throw new Error('deleteLabel not implemented');
+}
+
 // to become async?
 function getPrFiles(prNo) {
   logger.info(`getPrFiles(prNo)(${prNo}) - Not supported by VSTS (yet!)`);
diff --git a/lib/workers/branch/parent.js b/lib/workers/branch/parent.js
index a6b7e5a6208c026ab070d4a8fc715dac7d8ebae0..7ad9c5ce7c80d571c621a2782bb454b2c9a1aa1d 100644
--- a/lib/workers/branch/parent.js
+++ b/lib/workers/branch/parent.js
@@ -15,6 +15,12 @@ async function getParentBranch(config) {
   // Check for existing PR
   const pr = await platform.getBranchPr(branchName);
 
+  if (pr && pr.labels && pr.labels.includes(config.rebaseLabel)) {
+    logger.info({ prNo: pr.number }, 'Manual rebase requested for PR');
+    await platform.deleteLabel(pr.number, config.rebaseLabel);
+    return { parentBranch: undefined };
+  }
+
   if (
     config.rebaseStalePrs ||
     (config.rebaseStalePrs === null && (await platform.getRepoForceRebase())) ||
diff --git a/test/_fixtures/github/graphql/pullrequest-1.json b/test/_fixtures/github/graphql/pullrequest-1.json
index c17fdd04b6414fd8836992d1598cd7f15a690309..ccf390af6072578ead3431e552367fbae6170e9c 100644
--- a/test/_fixtures/github/graphql/pullrequest-1.json
+++ b/test/_fixtures/github/graphql/pullrequest-1.json
@@ -9,6 +9,13 @@
             "title": "build(deps): update got packages (major)",
             "mergeable": "MERGEABLE",
             "mergeStateStatus": "CLEAN",
+            "labels": {
+              "nodes": [
+                {
+                  "name": "blocked"
+                }
+              ]
+            },
             "commits": {
               "nodes": [
                 {
diff --git a/test/platform/__snapshots__/index.spec.js.snap b/test/platform/__snapshots__/index.spec.js.snap
index 6e4a8bc0101fa5c204fb63f516002c8ded055ba9..e6870bffdadcb5da65b534130ba54760acba4222 100644
--- a/test/platform/__snapshots__/index.spec.js.snap
+++ b/test/platform/__snapshots__/index.spec.js.snap
@@ -23,6 +23,7 @@ Array [
   "ensureIssueClosing",
   "addAssignees",
   "addReviewers",
+  "deleteLabel",
   "ensureComment",
   "ensureCommentRemoval",
   "getPrList",
@@ -63,6 +64,7 @@ Array [
   "ensureIssueClosing",
   "addAssignees",
   "addReviewers",
+  "deleteLabel",
   "ensureComment",
   "ensureCommentRemoval",
   "getPrList",
@@ -103,6 +105,7 @@ Array [
   "ensureIssueClosing",
   "addAssignees",
   "addReviewers",
+  "deleteLabel",
   "ensureComment",
   "ensureCommentRemoval",
   "getPrList",
diff --git a/test/platform/github/__snapshots__/index.spec.js.snap b/test/platform/github/__snapshots__/index.spec.js.snap
index c780519bb621a950f84c4ad1169150919caaf636..a6686ab1ee6eeba99f692808a3bbdd1af21a223f 100644
--- a/test/platform/github/__snapshots__/index.spec.js.snap
+++ b/test/platform/github/__snapshots__/index.spec.js.snap
@@ -140,6 +140,14 @@ Array [
 ]
 `;
 
+exports[`platform/github deleteLabel(issueNo, label) should delete the label 1`] = `
+Array [
+  Array [
+    "repos/some/repo/issues/42/labels/rebase",
+  ],
+]
+`;
+
 exports[`platform/github ensureComment add comment if not found 1`] = `
 Array [
   "repos/some/repo/issues/42/comments",
diff --git a/test/platform/github/index.spec.js b/test/platform/github/index.spec.js
index ffa000898ed95330aa42fb0af5449db2ce707c7f..1328a4deebe0d7614156b57901511d128a403de8 100644
--- a/test/platform/github/index.spec.js
+++ b/test/platform/github/index.spec.js
@@ -949,6 +949,16 @@ describe('platform/github', () => {
       await github.ensureIssueClosing('title-2');
     });
   });
+  describe('deleteLabel(issueNo, label)', () => {
+    it('should delete the label', async () => {
+      await initRepo({
+        repository: 'some/repo',
+        token: 'token',
+      });
+      await github.deleteLabel(42, 'rebase');
+      expect(get.delete.mock.calls).toMatchSnapshot();
+    });
+  });
   describe('addAssignees(issueNo, assignees)', () => {
     it('should add the given assignees to the issue', async () => {
       await initRepo({
diff --git a/test/workers/branch/parent.spec.js b/test/workers/branch/parent.spec.js
index 53e3fbeb3378cc39e50a394deb071c942b328756..707fd884bfed08caa4ea8f318957e1c03b26de2b 100644
--- a/test/workers/branch/parent.spec.js
+++ b/test/workers/branch/parent.spec.js
@@ -6,6 +6,7 @@ describe('workers/branch/parent', () => {
     beforeEach(() => {
       config = {
         branchName: 'renovate/some-branch',
+        rebaseLabel: 'rebase',
       };
     });
     afterEach(() => {
@@ -39,6 +40,16 @@ describe('workers/branch/parent', () => {
       const res = await getParentBranch(config);
       expect(res.parentBranch).toBe(config.branchName);
     });
+    it('returns undefined if manual rebase by label', async () => {
+      platform.branchExists.mockReturnValue(true);
+      platform.getBranchPr.mockReturnValue({
+        isUnmergeable: true,
+        canRebase: false,
+        labels: ['rebase'],
+      });
+      const res = await getParentBranch(config);
+      expect(res.parentBranch).toBe(undefined);
+    });
     it('returns undefined if unmergeable and can rebase', async () => {
       platform.branchExists.mockReturnValue(true);
       platform.getBranchPr.mockReturnValue({
diff --git a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
index 2d25bc477e2166e7b43524a0eb7332086c2dcb80..5654110755e36af7e5f896940d829b45ba41c284 100644
--- a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
+++ b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
@@ -46,6 +46,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": null,
     "recreateClosed": false,
     "requiredStatusChecks": Array [],
@@ -116,6 +117,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": null,
     "recreateClosed": false,
     "requiredStatusChecks": Array [],
@@ -183,6 +185,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": true,
     "recreateClosed": true,
     "requiredStatusChecks": Array [],
@@ -256,6 +259,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": null,
     "recreateClosed": false,
     "requiredStatusChecks": Array [],
@@ -323,6 +327,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": true,
     "recreateClosed": true,
     "requiredStatusChecks": Array [],
@@ -396,6 +401,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": null,
     "recreateClosed": false,
     "requiredStatusChecks": Array [],
@@ -466,6 +472,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": null,
     "recreateClosed": false,
     "requiredStatusChecks": Array [],
@@ -536,6 +543,7 @@ Array [
     "prNotPendingHours": 25,
     "prTitle": null,
     "raiseDeprecationWarnings": true,
+    "rebaseLabel": "rebase",
     "rebaseStalePrs": null,
     "recreateClosed": false,
     "requiredStatusChecks": Array [],
diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md
index bdc6928ff3b2a75b485cb992514d39b10688c920..7c13e6767d8df3c48d65f1d0351ae97666e6f488 100644
--- a/website/docs/configuration-options.md
+++ b/website/docs/configuration-options.md
@@ -607,6 +607,10 @@ For example, if your `package.json` specifies a value for `left-pad` of `^1.0.0`
 
 This feature supports simple caret (`^`) and tilde (`~`) ranges only, like `^1.0.0` and `~1.0.0`.
 
+## rebaseLabel
+
+On GitHub it is possible to add a label to a PR to manually request Renovate to recreate/rebase it. By default this label is "rebase" however you can configure it to anything you want by changing this `rebaseLabel` field.
+
 ## rebaseStalePrs
 
 This field is defaulted to `null` because it has a potential to create a lot of noise and additional builds to your repository. If you enable it to true, it means each Renovate branch will be updated whenever the base branch has changed. If enabled, this also means that whenever a Renovate PR is merged (whether by automerge or manually via GitHub web) then any other existing Renovate PRs will then need to get rebased and retested.
diff --git a/website/docs/updating-rebasing.md b/website/docs/updating-rebasing.md
index f3b6eccb49e414c8ad0551f26f0be8f750347284..36206b355d18d43ae6bb565935c0105edc6eba14 100644
--- a/website/docs/updating-rebasing.md
+++ b/website/docs/updating-rebasing.md
@@ -32,3 +32,13 @@ If an existing PR is open to upgrade dependency "foo" to v1.1.0 and then v1.1.1
 
 - Each Renovate branch will always have 1 and only 1 commit
 - The newest version will be based off the latest base branch commit at the time
+
+## Manual rebasing
+
+In GitHub, it is possible to manually request that Renovate rebase a PR by adding the label "rebase" to it. This label name is also configurable via the `rebaseLabel` config option too.
+
+If you apply this label then Renovate will regenerate its commit for the branch, even if the branch has been modified. Therefore it is useful in situations such as:
+
+- If a branch is stale but you don't have `rebaseStalePrs` enabled
+- If a branch has been edited and you wish to discard the edits and have Renovate create it again
+- If a branch was created with an error (e.g. lockfile generation) and you wish to have it retried.