diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 7b3162786ff08087b13baf023255bf6f612dce1c..69da0fb1f0e3dc05575b5500f5a8e0f440cc9e58 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -673,6 +673,17 @@ VcsBaseEditorWidget *GitClient::findExistingVCSEditor(const char *registerDynami
     return rc;
 }
 
+QTextCodec *GitClient::codecFor(GitClient::CodecType codecType, const QString &source) const
+{
+    if (codecType == CodecSource) {
+        return QFileInfo(source).isFile() ? VcsBaseEditor::getCodec(source)
+                                          : encoding(source, "gui.encoding");
+    }
+    if (codecType == CodecLogOutput)
+        return encoding(source, "i18n.logOutputEncoding");
+    return 0;
+}
+
 void GitClient::slotChunkActionsRequested(QMenu *menu, bool isValid)
 {
     menu->addSeparator();
@@ -746,37 +757,6 @@ void GitClient::stage(const QString &patch, bool revert)
     }
 }
 
-/* Create an editor associated to VCS output of a source file/directory
- * (using the file's codec). Makes use of a dynamic property to find an
- * existing instance and to reuse it (in case, say, 'git diff foo' is
- * already open). */
-VcsBaseEditorWidget *GitClient::createVcsEditor(Id id, QString title,
-                                                const QString &source, // Source file or directory
-                                                CodecType codecType,
-                                                const char *registerDynamicProperty, // Dynamic property and value to identify that editor
-                                                const QString &dynamicPropertyValue) const
-{
-    VcsBaseEditorWidget *rc = 0;
-    QTC_CHECK(!findExistingVCSEditor(registerDynamicProperty, dynamicPropertyValue));
-
-    // Create new, set wait message, set up with source and codec
-    IEditor *outputEditor = EditorManager::openEditorWithContents(id, &title);
-    outputEditor->document()->setProperty(registerDynamicProperty, dynamicPropertyValue);
-    rc = VcsBaseEditor::getVcsBaseEditor(outputEditor);
-    connect(rc, &VcsBaseEditorWidget::annotateRevisionRequested,
-            this, &GitClient::slotBlameRevisionRequested);
-    QTC_ASSERT(rc, return 0);
-    rc->setSource(source);
-    if (codecType == CodecSource)
-        rc->setCodec(getSourceCodec(source));
-    else if (codecType == CodecLogOutput)
-        rc->setCodec(encoding(source, "i18n.logOutputEncoding"));
-
-    rc->setForceReadOnly(true);
-
-    return rc;
-}
-
 void GitClient::requestReload(const QString &documentId, const QString &source,
                               const QString &title,
                               std::function<DiffEditorController *(IDocument *)> factory) const
@@ -889,7 +869,8 @@ void GitClient::log(const QString &workingDirectory, const QString &fileName,
         auto *argWidget = new GitLogArgumentsWidget(settings());
         connect(argWidget, &VcsBaseEditorParameterWidget::commandExecutionRequested,
                 [=]() { this->log(workingDirectory, fileName, enableAnnotationContextMenu, args); });
-        editor = createVcsEditor(editorId, title, sourceFile, CodecLogOutput, "logTitle", msgArg);
+        editor = createVcsEditor(editorId, title, sourceFile, codecFor(CodecLogOutput),
+                                 "logTitle", msgArg);
         editor->setConfigurationWidget(argWidget);
     }
     editor->setFileLogAnnotateEnabled(enableAnnotationContextMenu);
@@ -921,7 +902,7 @@ void GitClient::reflog(const QString &workingDirectory)
     const Id editorId = Git::Constants::GIT_LOG_EDITOR_ID;
     VcsBaseEditorWidget *editor = findExistingVCSEditor("reflogRepository", workingDirectory);
     if (!editor) {
-        editor = createVcsEditor(editorId, title, workingDirectory, CodecLogOutput,
+        editor = createVcsEditor(editorId, title, workingDirectory, codecFor(CodecLogOutput),
                                  "reflogRepository", workingDirectory);
     }
     editor->setWorkingDirectory(workingDirectory);
@@ -974,21 +955,16 @@ void GitClient::show(const QString &source, const QString &id, const QString &na
                                });
 }
 
-void GitClient::slotBlameRevisionRequested(const QString &workingDirectory, const QString &file,
-                                           QString change, int lineNumber)
+void GitClient::annotateRevisionRequested(const QString &workingDirectory, const QString &file,
+                                          const QString &change, int lineNumber)
 {
+    QString sha1 = change;
     // This might be invoked with a verbose revision description
     // "SHA1 author subject" from the annotation context menu. Strip the rest.
-    const int blankPos = change.indexOf(QLatin1Char(' '));
+    const int blankPos = sha1.indexOf(QLatin1Char(' '));
     if (blankPos != -1)
-        change.truncate(blankPos);
-    blame(workingDirectory, QStringList(), file, change, lineNumber);
-}
-
-QTextCodec *GitClient::getSourceCodec(const QString &file) const
-{
-    return QFileInfo(file).isFile() ? VcsBaseEditor::getCodec(file)
-                                    : encoding(file, "gui.encoding");
+        sha1.truncate(blankPos);
+    blame(workingDirectory, QStringList(), file, sha1, lineNumber);
 }
 
 void GitClient::blame(const QString &workingDirectory,
@@ -1011,7 +987,8 @@ void GitClient::blame(const QString &workingDirectory,
                     const int line = VcsBaseEditor::lineNumberOfCurrentEditor();
                     blame(workingDirectory, args, fileName, revision, line);
                 } );
-        editor = createVcsEditor(editorId, title, sourceFile, CodecSource, "blameFileName", id);
+        editor = createVcsEditor(editorId, title, sourceFile, codecFor(CodecSource, sourceFile),
+                                 "blameFileName", id);
         editor->setConfigurationWidget(argWidget);
     }
 
@@ -1564,7 +1541,7 @@ void GitClient::branchesForCommit(const QString &revision)
     auto controller = qobject_cast<DiffEditorController *>(sender());
     QString workingDirectory = controller->baseDirectory();
     auto command = new VcsCommand(vcsBinary(), workingDirectory, processEnvironment());
-    command->setCodec(getSourceCodec(currentDocumentPath()));
+    command->setCodec(codecFor(CodecSource, currentDocumentPath()));
     command->setCookie(workingDirectory);
 
     connect(command, &VcsCommand::output, controller,
@@ -3022,7 +2999,8 @@ void GitClient::subversionLog(const QString &workingDirectory)
     const QString sourceFile = VcsBaseEditor::getSource(workingDirectory, QStringList());
     VcsBaseEditorWidget *editor = findExistingVCSEditor("svnLog", sourceFile);
     if (!editor)
-        editor = createVcsEditor(editorId, title, sourceFile, CodecNone, "svnLog", sourceFile);
+        editor = createVcsEditor(editorId, title, sourceFile, codecFor(CodecNone),
+                                 "svnLog", sourceFile);
     editor->setWorkingDirectory(workingDirectory);
     executeGit(workingDirectory, arguments, editor);
 }
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index efc2127f0611d34ea3bf8afbb36db37e3e05f4b8..8a2bb35bf91b2aaad2103a2aa22b000ccec7d55d 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -349,8 +349,6 @@ public slots:
               const QString &name = QString());
 
 private slots:
-    void slotBlameRevisionRequested(const QString &workingDirectory, const QString &file,
-                                    QString change, int lineNumber);
     void finishSubmoduleUpdate();
     void fetchFinished(const QVariant &cookie);
     void slotChunkActionsRequested(QMenu *menu, bool isValid);
@@ -359,19 +357,15 @@ private slots:
     void branchesForCommit(const QString &revision);
 
 private:
+    void annotateRevisionRequested(const QString &workingDirectory, const QString &file,
+                                   const QString &change, int lineNumber) override;
+
     void stage(const QString &patch, bool revert);
-    QTextCodec *getSourceCodec(const QString &file) const;
     VcsBase::VcsBaseEditorWidget *findExistingVCSEditor(const char *registerDynamicProperty,
                                                         const QString &dynamicPropertyValue) const;
 
     enum CodecType { CodecSource, CodecLogOutput, CodecNone };
-
-    VcsBase::VcsBaseEditorWidget *createVcsEditor(Core::Id kind,
-                                                  QString title,
-                                                  const QString &source,
-                                                  CodecType codecType,
-                                                  const char *registerDynamicProperty,
-                                                  const QString &dynamicPropertyValue) const;
+    QTextCodec *codecFor(CodecType codecType, const QString &source = QString()) const;
 
     void requestReload(const QString &documentId, const QString &source, const QString &title,
                        std::function<DiffEditor::DiffEditorController *(Core::IDocument *)> factory) const;
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index a736d8f622c55cb7d46141806bcb5abcc4bebdd3..7ca29f347f64a12dd33b0b742451928810639f0c 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -282,7 +282,8 @@ void MercurialClient::incoming(const QString &repositoryRoot, const QString &rep
     const QString title = tr("Hg incoming %1").arg(id);
 
     VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG_ID, title, repositoryRoot,
-                                                  true, "incoming", id);
+                                                  VcsBaseEditor::getCodec(repositoryRoot),
+                                                  "incoming", id);
     VcsCommand *cmd = createCommand(repository, editor);
     enqueueJob(cmd, args);
 }
@@ -295,7 +296,8 @@ void MercurialClient::outgoing(const QString &repositoryRoot)
     const QString title = tr("Hg outgoing %1").
             arg(QDir::toNativeSeparators(repositoryRoot));
 
-    VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG_ID, title, repositoryRoot, true,
+    VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG_ID, title, repositoryRoot,
+                                                  VcsBaseEditor::getCodec(repositoryRoot),
                                                   "outgoing", repositoryRoot);
 
     VcsCommand *cmd = createCommand(repositoryRoot, editor);
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index 6ac445db0ccda5500ff36fb659bd1ecaec13a264..2412355b3034f1be01bf0d40872a1b9a1b1ab43c 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -180,6 +180,36 @@ int VcsBaseClientImpl::vcsTimeout() const
     return settings().intValue(VcsBaseClientSettings::timeoutKey);
 }
 
+VcsBaseEditorWidget *VcsBaseClientImpl::createVcsEditor(Core::Id kind, QString title,
+                                                        const QString &source, QTextCodec *codec,
+                                                        const char *registerDynamicProperty,
+                                                        const QString &dynamicPropertyValue) const
+{
+    VcsBaseEditorWidget *baseEditor = 0;
+    Core::IEditor *outputEditor = locateEditor(registerDynamicProperty, dynamicPropertyValue);
+    const QString progressMsg = tr("Working...");
+    if (outputEditor) {
+        // Exists already
+        outputEditor->document()->setContents(progressMsg.toUtf8());
+        baseEditor = VcsBaseEditor::getVcsBaseEditor(outputEditor);
+        QTC_ASSERT(baseEditor, return 0);
+        Core::EditorManager::activateEditor(outputEditor);
+    } else {
+        outputEditor = Core::EditorManager::openEditorWithContents(kind, &title, progressMsg.toUtf8());
+        outputEditor->document()->setProperty(registerDynamicProperty, dynamicPropertyValue);
+        baseEditor = VcsBaseEditor::getVcsBaseEditor(outputEditor);
+        connect(baseEditor, &VcsBaseEditorWidget::annotateRevisionRequested,
+                this, &VcsBaseClientImpl::annotateRevisionRequested);
+        QTC_ASSERT(baseEditor, return 0);
+        baseEditor->setSource(source);
+        if (codec)
+            baseEditor->setCodec(codec);
+    }
+
+    baseEditor->setForceReadOnly(true);
+    return baseEditor;
+}
+
 void VcsBaseClientImpl::saveSettings()
 {
     settings().writeSettings(Core::ICore::settings());
@@ -386,7 +416,8 @@ void VcsBaseClient::annotate(const QString &workingDir, const QString &file,
     const QString title = vcsEditorTitle(vcsCmdString, id);
     const QString source = VcsBaseEditor::getSource(workingDir, file);
 
-    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true,
+    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source,
+                                                  VcsBaseEditor::getCodec(source),
                                                   vcsCmdString.toLatin1().constData(), id);
 
     VcsCommand *cmd = createCommand(workingDir, editor);
@@ -402,7 +433,8 @@ void VcsBaseClient::diff(const QString &workingDir, const QStringList &files,
     const QString id = VcsBaseEditor::getTitleId(workingDir, files);
     const QString title = vcsEditorTitle(vcsCmdString, id);
     const QString source = VcsBaseEditor::getSource(workingDir, files);
-    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true,
+    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source,
+                                                  VcsBaseEditor::getCodec(source),
                                                   vcsCmdString.toLatin1().constData(), id);
     editor->setWorkingDirectory(workingDir);
 
@@ -434,7 +466,8 @@ void VcsBaseClient::log(const QString &workingDir, const QStringList &files,
     const QString id = VcsBaseEditor::getTitleId(workingDir, files);
     const QString title = vcsEditorTitle(vcsCmdString, id);
     const QString source = VcsBaseEditor::getSource(workingDir, files);
-    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true,
+    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source,
+                                                  VcsBaseEditor::getCodec(source),
                                                   vcsCmdString.toLatin1().constData(), id);
     editor->setFileLogAnnotateEnabled(enableAnnotationContextMenu);
 
@@ -555,7 +588,8 @@ void VcsBaseClient::view(const QString &source, const QString &id,
     const Core::Id kind = vcsEditorKind(DiffCommand);
     const QString title = vcsEditorTitle(vcsCommandString(LogCommand), id);
 
-    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source, true, "view", id);
+    VcsBaseEditorWidget *editor = createVcsEditor(kind, title, source,
+                                                  VcsBaseEditor::getCodec(source), "view", id);
 
     const QFileInfo fi(source);
     const QString workingDirPath = fi.isFile() ? fi.absolutePath() : source;
@@ -601,36 +635,6 @@ QString VcsBaseClient::vcsEditorTitle(const QString &vcsCmd, const QString &sour
             Utils::FileName::fromString(sourceId).fileName();
 }
 
-VcsBaseEditorWidget *VcsBaseClient::createVcsEditor(Core::Id kind, QString title,
-                                                    const QString &source, bool setSourceCodec,
-                                                    const char *registerDynamicProperty,
-                                                    const QString &dynamicPropertyValue) const
-{
-    VcsBaseEditorWidget *baseEditor = 0;
-    Core::IEditor *outputEditor = locateEditor(registerDynamicProperty, dynamicPropertyValue);
-    const QString progressMsg = tr("Working...");
-    if (outputEditor) {
-        // Exists already
-        outputEditor->document()->setContents(progressMsg.toUtf8());
-        baseEditor = VcsBaseEditor::getVcsBaseEditor(outputEditor);
-        QTC_ASSERT(baseEditor, return 0);
-        Core::EditorManager::activateEditor(outputEditor);
-    } else {
-        outputEditor = Core::EditorManager::openEditorWithContents(kind, &title, progressMsg.toUtf8());
-        outputEditor->document()->setProperty(registerDynamicProperty, dynamicPropertyValue);
-        baseEditor = VcsBaseEditor::getVcsBaseEditor(outputEditor);
-        connect(baseEditor, &VcsBaseEditorWidget::annotateRevisionRequested,
-                this, &VcsBaseClient::annotateRevision);
-        QTC_ASSERT(baseEditor, return 0);
-        baseEditor->setSource(source);
-        if (setSourceCodec)
-            baseEditor->setCodec(VcsBaseEditor::getCodec(source));
-    }
-
-    baseEditor->setForceReadOnly(true);
-    return baseEditor;
-}
-
 void VcsBaseClient::statusParser(const QString &text)
 {
     QList<VcsBaseClient::StatusItem> lineInfoList;
@@ -646,8 +650,9 @@ void VcsBaseClient::statusParser(const QString &text)
     emit parsedStatus(lineInfoList);
 }
 
-void VcsBaseClient::annotateRevision(const QString &workingDirectory,  const QString &file,
-                                     const QString& change, int lineNumber)
+void VcsBaseClient::annotateRevisionRequested(const QString &workingDirectory,
+                                              const QString &file, const QString &change,
+                                              int line)
 {
     QString changeCopy = change;
     // This might be invoked with a verbose revision description
@@ -655,7 +660,7 @@ void VcsBaseClient::annotateRevision(const QString &workingDirectory,  const QSt
     const int blankPos = changeCopy.indexOf(QLatin1Char(' '));
     if (blankPos != -1)
         changeCopy.truncate(blankPos);
-    annotate(workingDirectory, file, changeCopy, lineNumber);
+    annotate(workingDirectory, file, changeCopy, line);
 }
 
 } // namespace VcsBase
diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h
index d176e926768f51cc738d30fdb6b3feeec7d8e219..e9de7fa20176b754184cd034f6d6809c5c629ec1 100644
--- a/src/plugins/vcsbase/vcsbaseclient.h
+++ b/src/plugins/vcsbase/vcsbaseclient.h
@@ -81,6 +81,11 @@ public:
         VcsWindowOutputBind
     };
 
+    VcsBaseEditorWidget *createVcsEditor(Core::Id kind, QString title,
+                                         const QString &source, QTextCodec *codec,
+                                         const char *registerDynamicProperty,
+                                         const QString &dynamicPropertyValue) const;
+
     VcsCommand *createCommand(const QString &workingDirectory,
                               VcsBaseEditorWidget *editor = 0,
                               JobOutputBindMode mode = NoOutputBind) const;
@@ -92,6 +97,8 @@ public:
 
 protected:
     void resetCachedVcsInfo(const QString &workingDir);
+    virtual void annotateRevisionRequested(const QString &workingDirectory, const QString &file,
+                                           const QString &change, int line) = 0;
 
 private:
     void saveSettings();
@@ -172,6 +179,9 @@ public slots:
                       const QStringList &extraOptions = QStringList());
 
 protected:
+    void annotateRevisionRequested(const QString &workingDirectory, const QString &file,
+                                   const QString &change, int line);
+
     enum VcsCommandTag
     {
         CreateRepositoryCommand,
@@ -212,14 +222,9 @@ protected:
                                                          const QStringList &args,
                                                          unsigned flags = 0,
                                                          QTextCodec *outputCodec = 0) const;
-    VcsBaseEditorWidget *createVcsEditor(Core::Id kind, QString title,
-                                         const QString &source, bool setSourceCodec,
-                                         const char *registerDynamicProperty,
-                                         const QString &dynamicPropertyValue) const;
 
 private:
     void statusParser(const QString&);
-    void annotateRevision(const QString&, const QString&, const QString&, int);
 
     friend class VcsBaseClientPrivate;
     VcsBaseClientPrivate *d;