diff --git a/src/plugins/bazaar/bazaareditor.cpp b/src/plugins/bazaar/bazaareditor.cpp
index 48a1687b8dbbe2d7eba642366073a1d7bd1747f6..99c241d12742ff5224700f7af750f89c65c83e8a 100644
--- a/src/plugins/bazaar/bazaareditor.cpp
+++ b/src/plugins/bazaar/bazaareditor.cpp
@@ -52,11 +52,13 @@ using namespace Bazaar;
 BazaarEditor::BazaarEditor(const VcsBase::VcsBaseEditorParameters *type, QWidget *parent)
     : VcsBase::VcsBaseEditorWidget(type, parent),
       m_changesetId(QLatin1String(Constants::CHANGESET_ID)),
-      m_exactChangesetId(QLatin1String(Constants::CHANGESET_ID_EXACT)),
-      m_diffFileId(QLatin1String("^=== [a-z]+ [a-z]+ '(.*)'\\s*"))
+      m_exactChangesetId(QLatin1String(Constants::CHANGESET_ID_EXACT))
 {
     setAnnotateRevisionTextFormat(tr("Annotate %1"));
     setAnnotatePreviousRevisionTextFormat(tr("Annotate parent revision %1"));
+    // Diff format:
+    // === <change> <file|dir> 'mainwindow.cpp'
+    setDiffFilePattern(QRegExp(QLatin1String("^=== [a-z]+ [a-z]+ '(.+)'\\s*")));
 }
 
 QSet<QString> BazaarEditor::annotationChanges() const
@@ -111,25 +113,8 @@ QString BazaarEditor::changeUnderCursor(const QTextCursor &cursorIn) const
     return QString();
 }
 
-QRegExp BazaarEditor::diffFilePattern() const
-{
-    return m_diffFileId;
-}
-
 VcsBase::BaseAnnotationHighlighter *BazaarEditor::createAnnotationHighlighter(const QSet<QString> &changes,
                                                                               const QColor &bg) const
 {
     return new BazaarAnnotationHighlighter(changes, bg);
 }
-
-QString BazaarEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
-{
-    // Check for:
-    // === <change> <file|dir> 'mainwindow.cpp'
-    for (QTextBlock  block = inBlock; block.isValid(); block = block.previous()) {
-        const QString line = block.text();
-        if (m_diffFileId.indexIn(line) != -1)
-            return findDiffFile(m_diffFileId.cap(1));
-    }
-    return QString();
-}
diff --git a/src/plugins/bazaar/bazaareditor.h b/src/plugins/bazaar/bazaareditor.h
index b895fb6593bf899daeb38a6faff2c8ddbec51911..6b92909ecc9cad32ee0f73c03353f89e8292571c 100644
--- a/src/plugins/bazaar/bazaareditor.h
+++ b/src/plugins/bazaar/bazaareditor.h
@@ -46,13 +46,10 @@ public:
 private:
     QSet<QString> annotationChanges() const;
     QString changeUnderCursor(const QTextCursor &cursor) const;
-    QRegExp diffFilePattern() const;
     VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
-    QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const;
 
     mutable QRegExp m_changesetId;
     mutable QRegExp m_exactChangesetId;
-    mutable QRegExp m_diffFileId;
 };
 
 } // namespace Internal
diff --git a/src/plugins/bazaar/bazaarplugin.cpp b/src/plugins/bazaar/bazaarplugin.cpp
index 618b9d3ca7b0546e0d8646684257e03fb39bb507..bfee3ee6348f163fcbb77765d74eddd421a3b084 100644
--- a/src/plugins/bazaar/bazaarplugin.cpp
+++ b/src/plugins/bazaar/bazaarplugin.cpp
@@ -591,6 +591,41 @@ void BazaarPlugin::diffFromEditorSelected(const QStringList &files)
     m_client->diff(m_submitRepository, files);
 }
 
+#ifdef WITH_TESTS
+#include <QTest>
+
+void BazaarPlugin::testDiffFileResolving_data()
+{
+    QTest::addColumn<QByteArray>("header");
+    QTest::addColumn<QByteArray>("fileName");
+
+    QTest::newRow("New") << QByteArray(
+            "=== added file 'src/plugins/bazaar/bazaareditor.cpp'\n"
+            "--- src/plugins/bazaar/bazaareditor.cpp\t1970-01-01 00:00:00 +0000\n"
+            "+++ src/plugins/bazaar/bazaareditor.cpp\t2013-01-20 21:39:47 +0000\n"
+            "@@ -0,0 +1,121 @@\n\n")
+        << QByteArray("src/plugins/bazaar/bazaareditor.cpp");
+    QTest::newRow("Deleted") << QByteArray(
+            "=== removed file 'src/plugins/bazaar/bazaareditor.cpp'\n"
+            "--- src/plugins/bazaar/bazaareditor.cpp\t2013-01-20 21:39:47 +0000\n"
+            "+++ src/plugins/bazaar/bazaareditor.cpp\t1970-01-01 00:00:00 +0000\n"
+            "@@ -1,121 +0,0 @@\n\n")
+        << QByteArray("src/plugins/bazaar/bazaareditor.cpp");
+    QTest::newRow("Modified") << QByteArray(
+            "=== modified file 'src/plugins/bazaar/bazaareditor.cpp'\n"
+            "--- src/plugins/bazaar/bazaareditor.cpp\t2010-08-27 14:12:44 +0000\n"
+            "+++ src/plugins/bazaar/bazaareditor.cpp\t2011-02-28 21:24:19 +0000\n"
+            "@@ -727,6 +727,9 @@\n\n")
+        << QByteArray("src/plugins/bazaar/bazaareditor.cpp");
+}
+
+void BazaarPlugin::testDiffFileResolving()
+{
+    BazaarEditor editor(editorParameters + 3, 0);
+    VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
+}
+#endif
+
 void BazaarPlugin::commitFromEditor()
 {
     // Close the submit editor
diff --git a/src/plugins/bazaar/bazaarplugin.h b/src/plugins/bazaar/bazaarplugin.h
index ff6b6fbbd7652162cada0542a2fb8727f2ae9aa0..b483e2ef140bc8470a66e59887e0ad29538a7a9f 100644
--- a/src/plugins/bazaar/bazaarplugin.h
+++ b/src/plugins/bazaar/bazaarplugin.h
@@ -112,6 +112,10 @@ private slots:
     void showCommitWidget(const QList<VcsBase::VcsBaseClient::StatusItem> &status);
     void commitFromEditor();
     void diffFromEditorSelected(const QStringList &files);
+#ifdef WITH_TESTS
+    void testDiffFileResolving_data();
+    void testDiffFileResolving();
+#endif
 
 protected:
     void updateActions(VcsBase::VcsBasePlugin::ActionState);
diff --git a/src/plugins/clearcase/clearcaseeditor.cpp b/src/plugins/clearcase/clearcaseeditor.cpp
index c00a973b428c194ccca4f576177805d0588fa927..63d7964ecedd78e96f68d53e8c397a4fc143707d 100644
--- a/src/plugins/clearcase/clearcaseeditor.cpp
+++ b/src/plugins/clearcase/clearcaseeditor.cpp
@@ -51,6 +51,12 @@ ClearCaseEditor::ClearCaseEditor(const VcsBase::VcsBaseEditorParameters *type,
     m_versionNumberPattern(QLatin1String("[\\\\/]main[\\\\/][^ \t\n\"]*"))
 {
     QTC_ASSERT(m_versionNumberPattern.isValid(), return);
+    // Diff formats:
+    // "+++ D:\depot\...\mainwindow.cpp@@\main\3" (versioned)
+    // "+++ D:\depot\...\mainwindow.cpp[TAB]Sun May 01 14:22:37 2011" (local)
+    QRegExp diffFilePattern(QLatin1String("^[-+]{3} ([^\\t]+)(?:@@|\\t)"));
+    diffFilePattern.setMinimal(true);
+    setDiffFilePattern(diffFilePattern);
     setAnnotateRevisionTextFormat(tr("Annotate version \"%1\""));
 }
 
@@ -87,41 +93,8 @@ QString ClearCaseEditor::changeUnderCursor(const QTextCursor &c) const
     return QString();
 }
 
-/*
- Diff header format (on Windows, native separators are used after the @@)
---- main.cpp@@\main\2
-+++ main.cpp@@\main\1
-@@ -6,6 +6,5 @@
-*/
-QRegExp ClearCaseEditor::diffFilePattern() const
-{
-    return QRegExp(QLatin1String("^[-+][-+][-+] "));
-}
-
 VcsBase::BaseAnnotationHighlighter *ClearCaseEditor::createAnnotationHighlighter(const QSet<QString> &changes,
                                                                                  const QColor &bg) const
 {
     return new ClearCaseAnnotationHighlighter(changes, bg);
 }
-
-QString ClearCaseEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
-{
-    // "+++ D:\depot\...\mainwindow.cpp@@\main\3"
-    // "+++ D:\depot\...\mainwindow.cpp[TAB]Sun May 01 14:22:37 2011"
-    // Go back chunks
-    const QString diffIndicator = QLatin1String("+++ ");
-    for (QTextBlock  block = inBlock; block.isValid() ; block = block.previous()) {
-        QString diffFileName = block.text();
-        if (diffFileName.startsWith(diffIndicator)) {
-            diffFileName.remove(0, diffIndicator.size());
-            const int tabIndex = diffFileName.indexOf(QRegExp(QLatin1String("@@|\t")));
-            if (tabIndex != -1)
-                diffFileName.truncate(tabIndex);
-            const QString rc = findDiffFile(diffFileName);
-            if (ClearCase::Constants::debug)
-                qDebug() << Q_FUNC_INFO << diffFileName << rc << source();
-            return rc;
-        }
-    }
-    return QString();
-}
diff --git a/src/plugins/clearcase/clearcaseeditor.h b/src/plugins/clearcase/clearcaseeditor.h
index afb795536660f9908fc9c5b0f67c37d6674e794b..18577d95466f4fa711cd4beea460245d865833e7 100644
--- a/src/plugins/clearcase/clearcaseeditor.h
+++ b/src/plugins/clearcase/clearcaseeditor.h
@@ -49,11 +49,9 @@ public:
 private:
     QSet<QString> annotationChanges() const;
     QString changeUnderCursor(const QTextCursor &) const;
-    QRegExp diffFilePattern() const;
     VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
-    QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
 
-    mutable QRegExp m_versionNumberPattern;
+    QRegExp m_versionNumberPattern;
 };
 
 } // namespace Internal
diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index 048d50a2347ffe47067b09ac0b822278033b4521..215a0741e21f57fc079a7150c52de942dfacc0d7 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -96,7 +96,9 @@
 #include <QVariant>
 #include <QVBoxLayout>
 #include <QXmlStreamReader>
-
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
 
 namespace ClearCase {
 namespace Internal {
@@ -1943,6 +1945,26 @@ void ClearCasePlugin::sync(QFutureInterface<void> &future, QString topLevel, QSt
     ccSync.run(future, topLevel, files);
 }
 
+#ifdef WITH_TESTS
+void ClearCasePlugin::testDiffFileResolving_data()
+{
+    QTest::addColumn<QByteArray>("header");
+    QTest::addColumn<QByteArray>("fileName");
+
+    QTest::newRow("Modified") << QByteArray(
+            "--- src/plugins/clearcase/clearcaseeditor.cpp@@/main/1\t2013-01-20 23:45:48.549615210 +0200\n"
+            "+++ src/plugins/clearcase/clearcaseeditor.cpp@@/main/2\t2013-01-20 23:45:53.217604679 +0200\n"
+            "@@ -58,6 +58,10 @@\n\n")
+        << QByteArray("src/plugins/clearcase/clearcaseeditor.cpp");
+}
+
+void ClearCasePlugin::testDiffFileResolving()
+{
+    ClearCaseEditor editor(editorParameters + 3, 0);
+    VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
+}
+#endif
+
 } // namespace Internal
 } // namespace ClearCase
 
diff --git a/src/plugins/clearcase/clearcaseplugin.h b/src/plugins/clearcase/clearcaseplugin.h
index 7f8a5e32525949743d70e0d9b41f2a391a8a90b6..8b8f976eb51b25658dffe8dbeabcebb06df1b1ff 100644
--- a/src/plugins/clearcase/clearcaseplugin.h
+++ b/src/plugins/clearcase/clearcaseplugin.h
@@ -192,6 +192,10 @@ private slots:
     void syncSlot();
     void closing();
     void updateStatusActions();
+#ifdef WITH_TESTS
+    void testDiffFileResolving_data();
+    void testDiffFileResolving();
+#endif
 
 protected:
     void updateActions(VcsBase::VcsBasePlugin::ActionState);
diff --git a/src/plugins/cvs/cvseditor.cpp b/src/plugins/cvs/cvseditor.cpp
index f2624fb15f2cd49d7cab307671c891ee0c5b20e9..a2de1f235ae1821d0cfb8ca3e94dd0a0ccc56eed 100644
--- a/src/plugins/cvs/cvseditor.cpp
+++ b/src/plugins/cvs/cvseditor.cpp
@@ -55,6 +55,15 @@ CvsEditor::CvsEditor(const VcsBase::VcsBaseEditorParameters *type,
 {
     QTC_ASSERT(m_revisionAnnotationPattern.isValid(), return);
     QTC_ASSERT(m_revisionLogPattern.isValid(), return);
+    /* Diff format:
+    \code
+    cvs diff -d -u -r1.1 -r1.2:
+    --- mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000<tab>1.1
+    +++ mainwindow.cpp<\t>14 Jul 2009 07:09:24 -0000<tab>1.2
+    @@ -6,6 +6,5 @@
+    \endcode
+    */
+    setDiffFilePattern(QRegExp(QLatin1String("^[-+]{3} ([^\\t]+)")));
     setAnnotateRevisionTextFormat(tr("Annotate revision \"%1\""));
 }
 
@@ -113,42 +122,12 @@ QString CvsEditor::changeUnderCursor(const QTextCursor &c) const
     return QString();
 }
 
-/* \code
-cvs diff -d -u -r1.1 -r1.2:
---- mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000 <\t>1.1
-+++ mainwindow.cpp<\t>14 Jul 2009 07:09:24 -0000<\t>1.2
-@@ -6,6 +6,5 @@
-\endcode
-*/
-QRegExp CvsEditor::diffFilePattern() const
-{
-    return QRegExp(QLatin1String("^[-+][-+][-+] .*1\\.[\\d\\.]+$"));
-}
-
 VcsBase::BaseAnnotationHighlighter *CvsEditor::createAnnotationHighlighter(const QSet<QString> &changes,
                                                                            const QColor &bg) const
 {
     return new CvsAnnotationHighlighter(changes, bg);
 }
 
-QString CvsEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
-{
-    // "+++ mainwindow.cpp<\t>13 Jul 2009 13:50:15 -0000      1.1"
-    // Go back chunks
-    const QString diffIndicator = QLatin1String("+++ ");
-    for (QTextBlock  block = inBlock; block.isValid() ; block = block.previous()) {
-        QString diffFileName = block.text();
-        if (diffFileName.startsWith(diffIndicator)) {
-            diffFileName.remove(0, diffIndicator.size());
-            const int tabIndex = diffFileName.indexOf(QLatin1Char('\t'));
-            if (tabIndex != -1)
-                diffFileName.truncate(tabIndex);
-            return findDiffFile(diffFileName);
-        }
-    }
-    return QString();
-}
-
 QStringList CvsEditor::annotationPreviousVersions(const QString &revision) const
 {
     if (isFirstRevision(revision))
diff --git a/src/plugins/cvs/cvseditor.h b/src/plugins/cvs/cvseditor.h
index 5e4a2fda980a99fcacb690441bf5a3962dd02b1f..d9e63275235cfc4c9af9aa8618841f6c2fec293d 100644
--- a/src/plugins/cvs/cvseditor.h
+++ b/src/plugins/cvs/cvseditor.h
@@ -48,9 +48,7 @@ public:
 private:
     QSet<QString> annotationChanges() const;
     QString changeUnderCursor(const QTextCursor &) const;
-    QRegExp diffFilePattern() const;
     VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
-    QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
     QStringList annotationPreviousVersions(const QString &revision) const;
 
     mutable QRegExp m_revisionAnnotationPattern;
diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp
index 40997ffcd6c7cd50f110a4fb79e8793e53d0c547..69e0b52cb139087e74eb0cba273b97c35d768ad0 100644
--- a/src/plugins/git/giteditor.cpp
+++ b/src/plugins/git/giteditor.cpp
@@ -66,6 +66,13 @@ GitEditor::GitEditor(const VcsBase::VcsBaseEditorParameters *type,
 {
     QTC_ASSERT(m_changeNumberPattern8.isValid(), return);
     QTC_ASSERT(m_changeNumberPattern40.isValid(), return);
+    /* Diff format:
+        diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp
+        index 40997ff..4e49337 100644
+        --- a/src/plugins/git/giteditor.cpp
+        +++ b/src/plugins/git/giteditor.cpp
+    */
+    setDiffFilePattern(QRegExp(QLatin1String("^(?:diff --git a/|index |[+-]{3} (?:/dev/null|[ab]/(.+$)))")));
     setAnnotateRevisionTextFormat(tr("Blame %1"));
     setAnnotatePreviousRevisionTextFormat(tr("Blame Parent Revision %1"));
 }
@@ -107,46 +114,12 @@ QString GitEditor::changeUnderCursor(const QTextCursor &c) const
     return QString();
 }
 
-QRegExp GitEditor::diffFilePattern() const
-{
-    return QRegExp(QLatin1String("^(diff --git a/|index |[+-][+-][+-] [ab/]).*$"));
-}
-
 VcsBase::BaseAnnotationHighlighter *GitEditor::createAnnotationHighlighter(const QSet<QString> &changes,
                                                                            const QColor &bg) const
 {
     return new GitAnnotationHighlighter(changes, bg);
 }
 
-QString GitEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
-{
-    // Check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff)
-    // as well as "--- a/src/plugins/git/giteditor.cpp".
-    // Go back chunks.
-    bool checkForOld = false;
-
-    const QString oldFileIndicator = QLatin1String("--- a/");
-    const QString newFileIndicator = QLatin1String("+++ ");
-    for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
-        QString diffFileName = block.text();
-        if (diffFileName.startsWith(oldFileIndicator) && checkForOld) {
-            diffFileName.remove(0, oldFileIndicator.size());
-            checkForOld = false;
-            return diffFileName;
-        } else if (diffFileName.startsWith(newFileIndicator)) {
-            diffFileName.remove(0, newFileIndicator.size());
-            if (diffFileName == QLatin1String("/dev/null")) {
-                checkForOld = true;
-                continue;
-            }
-            diffFileName.remove(0, 2); // remove "b/"
-            return findDiffFile(diffFileName);
-        }
-        checkForOld = false;
-    }
-    return QString();
-}
-
 /* Remove the date specification from annotation, which is tabular:
 \code
 8ca887aa (author               YYYY-MM-DD HH:MM:SS <offset>  <line>)<content>
diff --git a/src/plugins/git/giteditor.h b/src/plugins/git/giteditor.h
index 5fc066c4cc72a5e002099767eb88512e8a086e4b..6b55f0b3ef0e036e8546ca878b84ee8696c55a86 100644
--- a/src/plugins/git/giteditor.h
+++ b/src/plugins/git/giteditor.h
@@ -57,9 +57,7 @@ public slots:
 private:
     QSet<QString> annotationChanges() const;
     QString changeUnderCursor(const QTextCursor &) const;
-    QRegExp diffFilePattern() const;
     VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
-    QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
     QString decorateVersion(const QString &revision) const;
     QStringList annotationPreviousVersions(const QString &revision) const;
     bool isValidRevision(const QString &revision) const;
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 8951ffe088583761eacb724ab06901ab45d8cd5f..ea91635342418124f835ec1a11cfe6f69d6530aa 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -1253,8 +1253,14 @@ GitClient *GitPlugin::gitClient() const
 }
 
 #ifdef WITH_TESTS
+#include "giteditor.h"
+
 #include <QTest>
+#include <QTextBlock>
+#include <QTextDocument>
+
 Q_DECLARE_METATYPE(FileStates)
+
 void GitPlugin::testStatusParsing_data()
 {
     QTest::addColumn<FileStates>("first");
@@ -1301,6 +1307,42 @@ void GitPlugin::testStatusParsing()
     else
         QCOMPARE(data.files.at(1).first, second);
 }
+
+void GitPlugin::testDiffFileResolving_data()
+{
+    QTest::addColumn<QByteArray>("header");
+    QTest::addColumn<QByteArray>("fileName");
+
+    QTest::newRow("New") << QByteArray(
+            "diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp\n"
+            "new file mode 100644\n"
+            "index 0000000..40997ff\n"
+            "--- /dev/null\n"
+            "+++ b/src/plugins/git/giteditor.cpp\n"
+            "@@ -0,0 +1,281 @@\n\n")
+        << QByteArray("src/plugins/git/giteditor.cpp");
+    QTest::newRow("Deleted") << QByteArray(
+            "diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp\n"
+            "deleted file mode 100644\n"
+            "index 40997ff..0000000\n"
+            "--- a/src/plugins/git/giteditor.cpp\n"
+            "+++ /dev/null\n"
+            "@@ -1,281 +0,0 @@\n\n")
+        << QByteArray("src/plugins/git/giteditor.cpp");
+    QTest::newRow("Normal") << QByteArray(
+            "diff --git a/src/plugins/git/giteditor.cpp b/src/plugins/git/giteditor.cpp\n"
+            "index 69e0b52..8fc974d 100644\n"
+            "--- a/src/plugins/git/giteditor.cpp\n"
+            "+++ b/src/plugins/git/giteditor.cpp\n"
+            "@@ -49,6 +49,8 @@\n\n")
+        << QByteArray("src/plugins/git/giteditor.cpp");
+}
+
+void GitPlugin::testDiffFileResolving()
+{
+    GitEditor editor(editorParameters + 3, 0);
+    VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
+}
 #endif
 
 Q_EXPORT_PLUGIN(GitPlugin)
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index a02d428df1c34d113aeb61448e3d433bb6327461..8e9dd0a636d01e5e44e9eb89fcd835af083e67a2 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -144,6 +144,8 @@ private slots:
 #ifdef WITH_TESTS
     void testStatusParsing_data();
     void testStatusParsing();
+    void testDiffFileResolving_data();
+    void testDiffFileResolving();
 #endif
 protected:
     void updateActions(VcsBase::VcsBasePlugin::ActionState);
diff --git a/src/plugins/mercurial/constants.h b/src/plugins/mercurial/constants.h
index c9798c63d48f3e9fa385a8bda977ad623a181e1d..b5b1daa6b2a24eb97da97de468e2e883748e2fcb 100644
--- a/src/plugins/mercurial/constants.h
+++ b/src/plugins/mercurial/constants.h
@@ -42,7 +42,7 @@ const char CHANGESETID12[] = " ([a-f0-9]{12,12}) "; //match 12 hex chars and cap
 const char CHANGESETID40[] = " ([a-f0-9]{40,40}) ";
 const char CHANGEIDEXACT12[] = "[a-f0-9]{12,12}"; //match 12 hex chars a
 const char CHANGEIDEXACT40[] = "[a-f0-9]{40,40}";
-const char DIFFIDENTIFIER[] = "^[-+]{3,3} [ab]{1,1}.*"; // match e.g. +++ b/filename
+const char DIFFIDENTIFIER[] = "^[-+]{3} [ab]/(.+)$"; // match e.g. +++ b/filename
 
 // Base editor parameters
 const char COMMANDLOG_ID[] = "Mercurial Command Log Editor";
diff --git a/src/plugins/mercurial/mercurialeditor.cpp b/src/plugins/mercurial/mercurialeditor.cpp
index 4e775e6a935d184b00504085c4c0a53c75e6ae1d..4eafe92b72b52532fd53162848cc6d2409a13e97 100644
--- a/src/plugins/mercurial/mercurialeditor.cpp
+++ b/src/plugins/mercurial/mercurialeditor.cpp
@@ -51,9 +51,9 @@ MercurialEditor::MercurialEditor(const VcsBase::VcsBaseEditorParameters *type, Q
         exactIdentifier12(QLatin1String(Constants::CHANGEIDEXACT12)),
         exactIdentifier40(QLatin1String(Constants::CHANGEIDEXACT40)),
         changesetIdentifier12(QLatin1String(Constants::CHANGESETID12)),
-        changesetIdentifier40(QLatin1String(Constants::CHANGESETID40)),
-        diffIdentifier(QLatin1String(Constants::DIFFIDENTIFIER))
+        changesetIdentifier40(QLatin1String(Constants::CHANGESETID40))
 {
+    setDiffFilePattern(QRegExp(QLatin1String(Constants::DIFFIDENTIFIER)));
     setAnnotateRevisionTextFormat(tr("Annotate %1"));
     setAnnotatePreviousRevisionTextFormat(tr("Annotate parent revision %1"));
 }
@@ -88,33 +88,12 @@ QString MercurialEditor::changeUnderCursor(const QTextCursor &cursorIn) const
     return QString();
 }
 
-QRegExp MercurialEditor::diffFilePattern() const
-{
-    return diffIdentifier;
-}
-
 VcsBase::BaseAnnotationHighlighter *MercurialEditor::createAnnotationHighlighter(const QSet<QString> &changes,
                                                                                  const QColor &bg) const
 {
     return new MercurialAnnotationHighlighter(changes, bg);
 }
 
-QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
-{
-    // git-compatible format: check for "+++ b/src/plugins/git/giteditor.cpp" (blame and diff)
-    // Go back chunks.
-    const QString newFileIndicator = QLatin1String("+++ b/");
-    for (QTextBlock  block = inBlock; block.isValid(); block = block.previous()) {
-        QString diffFileName = block.text();
-        if (diffFileName.startsWith(newFileIndicator)) {
-            diffFileName.remove(0, newFileIndicator.size());
-            return findDiffFile(diffFileName);
-        }
-
-    }
-    return QString();
-}
-
 QString MercurialEditor::decorateVersion(const QString &revision) const
 {
     const QFileInfo fi(source());
diff --git a/src/plugins/mercurial/mercurialeditor.h b/src/plugins/mercurial/mercurialeditor.h
index da0d48789b4e6f6c7069e89a58941f9847dd28f7..28a1b38bb51f7bbf2b67308c2eee85608a0e7b6c 100644
--- a/src/plugins/mercurial/mercurialeditor.h
+++ b/src/plugins/mercurial/mercurialeditor.h
@@ -46,9 +46,7 @@ public:
 private:
     QSet<QString> annotationChanges() const;
     QString changeUnderCursor(const QTextCursor &cursor) const;
-    QRegExp diffFilePattern() const;
     VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
-    QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const;
     QString decorateVersion(const QString &revision) const;
     QStringList annotationPreviousVersions(const QString &revision) const;
 
@@ -56,7 +54,6 @@ private:
     mutable QRegExp exactIdentifier40;
     mutable QRegExp changesetIdentifier12;
     const QRegExp changesetIdentifier40;
-    const QRegExp diffIdentifier;
 };
 
 } // namespace Internal
diff --git a/src/plugins/perforce/perforceeditor.cpp b/src/plugins/perforce/perforceeditor.cpp
index aa925a86ec4c35b79b563e2368bcd4472c0a3cbd..c97da58e61f2c4e1b9e8df525c095d8d351b3f72 100644
--- a/src/plugins/perforce/perforceeditor.cpp
+++ b/src/plugins/perforce/perforceeditor.cpp
@@ -63,6 +63,10 @@ PerforceEditor::PerforceEditor(const VcsBase::VcsBaseEditorParameters *type,
     m_plugin(PerforcePlugin::perforcePluginInstance())
 {
     QTC_CHECK(m_changeNumberPattern.isValid());
+    // Diff format:
+    // 1) "==== //depot/.../mainwindow.cpp#2 - /depot/.../mainwindow.cpp ====" (created by p4 diff)
+    // 2) "==== //depot/.../mainwindow.cpp#15 (text) ====" (created by p4 describe)
+    setDiffFilePattern(QRegExp(QLatin1String("^==== (.+)#\\d")));
     setAnnotateRevisionTextFormat(tr("Annotate change list \"%1\""));
     if (Perforce::Constants::debug)
         qDebug() << "PerforceEditor::PerforceEditor" << type->type << type->id;
@@ -103,57 +107,19 @@ QString PerforceEditor::changeUnderCursor(const QTextCursor &c) const
     return m_changeNumberPattern.exactMatch(change) ? change : QString();
 }
 
-QRegExp PerforceEditor::diffFilePattern() const
-{
-    return QRegExp(QLatin1String("^====.*"));
-}
-
 VcsBase::BaseAnnotationHighlighter *PerforceEditor::createAnnotationHighlighter(const QSet<QString> &changes,
                                                                                 const QColor &bg) const
 {
     return new PerforceAnnotationHighlighter(changes, bg);
 }
 
-QString PerforceEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
+QString PerforceEditor::findDiffFile(const QString &f) const
 {
     QString errorMessage;
-    const QString diffIndicator = QLatin1String("==== ");
-    const QString diffEndIndicator = QLatin1String(" ====");
-    // Go back chunks. Note that for 'describe', an extra, empty line
-    // occurs.
-    for (QTextBlock  block = inBlock; block.isValid(); block = block.previous()) {
-        QString diffFileName = block.text();
-        if (diffFileName.startsWith(diffIndicator) && diffFileName.endsWith(diffEndIndicator)) {
-            // Split:
-            // 1) "==== //depot/.../mainwindow.cpp#2 - /depot/.../mainwindow.cpp ===="
-            // (as created by p4 diff) or
-            // 2) "==== //depot/.../mainwindow.cpp#15 (text) ===="
-            // (as created by p4 describe).
-            diffFileName.remove(0, diffIndicator.size());
-            diffFileName.truncate(diffFileName.size() - diffEndIndicator.size());
-            const int separatorPos = diffFileName.indexOf(QLatin1String(" - "));
-            if (separatorPos == -1) {
-                // ==== depot path (text) ==== (p4 describe)
-                const int blankPos = diffFileName.indexOf(QLatin1Char(' '));
-                if (blankPos == -1)
-                    return QString();
-                diffFileName.truncate(blankPos);
-            } else {
-                // ==== depot path - local path ==== (p4 diff)
-                diffFileName.truncate(separatorPos);
-            }
-            // Split off revision "#4"
-            const int revisionPos = diffFileName.lastIndexOf(QLatin1Char('#'));
-            if (revisionPos != -1 && revisionPos < diffFileName.length() - 1)
-                diffFileName.truncate(revisionPos);
-            // Ask plugin to map back
-            const QString fileName = m_plugin->fileNameFromPerforceName(diffFileName.trimmed(), false, &errorMessage);
-            if (fileName.isEmpty())
-                qWarning("%s", qPrintable(errorMessage));
-            return fileName;
-        }
-    }
-    return QString();
+    const QString fileName = m_plugin->fileNameFromPerforceName(f.trimmed(), false, &errorMessage);
+    if (fileName.isEmpty())
+        qWarning("%s", qPrintable(errorMessage));
+    return fileName;
 }
 
 QStringList PerforceEditor::annotationPreviousVersions(const QString &v) const
diff --git a/src/plugins/perforce/perforceeditor.h b/src/plugins/perforce/perforceeditor.h
index 3a8791eb5221ea50c22603d061ab9f1722d381aa..1edf5eba3e3f65ad5772e2d68ca071e16abf8904 100644
--- a/src/plugins/perforce/perforceeditor.h
+++ b/src/plugins/perforce/perforceeditor.h
@@ -50,9 +50,8 @@ public:
 private:
     QSet<QString> annotationChanges() const;
     QString changeUnderCursor(const QTextCursor &) const;
-    QRegExp diffFilePattern() const;
     VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
-    QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
+    QString findDiffFile(const QString &f) const;
     QStringList annotationPreviousVersions(const QString &v) const;
 
     mutable QRegExp m_changeNumberPattern;
diff --git a/src/plugins/subversion/subversioneditor.cpp b/src/plugins/subversion/subversioneditor.cpp
index 7a7b44424bfa226af786445eeb24e0126cd22094..cb8141a3467a4bdd711b09ace7354e5795255605 100644
--- a/src/plugins/subversion/subversioneditor.cpp
+++ b/src/plugins/subversion/subversioneditor.cpp
@@ -52,6 +52,16 @@ SubversionEditor::SubversionEditor(const VcsBase::VcsBaseEditorParameters *type,
 {
     QTC_ASSERT(m_changeNumberPattern.isValid(), return);
     QTC_ASSERT(m_revisionNumberPattern.isValid(), return);
+    /* Diff pattern:
+    \code
+        Index: main.cpp
+    ===================================================================
+    --- main.cpp<tab>(revision 2)
+    +++ main.cpp<tab>(working copy)
+    @@ -6,6 +6,5 @@
+    \endcode
+    */
+    setDiffFilePattern(QRegExp(QLatin1String("^[-+]{3} ([^\\t]+)|^Index: .*|^=+$")));
     setAnnotateRevisionTextFormat(tr("Annotate revision \"%1\""));
 }
 
@@ -98,46 +108,12 @@ QString SubversionEditor::changeUnderCursor(const QTextCursor &c) const
     return QString();
 }
 
-/* code:
-    Index: main.cpp
-===================================================================
---- main.cpp    (revision 2)
-+++ main.cpp    (working copy)
-@@ -6,6 +6,5 @@
-\endcode
-*/
-QRegExp SubversionEditor::diffFilePattern() const
-{
-    return QRegExp(QLatin1String("^[-+][-+][-+] .*|^Index: .*|^==*$"));
-}
-
 VcsBase::BaseAnnotationHighlighter *SubversionEditor::createAnnotationHighlighter(const QSet<QString> &changes,
                                                                                   const QColor &bg) const
 {
     return new SubversionAnnotationHighlighter(changes, bg);
 }
 
-QString SubversionEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
-{
-    // "+++ /depot/.../mainwindow.cpp<tab>(revision 3)"
-    // Go back chunks
-    const QString diffIndicator = QLatin1String("+++ ");
-    for (QTextBlock  block = inBlock; block.isValid() ; block = block.previous()) {
-        QString diffFileName = block.text();
-        if (diffFileName.startsWith(diffIndicator)) {
-            diffFileName.remove(0, diffIndicator.size());
-            const int tabIndex = diffFileName.lastIndexOf(QLatin1Char('\t'));
-            if (tabIndex != -1)
-                diffFileName.truncate(tabIndex);
-            const QString rc = findDiffFile(diffFileName);
-            if (Subversion::Constants::debug)
-                qDebug() << Q_FUNC_INFO << diffFileName << rc << source();
-            return rc;
-        }
-    }
-    return QString();
-}
-
 QStringList SubversionEditor::annotationPreviousVersions(const QString &v) const
 {
     bool ok;
diff --git a/src/plugins/subversion/subversioneditor.h b/src/plugins/subversion/subversioneditor.h
index f2ec7843677e720c292ce2a0c0d5f04751d0c22a..9d64b061fd51bac1a689d1643d7494e4cff6f1b6 100644
--- a/src/plugins/subversion/subversioneditor.h
+++ b/src/plugins/subversion/subversioneditor.h
@@ -48,9 +48,7 @@ public:
 private:
     QSet<QString> annotationChanges() const;
     QString changeUnderCursor(const QTextCursor &) const;
-    QRegExp diffFilePattern() const;
     VcsBase::BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes, const QColor &bg) const;
-    QString fileNameFromDiffSpecification(const QTextBlock &diffFileName) const;
     QStringList annotationPreviousVersions(const QString &) const;
 
     mutable QRegExp m_changeNumberPattern;
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index 5bb6533c58ad00668d308513687c042f6e9c304a..9b663950ad438f4c68756f822463b532c9587536 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -77,6 +77,10 @@
 #include <QInputDialog>
 #include <limits.h>
 
+#ifdef WITH_TESTS
+#include <QTest>
+#endif
+
 namespace Subversion {
 namespace Internal {
 
@@ -1389,6 +1393,42 @@ SubversionControl *SubversionPlugin::subVersionControl() const
     return static_cast<SubversionControl *>(versionControl());
 }
 
+#ifdef WITH_TESTS
+void SubversionPlugin::testDiffFileResolving_data()
+{
+    QTest::addColumn<QByteArray>("header");
+    QTest::addColumn<QByteArray>("fileName");
+
+    QTest::newRow("New") << QByteArray(
+            "Index: src/plugins/subversion/subversioneditor.cpp\n"
+            "===================================================================\n"
+            "--- src/plugins/subversion/subversioneditor.cpp\t(revision 0)\n"
+            "+++ src/plugins/subversion/subversioneditor.cpp\t(revision 0)\n"
+            "@@ -0,0 +125 @@\n\n")
+        << QByteArray("src/plugins/subversion/subversioneditor.cpp");
+    QTest::newRow("Deleted") << QByteArray(
+            "Index: src/plugins/subversion/subversioneditor.cpp\n"
+            "===================================================================\n"
+            "--- src/plugins/subversion/subversioneditor.cpp\t(revision 42)\n"
+            "+++ src/plugins/subversion/subversioneditor.cpp\t(working copy)\n"
+            "@@ -1,125 +0,0 @@\n\n")
+        << QByteArray("src/plugins/subversion/subversioneditor.cpp");
+    QTest::newRow("Normal") << QByteArray(
+            "Index: src/plugins/subversion/subversioneditor.cpp\n"
+            "===================================================================\n"
+            "--- src/plugins/subversion/subversioneditor.cpp\t(revision 42)\n"
+            "+++ src/plugins/subversion/subversioneditor.cpp\t(working copy)\n"
+            "@@ -120,7 +120,7 @@\n\n")
+        << QByteArray("src/plugins/subversion/subversioneditor.cpp");
+}
+
+void SubversionPlugin::testDiffFileResolving()
+{
+    SubversionEditor editor(editorParameters + 3, 0);
+    VcsBase::VcsBaseEditorWidget::testDiffFileResolving(&editor);
+}
+#endif
+
 } // Internal
 } // Subversion
 
diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h
index b3760d1e4c8a2e03bce1a22c47793d23afdb9a8d..c82851de013fece1186177684e5aa2544b832a4b 100644
--- a/src/plugins/subversion/subversionplugin.h
+++ b/src/plugins/subversion/subversionplugin.h
@@ -136,6 +136,10 @@ private slots:
     void diffRepository();
     void statusRepository();
     void updateRepository();
+#ifdef WITH_TESTS
+    void testDiffFileResolving_data();
+    void testDiffFileResolving();
+#endif
 
 protected:
     void updateActions(VcsBase::VcsBasePlugin::ActionState);
diff --git a/src/plugins/vcsbase/diffhighlighter.cpp b/src/plugins/vcsbase/diffhighlighter.cpp
index 278b32a1388b6052add1cda51e83c10d1b734c73..463449e0dcdd9497b9a85981e1b15aad5e042803 100644
--- a/src/plugins/vcsbase/diffhighlighter.cpp
+++ b/src/plugins/vcsbase/diffhighlighter.cpp
@@ -116,7 +116,7 @@ DiffFormats DiffHighlighterPrivate::analyzeLine(const QString &text) const
 {
     // Do not match on git "--- a/" as a deleted line, check
     // file first
-    if (m_filePattern.exactMatch(text))
+    if (m_filePattern.indexIn(text) == 0)
         return DiffFileFormat;
     if (text.startsWith(m_diffInIndicator))
         return DiffInFormat;
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index 1a25ad7a438799110774600e0db5260a372a963d..2999b7c939dbca6325be8493fe7bdc6739ee1399 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -668,17 +668,23 @@ VcsBaseEditorWidget::VcsBaseEditorWidget(const VcsBaseEditorParameters *type, QW
     setMimeType(QLatin1String(d->m_parameters->mimeType));
 }
 
+void VcsBaseEditorWidget::setDiffFilePattern(const QRegExp &pattern)
+{
+    QTC_ASSERT(pattern.isValid() && pattern.captureCount() >= 1, return);
+    d->m_diffFilePattern = pattern;
+}
+
 void VcsBaseEditorWidget::init()
 {
     switch (d->m_parameters->type) {
     case RegularCommandOutput:
     case LogOutput:
+        break;
     case AnnotateOutput:
         // Annotation highlighting depends on contents, which is set later on
         connect(this, SIGNAL(textChanged()), this, SLOT(slotActivateAnnotation()));
         break;
     case DiffOutput: {
-        d->m_diffFilePattern = diffFilePattern();
         DiffHighlighter *dh = new DiffHighlighter(d->m_diffFilePattern);
         setCodeFoldingSupported(true);
         baseTextDocument()->setSyntaxHighlighter(dh);
@@ -1429,6 +1435,20 @@ bool VcsBaseEditorWidget::applyDiffChunk(const DiffChunk &dc, bool revert) const
     return VcsBasePlugin::runPatch(dc.asPatch(), QString(), 0, revert);
 }
 
+QString VcsBaseEditorWidget::fileNameFromDiffSpecification(const QTextBlock &inBlock) const
+{
+    // Go back chunks
+    for (QTextBlock block = inBlock; block.isValid(); block = block.previous()) {
+        const QString line = block.text();
+        if (d->m_diffFilePattern.indexIn(line) != -1) {
+            QString cap = d->m_diffFilePattern.cap(1);
+            if (!cap.isEmpty())
+                return findDiffFile(cap);
+        }
+    }
+    return QString();
+}
+
 QString VcsBaseEditorWidget::decorateVersion(const QString &revision) const
 {
     return revision;
@@ -1502,4 +1522,18 @@ Core::IEditor* VcsBaseEditorWidget::locateEditorByTag(const QString &tag)
 
 } // namespace VcsBase
 
+#if WITH_TESTS
+#include <QTest>
+
+void VcsBase::VcsBaseEditorWidget::testDiffFileResolving(VcsBaseEditorWidget *editor)
+{
+    QFETCH(QByteArray, header);
+    QFETCH(QByteArray, fileName);
+    QTextDocument doc(QString::fromLatin1(header));
+    editor->init();
+    QTextBlock block = doc.lastBlock();
+    QVERIFY(editor->fileNameFromDiffSpecification(block).endsWith(QString::fromLatin1(fileName)));
+}
+#endif
+
 #include "vcsbaseeditor.moc"
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index 88b61834ff74cbea9932316ffffa9d155ee3fb3f..9cd0cbb1c2500c36ae797134a765321745a4bf84 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -38,6 +38,7 @@
 
 QT_BEGIN_NAMESPACE
 class QAction;
+class QRegExp;
 class QTextCodec;
 class QTextCursor;
 QT_END_NAMESPACE
@@ -99,6 +100,9 @@ protected:
     // virtual functions).
     explicit VcsBaseEditorWidget(const VcsBaseEditorParameters *type,
                                  QWidget *parent);
+    // Pattern for diff header. File name must be in the first capture group
+    void setDiffFilePattern(const QRegExp &pattern);
+
 public:
     void init();
 
@@ -180,6 +184,10 @@ public:
     bool setConfigurationWidget(QWidget *w);
     QWidget *configurationWidget() const;
 
+    // Returns a local file name from the diff file specification
+    // (text cursor at position above change hunk)
+    QString fileNameFromDiffSpecification(const QTextBlock &inBlock) const;
+
     /* Tagging editors: Sometimes, an editor should be re-used, for example, when showing
      * a diff of the same file with different diff-options. In order to be able to find
      * the editor, they get a 'tag' containing type and parameters (dynamic property string). */
@@ -187,7 +195,6 @@ public:
     static Core::IEditor* locateEditorByTag(const QString &tag);
     static QString editorTag(EditorContentType t, const QString &workingDirectory, const QStringList &files,
                              const QString &revision = QString());
-
 signals:
     // These signals also exist in the opaque editable (IEditor) that is
     // handled by the editor manager for convenience. They are emitted
@@ -227,25 +234,20 @@ protected:
     /* A helper that can be used to locate a file in a diff in case it
      * is relative. Tries to derive the directory from base directory,
      * source and version control. */
-    QString findDiffFile(const QString &f) const;
+    virtual QString findDiffFile(const QString &f) const;
 
     virtual bool canApplyDiffChunk(const DiffChunk &dc) const;
     // Revert a patch chunk. Default implementation uses patch.exe
     virtual bool applyDiffChunk(const DiffChunk &dc, bool revert = false) const;
 
-private:
     // Implement to return a set of change identifiers in
     // annotation mode
     virtual QSet<QString> annotationChanges() const = 0;
     // Implement to identify a change number at the cursor position
     virtual QString changeUnderCursor(const QTextCursor &) const = 0;
     // Factory functions for highlighters
-    virtual QRegExp diffFilePattern() const = 0;
     virtual BaseAnnotationHighlighter *createAnnotationHighlighter(const QSet<QString> &changes,
                                                                    const QColor &bg) const = 0;
-    // Implement to return a local file name from the diff file specification
-    // (text cursor at position above change hunk)
-    virtual QString fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const = 0;
     // Implement to return decorated annotation change for "Annotate version"
     virtual QString decorateVersion(const QString &revision) const;
     // Implement to return the previous version[s] of an annotation change
@@ -253,6 +255,8 @@ private:
     virtual QStringList annotationPreviousVersions(const QString &revision) const;
     // Implement to validate revisions
     virtual bool isValidRevision(const QString &revision) const;
+
+private:
     // cut out chunk and determine file name.
     DiffChunk diffChunk(QTextCursor cursor) const;
 
@@ -260,6 +264,11 @@ private:
 
     friend class Internal::ChangeTextCursorHandler;
     Internal::VcsBaseEditorWidgetPrivate *const d;
+
+#if WITH_TESTS
+public:
+    static void testDiffFileResolving(VcsBaseEditorWidget *editor);
+#endif
 };
 
 } // namespace VcsBase