diff --git a/src/plugins/coreplugin/iversioncontrol.h b/src/plugins/coreplugin/iversioncontrol.h
index 4b3b7c4cc754defb8d1512b7aa9a82f62029c021..13b43a687adfa5b7284cbc2ed7d3fb2f1de221ce 100644
--- a/src/plugins/coreplugin/iversioncontrol.h
+++ b/src/plugins/coreplugin/iversioncontrol.h
@@ -44,7 +44,8 @@ public:
     enum Operation {
         AddOperation, DeleteOperation, OpenOperation,
         CreateRepositoryOperation,
-        SnapshotOperations
+        SnapshotOperations,
+        AnnotateOperation
         };
 
     explicit IVersionControl(QObject *parent = 0) : QObject(parent) {}
@@ -126,6 +127,11 @@ public:
      */
     virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name) = 0;
 
+    /*!
+     * Display annotation for a file and scroll to line
+     */
+    virtual bool vcsAnnotate(const QString &file, int line) = 0;
+
 signals:
     void repositoryChanged(const QString &repository);
     void filesChanged(const QStringList &files);
diff --git a/src/plugins/cvs/cvscontrol.cpp b/src/plugins/cvs/cvscontrol.cpp
index e2c559174b1ee325e8a64879213952c8d3fbef78..33e08c03a057173829455091e5232ddbda86a79c 100644
--- a/src/plugins/cvs/cvscontrol.cpp
+++ b/src/plugins/cvs/cvscontrol.cpp
@@ -52,6 +52,7 @@ bool CVSControl::supportsOperation(Operation operation) const
     switch (operation) {
     case AddOperation:
     case DeleteOperation:
+    case AnnotateOperation:
         break;
     case OpenOperation:
     case CreateRepositoryOperation:
@@ -105,6 +106,12 @@ bool CVSControl::vcsRemoveSnapshot(const QString &, const QString &)
     return false;
 }
 
+bool CVSControl::vcsAnnotate(const QString &file, int line)
+{
+    m_plugin->vcsAnnotate(file, QString(), line);
+    return true;
+}
+
 bool CVSControl::managesDirectory(const QString &directory) const
 {
     return m_plugin->managesDirectory(directory);
diff --git a/src/plugins/cvs/cvscontrol.h b/src/plugins/cvs/cvscontrol.h
index 74bb1cda882aed66d1ff1c9999d05dc97b6ef904..24483afed331854008d1baafd1fc266cc1f5341e 100644
--- a/src/plugins/cvs/cvscontrol.h
+++ b/src/plugins/cvs/cvscontrol.h
@@ -57,6 +57,7 @@ public:
     virtual QStringList vcsSnapshots(const QString &topLevel);
     virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
     virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
+    virtual bool vcsAnnotate(const QString &file, int line);
 
     void emitRepositoryChanged(const QString &s);
     void emitFilesChanged(const QStringList &l);
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 78df829fcda866250da9ac8660ed4b39c8d1e484..b45deb226f9a970d7b1cbcb8f859b33e5af4194f 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -771,7 +771,7 @@ void CVSPlugin::annotateCurrentFile()
     annotate(state.currentFileTopLevel(), state.relativeCurrentFile());
 }
 
-void CVSPlugin::annotateVersion(const QString &file, const QString &revision, int lineNumber)
+void CVSPlugin::vcsAnnotate(const QString &file, const QString &revision, int lineNumber)
 {
     const QFileInfo fi(file);
     annotate(fi.absolutePath(), fi.fileName(), revision, lineNumber);
@@ -1072,7 +1072,7 @@ Core::IEditor * CVSPlugin::showOutputInEditor(const QString& title, const QStrin
     QString s = title;
     Core::IEditor *editor = Core::EditorManager::instance()->openEditorWithContents(id, &s, output.toLocal8Bit());
     connect(editor, SIGNAL(annotateRevisionRequested(QString,QString,int)),
-            this, SLOT(annotateVersion(QString,QString,int)));
+            this, SLOT(vcsAnnotate(QString,QString,int)));
     CVSEditor *e = qobject_cast<CVSEditor*>(editor->widget());
     if (!e)
         return 0;
diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h
index 312a085843502cd82c6e434b8dad8593590dc36d..12a1ee674f3ce431fba3bc572da43731fba4b8b2 100644
--- a/src/plugins/cvs/cvsplugin.h
+++ b/src/plugins/cvs/cvsplugin.h
@@ -101,6 +101,9 @@ public:
 
     static CVSPlugin *cvsPluginInstance();
 
+public slots:
+    void vcsAnnotate(const QString &file, const QString &revision /* = QString() */, int lineNumber);
+
 private slots:
     void addCurrentFile();
     void revertCurrentFile();
@@ -111,7 +114,6 @@ private slots:
     void startCommitCurrentFile();
     void filelogCurrentFile();
     void annotateCurrentFile();
-    void annotateVersion(const QString &file, const QString &revision, int lineNumber);
     void projectStatus();
     void slotDescribe(const QString &source, const QString &changeNr);
     void updateProject();
diff --git a/src/plugins/git/gitversioncontrol.cpp b/src/plugins/git/gitversioncontrol.cpp
index 65308fb17483aae01cdf5455cb3a60cb8901735d..07ff95213432bc45e1d169d28c390808140e89f5 100644
--- a/src/plugins/git/gitversioncontrol.cpp
+++ b/src/plugins/git/gitversioncontrol.cpp
@@ -81,6 +81,9 @@ bool GitVersionControl::supportsOperation(Operation operation) const
     case SnapshotOperations:
         rc = true;
         break;
+    case AnnotateOperation:
+        rc = true;
+        break;
     }
     return rc;
 }
@@ -203,6 +206,13 @@ QString GitVersionControl::findTopLevelForDirectory(const QString &directory) co
     return GitClient::findRepositoryForDirectory(directory);
 }
 
+bool GitVersionControl::vcsAnnotate(const QString &file, int line)
+{
+    const QFileInfo fi(file);
+    gitClient()->blame(fi.absolutePath(), fi.fileName(), QString(), line);
+    return true;
+}
+
 void GitVersionControl::emitFilesChanged(const QStringList &l)
 {
     emit filesChanged(l);
diff --git a/src/plugins/git/gitversioncontrol.h b/src/plugins/git/gitversioncontrol.h
index 44e65df84db6231654b670162720c8a843e94de2..c53c1f2ab5cf2af5c47871e37c0f4cc35e36f5fe 100644
--- a/src/plugins/git/gitversioncontrol.h
+++ b/src/plugins/git/gitversioncontrol.h
@@ -59,6 +59,8 @@ public:
     virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
     virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
 
+    virtual bool vcsAnnotate(const QString &file, int line);
+
     void emitFilesChanged(const QStringList &);
     void emitRepositoryChanged(const QString &);
 
diff --git a/src/plugins/mercurial/mercurialcontrol.cpp b/src/plugins/mercurial/mercurialcontrol.cpp
index a0af2093104df5a5e7bb0c2cdcc6ba9ae0cabc19..1b707b9c8b769253c49a02ccc8bd094f8fa90d6a 100644
--- a/src/plugins/mercurial/mercurialcontrol.cpp
+++ b/src/plugins/mercurial/mercurialcontrol.cpp
@@ -66,6 +66,7 @@ bool MercurialControl::supportsOperation(Operation operation) const
     case Core::IVersionControl::AddOperation:
     case Core::IVersionControl::DeleteOperation:
     case Core::IVersionControl::CreateRepositoryOperation:
+    case Core::IVersionControl::AnnotateOperation:
         break;
     case Core::IVersionControl::OpenOperation:
     case Core::IVersionControl::SnapshotOperations:
@@ -118,6 +119,13 @@ bool MercurialControl::vcsRemoveSnapshot(const QString &, const QString &)
     return false;
 }
 
+bool MercurialControl::vcsAnnotate(const QString &file, int line)
+{
+    const QFileInfo fi(file);
+    mercurialClient->annotate(fi.absolutePath(), fi.fileName(), QString(), line);
+    return true;
+}
+
 bool MercurialControl::sccManaged(const QString &filename)
 {
     const QFileInfo fi(filename);
diff --git a/src/plugins/mercurial/mercurialcontrol.h b/src/plugins/mercurial/mercurialcontrol.h
index c82401bad89804cc4baa28b6f5851d3e1da83b16..b6ee396b1c726d9c0841b5347d4cd705415ef084 100644
--- a/src/plugins/mercurial/mercurialcontrol.h
+++ b/src/plugins/mercurial/mercurialcontrol.h
@@ -62,6 +62,7 @@ public:
     bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
     bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
     bool sccManaged(const QString &filename);
+    virtual bool vcsAnnotate(const QString &file, int line);
 
 public slots:
     // To be connected to the HgTask's success signal to emit the repository/
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index 287d9bcfe2102f0eebd65792d15a23bccf3bfdce..fe3cbb5a29a8a377d3355a6cceadf2c5b4a9a081 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -723,7 +723,7 @@ void PerforcePlugin::annotate()
     }
 }
 
-void PerforcePlugin::annotateVersion(const QString &file, const QString &revision, int lineNumber)
+void PerforcePlugin::vcsAnnotate(const QString &file, const QString &revision, int lineNumber)
 {
     const QFileInfo fi(file);
     annotate(fi.absolutePath(), fi.fileName(), revision, lineNumber);
@@ -1175,7 +1175,7 @@ Core::IEditor * PerforcePlugin::showOutputInEditor(const QString& title, const Q
     QString s = title;
     Core::IEditor *editor = Core::EditorManager::instance()->openEditorWithContents(id, &s, output);
     connect(editor, SIGNAL(annotateRevisionRequested(QString,QString,int)),
-            this, SLOT(annotateVersion(QString,QString,int)));
+            this, SLOT(vcsAnnotate(QString,QString,int)));
     PerforceEditor *e = qobject_cast<PerforceEditor*>(editor->widget());
     if (!e)
         return 0;
diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h
index 2e62b5d5f9522c3981aba7f4838a88940180a6ad..7c88baef1a9ce09ee31db52d47f1f297c974e75d 100644
--- a/src/plugins/perforce/perforceplugin.h
+++ b/src/plugins/perforce/perforceplugin.h
@@ -106,6 +106,7 @@ public:
 
 public slots:
     void describe(const QString &source, const QString &n);
+    void vcsAnnotate(const QString &file, const QString &revision /* = QString() */, int lineNumber);
 
 private slots:
     void openCurrentFile();
@@ -123,7 +124,6 @@ private slots:
     void describeChange();
     void annotateCurrentFile();
     void annotate();
-    void annotateVersion(const QString &file, const QString &revision, int lineNumber);
     void filelogCurrentFile();
     void filelog();
     void logProject();
diff --git a/src/plugins/perforce/perforceversioncontrol.cpp b/src/plugins/perforce/perforceversioncontrol.cpp
index 69602d88113d10bab328dfa60a0ff17a9525d572..ecd75e7bfdfb426ad78550086a0cf0ebc7d6ac67 100644
--- a/src/plugins/perforce/perforceversioncontrol.cpp
+++ b/src/plugins/perforce/perforceversioncontrol.cpp
@@ -54,6 +54,7 @@ bool PerforceVersionControl::supportsOperation(Operation operation) const
     case AddOperation:
     case DeleteOperation:
     case OpenOperation:
+    case AnnotateOperation:
         return true;
     case CreateRepositoryOperation:
     case SnapshotOperations:
@@ -105,6 +106,12 @@ bool PerforceVersionControl::vcsRemoveSnapshot(const QString &, const QString &)
     return false;
 }
 
+bool PerforceVersionControl::vcsAnnotate(const QString &file, int line)
+{
+    m_plugin->vcsAnnotate(file, QString(), line);
+    return true;
+}
+
 bool PerforceVersionControl::managesDirectory(const QString &directory) const
 {
     const bool rc = m_plugin->managesDirectory(directory);
diff --git a/src/plugins/perforce/perforceversioncontrol.h b/src/plugins/perforce/perforceversioncontrol.h
index 063a3be77ce77959ad7baed82b3f54f613eaa59b..5be2ac9826bd6027066e37aad5fd3c754dc08482 100644
--- a/src/plugins/perforce/perforceversioncontrol.h
+++ b/src/plugins/perforce/perforceversioncontrol.h
@@ -57,6 +57,7 @@ public:
     virtual QStringList vcsSnapshots(const QString &topLevel);
     virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
     virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
+    virtual bool vcsAnnotate(const QString &file, int line);
 
     void emitRepositoryChanged(const QString &s);
     void emitFilesChanged(const QStringList &l);
diff --git a/src/plugins/projectexplorer/taskwindow.cpp b/src/plugins/projectexplorer/taskwindow.cpp
index 6b7a446e1f078932b08135f62416b924c10be179..493c5039324601b7bd1ade86d9d9490ca0ef9bd7 100644
--- a/src/plugins/projectexplorer/taskwindow.cpp
+++ b/src/plugins/projectexplorer/taskwindow.cpp
@@ -31,6 +31,8 @@
 
 #include <coreplugin/actionmanager/actionmanager.h>
 #include <coreplugin/coreconstants.h>
+#include <coreplugin/vcsmanager.h>
+#include <coreplugin/iversioncontrol.h>
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/icore.h>
 #include <coreplugin/uniqueidmanager.h>
@@ -40,6 +42,7 @@
 
 #include <QtCore/QDir>
 #include <QtCore/QFileInfo>
+#include <QtCore/QDebug>
 #include <QtGui/QApplication>
 #include <QtGui/QClipboard>
 #include <QtGui/QKeyEvent>
@@ -464,16 +467,21 @@ TaskWindow::TaskWindow()
     Core::Command *command = core->actionManager()->
             registerAction(m_copyAction, Core::Constants::COPY, m_taskWindowContext->context());
     m_listview->addAction(command->action());
+    connect(m_copyAction, SIGNAL(triggered()), SLOT(copy()));
 
-    connect(m_listview->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
-            tld, SLOT(currentChanged(const QModelIndex &, const QModelIndex &)));
+    m_vcsAnnotateAction = new QAction(tr("&Annotate"), this);
+    command = core->actionManager()->
+            registerAction(m_vcsAnnotateAction, QLatin1String("ProjectExplorer.Task.VCS_Annotate"), m_taskWindowContext->context());
+    m_listview->addAction(command->action());
+    connect(m_vcsAnnotateAction, SIGNAL(triggered()), SLOT(vcsAnnotate()));
 
-    connect(m_listview, SIGNAL(activated(const QModelIndex &)),
-            this, SLOT(showTaskInFile(const QModelIndex &)));
-    connect(m_listview, SIGNAL(clicked(const QModelIndex &)),
-            this, SLOT(showTaskInFile(const QModelIndex &)));
+    connect(m_listview->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+            tld, SLOT(currentChanged(QModelIndex,QModelIndex)));
 
-    connect(m_copyAction, SIGNAL(triggered()), SLOT(copy()));
+    connect(m_listview, SIGNAL(activated(QModelIndex)),
+            this, SLOT(showTaskInFile(QModelIndex)));
+    connect(m_listview, SIGNAL(clicked(QModelIndex)),
+            this, SLOT(showTaskInFile(QModelIndex)));
 
     m_filterWarningsButton = createFilterButton(Task::Warning,
                                                 tr("Show Warnings"), m_model,
@@ -563,12 +571,29 @@ void TaskWindow::showTaskInFile(const QModelIndex &index)
     m_listview->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
 }
 
+// Right-click VCS annotate: Find version control and point it to line
+void TaskWindow::vcsAnnotate()
+{
+    const QModelIndex index = m_listview->selectionModel()->currentIndex();
+    if (!index.isValid())
+        return;
+    const QString file = index.data(TaskModel::File).toString();
+    const int line = index.data(TaskModel::Line).toInt();
+    const QFileInfo fi(file);
+    if (fi.exists())
+        if (Core::IVersionControl *vc = Core::ICore::instance()->vcsManager()->findVersionControlForDirectory(fi.absolutePath()))
+            if (vc->supportsOperation(Core::IVersionControl::AnnotateOperation))
+                vc->vcsAnnotate(fi.absoluteFilePath(), line);
+}
+
 void TaskWindow::copy()
 {
-    QModelIndex index = m_listview->selectionModel()->currentIndex();
-    QString file = index.data(TaskModel::File).toString();
-    QString line = index.data(TaskModel::Line).toString();
-    QString description = index.data(TaskModel::Description).toString();
+    const QModelIndex index = m_listview->selectionModel()->currentIndex();
+    if (!index.isValid())
+        return;
+    const QString file = index.data(TaskModel::File).toString();
+    const QString line = index.data(TaskModel::Line).toString();
+    const QString description = index.data(TaskModel::Description).toString();
     QString type;
     switch (index.data(TaskModel::Type).toInt()) {
     case Task::Error:
diff --git a/src/plugins/projectexplorer/taskwindow.h b/src/plugins/projectexplorer/taskwindow.h
index 3592591f400bafaf430d02c8687f7fc62dbe56c7..e2f02245933e11c83b25c3723ce04d92307ffa3b 100644
--- a/src/plugins/projectexplorer/taskwindow.h
+++ b/src/plugins/projectexplorer/taskwindow.h
@@ -119,6 +119,7 @@ signals:
 private slots:
     void showTaskInFile(const QModelIndex &index);
     void copy();
+    void vcsAnnotate();
     void setShowWarnings(bool);
     void updateCategoriesMenu();
     void filterCategoryTriggered(QAction *action);
@@ -132,6 +133,7 @@ private:
     Internal::TaskView *m_listview;
     Internal::TaskWindowContext *m_taskWindowContext;
     QAction *m_copyAction;
+    QAction *m_vcsAnnotateAction;
     QToolButton *m_filterWarningsButton;
     QToolButton *m_categoriesButton;
     QMenu *m_categoriesMenu;
diff --git a/src/plugins/subversion/subversioncontrol.cpp b/src/plugins/subversion/subversioncontrol.cpp
index ef6a5677fc7718b8628ed764b61d94f82c600ae3..c58159ff60b358a75dc1d6598944fad29b969cf7 100644
--- a/src/plugins/subversion/subversioncontrol.cpp
+++ b/src/plugins/subversion/subversioncontrol.cpp
@@ -52,6 +52,7 @@ bool SubversionControl::supportsOperation(Operation operation) const
     switch (operation) {
     case AddOperation:
     case DeleteOperation:
+    case AnnotateOperation:
         break;
     case OpenOperation:
     case CreateRepositoryOperation:
@@ -115,6 +116,13 @@ QString SubversionControl::findTopLevelForDirectory(const QString &directory) co
     return m_plugin->findTopLevelForDirectory(directory);
 }
 
+bool SubversionControl::vcsAnnotate(const QString &file, int line)
+{
+    const QFileInfo fi(file);
+    m_plugin->vcsAnnotate(fi.absolutePath(), fi.fileName(), QString(), line);
+    return true;
+}
+
 void SubversionControl::emitRepositoryChanged(const QString &s)
 {
     emit repositoryChanged(s);
diff --git a/src/plugins/subversion/subversioncontrol.h b/src/plugins/subversion/subversioncontrol.h
index 43e803ace9b47b1522fbb2d07253739602d65283..132aca4d8ec95b237a31520eac47256989b79642 100644
--- a/src/plugins/subversion/subversioncontrol.h
+++ b/src/plugins/subversion/subversioncontrol.h
@@ -59,6 +59,8 @@ public:
     virtual bool vcsRestoreSnapshot(const QString &topLevel, const QString &name);
     virtual bool vcsRemoveSnapshot(const QString &topLevel, const QString &name);
 
+    virtual bool vcsAnnotate(const QString &file, int line);
+
     void emitRepositoryChanged(const QString &);
     void emitFilesChanged(const QStringList &);
 
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index ee1a116964158e6e9d8af644a25a5d63ea163308..bcc249ef5f84c624a8e5c32d053a806f3febc64a 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -799,7 +799,7 @@ void SubversionPlugin::annotateCurrentFile()
 {
     const VCSBase::VCSBasePluginState state = currentState();
     QTC_ASSERT(state.hasFile(), return);
-    annotate(state.currentFileTopLevel(), state.relativeCurrentFile());
+    vcsAnnotate(state.currentFileTopLevel(), state.relativeCurrentFile());
 }
 
 void SubversionPlugin::annotateVersion(const QString &file,
@@ -807,10 +807,10 @@ void SubversionPlugin::annotateVersion(const QString &file,
                                        int lineNr)
 {
     const QFileInfo fi(file);
-    annotate(fi.absolutePath(), fi.fileName(), revision, lineNr);
+    vcsAnnotate(fi.absolutePath(), fi.fileName(), revision, lineNr);
 }
 
-void SubversionPlugin::annotate(const QString &workingDir, const QString &file,
+void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &file,
                                 const QString &revision /* = QString() */,
                                 int lineNumber /* = -1 */)
 {
diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h
index 9acf0926b2aa6e6550354ba7fb40c4c906b8e7e6..2a9283da2fa0d903a097a0ccca5ecee282fd2b09 100644
--- a/src/plugins/subversion/subversionplugin.h
+++ b/src/plugins/subversion/subversionplugin.h
@@ -100,6 +100,10 @@ public:
 
     static SubversionPlugin *subversionPluginInstance();
 
+public slots:
+    void vcsAnnotate(const QString &workingDir, const QString &file,
+                     const QString &revision = QString(), int lineNumber = -1);
+
 private slots:
     void addCurrentFile();
     void revertCurrentFile();
@@ -132,8 +136,6 @@ private:
     SubversionResponse runSvn(const QString &workingDir,
                               const QStringList &arguments, int timeOut,
                               bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0);
-    void annotate(const QString &workingDir, const QString &file,
-                  const QString &revision = QString(), int lineNumber = -1);
     void filelog(const QString &workingDir,
                  const QStringList &file = QStringList(),
                  bool enableAnnotationContextMenu = false);