diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 5c0954b263168fd8066b54e29f5a89333c537f16..aa09dd376f2f6693cf9a9fe10901c0bed703b87f 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -115,7 +115,7 @@ GitPlugin::GitPlugin() :
     m_blameAction(0),
     m_logProjectAction(0),
     m_undoFileAction(0),
-    m_undoProjectAction(0),
+    m_undoRepositoryAction(0),
     m_showAction(0),
     m_stageAction(0),
     m_unstageAction(0),
@@ -282,10 +282,10 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
     connect(m_logProjectAction, SIGNAL(triggered()), this, SLOT(logProject()));
     gitContainer->addAction(command);
 
-    m_undoProjectAction = new QAction(tr("Undo Project Changes"), this);
-    command = actionManager->registerAction(m_undoProjectAction, "Git.UndoProject", globalcontext);
+    m_undoRepositoryAction = new QAction(tr("Undo Repository Changes"), this);
+    command = actionManager->registerAction(m_undoRepositoryAction, "Git.UndoRepository", globalcontext);
     command->setAttribute(Core::Command::CA_UpdateText);
-    connect(m_undoProjectAction, SIGNAL(triggered()), this, SLOT(undoProjectChanges()));
+    connect(m_undoRepositoryAction, SIGNAL(triggered()), this, SLOT(undoRepositoryChanges()));
     gitContainer->addAction(command);
 
     gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Global"), this));
@@ -428,7 +428,7 @@ void GitPlugin::undoFileChanges()
     m_gitClient->revert(QStringList(state.currentFile()));
 }
 
-void GitPlugin::undoProjectChanges()
+void GitPlugin::undoRepositoryChanges()
 {
     const VCSBase::VCSBasePluginState state = currentState();
     QTC_ASSERT(state.hasTopLevel(), return)
@@ -669,7 +669,7 @@ void GitPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
     m_diffProjectAction->setParameter(projectName);
     m_logProjectAction->setEnabled(projectEnabled);
     m_logProjectAction->setParameter(projectName);
-    m_undoProjectAction->setEnabled(projectEnabled);
+    m_undoRepositoryAction->setEnabled(projectEnabled);
 
     const bool repositoryEnabled = currentState().hasTopLevel();
     m_statusRepositoryAction->setEnabled(repositoryEnabled);
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index bd2f6d1af40f344b47a236e8ffa6faf226e4177b..baa46321cbd2bb34e8ccf9c34a55b0885d36ceac 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -95,7 +95,7 @@ private slots:
     void blameFile();
     void logProject();
     void undoFileChanges();
-    void undoProjectChanges();
+    void undoRepositoryChanges();
     void stageFile();
     void unstageFile();
 
@@ -126,7 +126,7 @@ private:
     Utils::ParameterAction *m_blameAction;
     Utils::ParameterAction *m_logProjectAction;
     Utils::ParameterAction *m_undoFileAction;
-    QAction *m_undoProjectAction;
+    QAction *m_undoRepositoryAction;
     QAction *m_showAction;
     Utils::ParameterAction *m_stageAction;
     Utils::ParameterAction *m_unstageAction;
diff --git a/src/plugins/subversion/subversioncontrol.cpp b/src/plugins/subversion/subversioncontrol.cpp
index 901b3f115cec7c13f9c5e9cf6cc63b4628948436..df653466a6985f5ce7c368d27c4ef80a9e897e59 100644
--- a/src/plugins/subversion/subversioncontrol.cpp
+++ b/src/plugins/subversion/subversioncontrol.cpp
@@ -30,6 +30,8 @@
 #include "subversioncontrol.h"
 #include "subversionplugin.h"
 
+#include <QtCore/QFileInfo>
+
 using namespace Subversion;
 using namespace Subversion::Internal;
 
@@ -66,12 +68,14 @@ bool SubversionControl::vcsOpen(const QString & /* fileName */)
 
 bool SubversionControl::vcsAdd(const QString &fileName)
 {
-    return m_plugin->vcsAdd(fileName);
+    const QFileInfo fi(fileName);
+    return m_plugin->vcsAdd(fi.absolutePath(), fi.fileName());
 }
 
 bool SubversionControl::vcsDelete(const QString &fileName)
 {
-    return m_plugin->vcsDelete(fileName);
+    const QFileInfo fi(fileName);
+    return m_plugin->vcsDelete(fi.absolutePath(), fi.fileName());
 }
 
 bool SubversionControl::managesDirectory(const QString &directory) const
diff --git a/src/plugins/subversion/subversioneditor.cpp b/src/plugins/subversion/subversioneditor.cpp
index db5ed169dfb6726dfc5475496283c1e30c45aabe..21e330c5fad6b1a8f4a4d907fd28fd519dff647f 100644
--- a/src/plugins/subversion/subversioneditor.cpp
+++ b/src/plugins/subversion/subversioneditor.cpp
@@ -28,6 +28,7 @@
 **************************************************************************/
 
 #include "subversioneditor.h"
+#include "subversionplugin.h"
 
 #include "annotationhighlighter.h"
 #include "subversionconstants.h"
@@ -36,6 +37,7 @@
 #include <vcsbase/diffhighlighter.h>
 
 #include <QtCore/QDebug>
+#include <QtCore/QFileInfo>
 #include <QtGui/QTextCursor>
 
 using namespace Subversion;
@@ -127,9 +129,10 @@ QString SubversionEditor::fileNameFromDiffSpecification(const QTextBlock &inBloc
             const int tabIndex = diffFileName.lastIndexOf(QLatin1Char('\t'));
             if (tabIndex != -1)
                 diffFileName.truncate(tabIndex);
+            const QString rc = findDiffFile(diffFileName, SubversionPlugin::subversionPluginInstance()->versionControl());
             if (Subversion::Constants::debug)
-                qDebug() << Q_FUNC_INFO << diffFileName;
-            return diffFileName;
+                qDebug() << Q_FUNC_INFO << diffFileName << rc << source();
+            return rc;
         }
     }
     return QString();
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index 7c479121f2f4d08ca37f353708c30258eefd69fb..eece5a9e85a2be24dc5fd05afc8abbb95badefeb 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -52,9 +52,6 @@
 #include <coreplugin/uniqueidmanager.h>
 #include <coreplugin/actionmanager/actionmanager.h>
 #include <coreplugin/editormanager/editormanager.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/session.h>
-#include <projectexplorer/project.h>
 #include <utils/qtcassert.h>
 
 #include <QtCore/QDebug>
@@ -182,7 +179,6 @@ SubversionPlugin *SubversionPlugin::m_subversionPluginInstance = 0;
 SubversionPlugin::SubversionPlugin() :
     VCSBase::VCSBasePlugin(QLatin1String(Subversion::Constants::SUBVERSIONCOMMITEDITOR_KIND)),
     m_svnDirectories(svnDirectories()),
-    m_projectExplorer(0),
     m_addAction(0),
     m_deleteAction(0),
     m_revertAction(0),
@@ -192,7 +188,7 @@ SubversionPlugin::SubversionPlugin() :
     m_commitCurrentAction(0),
     m_filelogCurrentAction(0),
     m_annotateCurrentAction(0),
-    m_statusAction(0),
+    m_statusProjectAction(0),
     m_updateProjectAction(0),
     m_describeAction(0),
     m_submitCurrentLogAction(0),
@@ -214,6 +210,7 @@ void SubversionPlugin::cleanCommitMessageFile()
     if (!m_commitMessageFileName.isEmpty()) {
         QFile::remove(m_commitMessageFileName);
         m_commitMessageFileName.clear();
+        m_commitRepository.clear();
     }
 }
 
@@ -306,9 +303,10 @@ bool SubversionPlugin::initialize(const QStringList & /*arguments */, QString *e
 
     subversionMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR0, globalcontext));
 
-    m_diffProjectAction = new QAction(tr("Diff Project"), this);
+    m_diffProjectAction = new Utils::ParameterAction(tr("Diff Project"), tr("Diff Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
     command = ami->registerAction(m_diffProjectAction, CMD_ID_DIFF_PROJECT,
         globalcontext);
+    command->setAttribute(Core::Command::CA_UpdateText);
     connect(m_diffProjectAction, SIGNAL(triggered()), this, SLOT(diffProject()));
     subversionMenu->addAction(command);
 
@@ -361,15 +359,17 @@ bool SubversionPlugin::initialize(const QStringList & /*arguments */, QString *e
 
     subversionMenu->addAction(createSeparator(this, ami, CMD_ID_SEPARATOR3, globalcontext));
 
-    m_statusAction = new QAction(tr("Project Status"), this);
-    command = ami->registerAction(m_statusAction, CMD_ID_STATUS,
+    m_statusProjectAction = new Utils::ParameterAction(tr("Project Status"), tr("Status of Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
+    command = ami->registerAction(m_statusProjectAction, CMD_ID_STATUS,
         globalcontext);
-    connect(m_statusAction, SIGNAL(triggered()), this, SLOT(projectStatus()));
+    command->setAttribute(Core::Command::CA_UpdateText);
+    connect(m_statusProjectAction, SIGNAL(triggered()), this, SLOT(projectStatus()));
     subversionMenu->addAction(command);
 
-    m_updateProjectAction = new QAction(tr("Update Project"), this);
+    m_updateProjectAction = new Utils::ParameterAction(tr("Update Project"), tr("Update Project \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
     command = ami->registerAction(m_updateProjectAction, CMD_ID_UPDATE, globalcontext);
     connect(m_updateProjectAction, SIGNAL(triggered()), this, SLOT(updateProject()));
+    command->setAttribute(Core::Command::CA_UpdateText);
     subversionMenu->addAction(command);
 
     // Actions of the submit editor
@@ -394,7 +394,6 @@ bool SubversionPlugin::initialize(const QStringList & /*arguments */, QString *e
 
 void SubversionPlugin::extensionsInitialized()
 {
-    m_projectExplorer = ProjectExplorer::ProjectExplorerPlugin::instance();
 }
 
 bool SubversionPlugin::submitEditorAboutToClose(VCSBase::VCSBaseSubmitEditor *submitEditor)
@@ -447,16 +446,16 @@ bool SubversionPlugin::submitEditorAboutToClose(VCSBase::VCSBaseSubmitEditor *su
     return closeEditor;
 }
 
-void SubversionPlugin::diffFiles(const QStringList &files)
+void SubversionPlugin::diffCommitFiles(const QStringList &files)
 {
-    svnDiff(files);
+    svnDiff(m_commitRepository, files);
 }
 
-void SubversionPlugin::svnDiff(const QStringList &files, QString diffname)
+void SubversionPlugin::svnDiff(const QString &workingDir, const QStringList &files, QString diffname)
 {
     if (Subversion::Constants::debug)
         qDebug() << Q_FUNC_INFO << files << diffname;
-    const QString source = files.empty() ? QString() : files.front();
+    const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, files);
     QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VCSBase::VCSBaseEditor::getCodec(source);
 
     if (files.count() == 1 && diffname.isEmpty())
@@ -465,7 +464,7 @@ void SubversionPlugin::svnDiff(const QStringList &files, QString diffname)
     QStringList args(QLatin1String("diff"));
     args << files;
 
-    const SubversionResponse response = runSvn(args, subversionShortTimeOut, false, codec);
+    const SubversionResponse response = runSvn(workingDir, args, subversionShortTimeOut, false, codec);
     if (response.error)
         return;
 
@@ -491,7 +490,7 @@ SubversionSubmitEditor *SubversionPlugin::openSubversionSubmitEditor(const QStri
     SubversionSubmitEditor *submitEditor = qobject_cast<SubversionSubmitEditor*>(editor);
     QTC_ASSERT(submitEditor, /**/);
     submitEditor->registerActions(m_submitUndoAction, m_submitRedoAction, m_submitCurrentLogAction, m_submitDiffAction);
-    connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(diffFiles(QStringList)));
+    connect(submitEditor, SIGNAL(diffSelectedFiles(QStringList)), this, SLOT(diffCommitFiles(QStringList)));
 
     return submitEditor;
 }
@@ -501,47 +500,49 @@ void SubversionPlugin::updateActions(VCSBase::VCSBasePlugin::ActionState as)
     if (!VCSBase::VCSBasePlugin::enableMenuAction(as, m_menuAction))
         return;
 
-    m_diffProjectAction->setEnabled(true);
-    m_commitAllAction->setEnabled(true);
-    m_statusAction->setEnabled(true);
-    m_describeAction->setEnabled(true);
-
-    const QString fileName = currentFileName();
-    const QString baseName = fileName.isEmpty() ? fileName : QFileInfo(fileName).fileName();
-
-    m_addAction->setParameter(baseName);
-    m_deleteAction->setParameter(baseName);
-    m_revertAction->setParameter(baseName);
-    m_diffCurrentAction->setParameter(baseName);
-    m_commitCurrentAction->setParameter(baseName);
-    m_filelogCurrentAction->setParameter(baseName);
-    m_annotateCurrentAction->setParameter(baseName);
+    const QString projectName = currentState().currentProjectName();
+    m_diffProjectAction->setParameter(projectName);
+    m_statusProjectAction->setParameter(projectName);
+    m_updateProjectAction->setParameter(projectName);
+
+    const bool repoEnabled = currentState().hasTopLevel();
+    m_commitAllAction->setEnabled(repoEnabled);
+    m_describeAction->setEnabled(repoEnabled);
+
+    const QString fileName = currentState().currentFileName();
+
+    m_addAction->setParameter(fileName);
+    m_deleteAction->setParameter(fileName);
+    m_revertAction->setParameter(fileName);
+    m_diffCurrentAction->setParameter(fileName);
+    m_commitCurrentAction->setParameter(fileName);
+    m_filelogCurrentAction->setParameter(fileName);
+    m_annotateCurrentAction->setParameter(fileName);
 }
 
 void SubversionPlugin::addCurrentFile()
 {
-    const QString file = currentFileName();
-    if (!file.isEmpty())
-        vcsAdd(file);
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
+    vcsAdd(state.currentFileTopLevel(), state.relativeCurrentFile());
 }
 
 void SubversionPlugin::deleteCurrentFile()
 {
-    const QString file = currentFileName();
-    if (!file.isEmpty())
-        vcsDelete(file);
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
+    vcsDelete(state.currentFileTopLevel(), state.relativeCurrentFile());
 }
 
 void SubversionPlugin::revertCurrentFile()
 {
-    const QString file = QDir::toNativeSeparators(currentFileName());
-    if (file.isEmpty())
-        return;
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
 
     QStringList args(QLatin1String("diff"));
-    args.push_back(file);
+    args.push_back(state.relativeCurrentFile());
 
-    const SubversionResponse diffResponse = runSvn(args, subversionShortTimeOut, false);
+    const SubversionResponse diffResponse = runSvn(state.currentFileTopLevel(), args, subversionShortTimeOut, false);
     if (diffResponse.error)
         return;
 
@@ -552,97 +553,52 @@ void SubversionPlugin::revertCurrentFile()
         return;
 
 
-    Core::FileChangeBlocker fcb(file);
+    Core::FileChangeBlocker fcb(state.currentFile());
 
     // revert
     args.clear();
-    args.push_back(QLatin1String("revert"));
-    args.append(file);
+    args << QLatin1String("revert") << state.relativeCurrentFile();
 
-    const SubversionResponse revertResponse = runSvn(args, subversionShortTimeOut, true);
+    const SubversionResponse revertResponse = runSvn(state.currentFileTopLevel(), args, subversionShortTimeOut, true);
     if (!revertResponse.error) {
         fcb.setModifiedReload(true);
-        subVersionControl()->emitFilesChanged(QStringList(file));
-    }
-}
-
-// Get a unique set of toplevel directories for the current projects.
-// To be used for "diff all" or "commit all".
-QStringList SubversionPlugin::currentProjectsTopLevels(QString *name) const
-{
-    typedef QList<ProjectExplorer::Project *> ProjectList;
-    ProjectList projects;
-    // Compile list of projects
-    if (ProjectExplorer::Project *currentProject = m_projectExplorer->currentProject()) {
-        projects.push_back(currentProject);
-    } else {
-        if (const ProjectExplorer::SessionManager *session = m_projectExplorer->session())
-            projects.append(session->projects());
-    }
-    // Get unique set of toplevels and concat project names
-    QStringList toplevels;
-    const QChar blank(QLatin1Char(' '));
-    foreach (const ProjectExplorer::Project *p,  projects) {
-        if (name) {
-            if (!name->isEmpty())
-                name->append(blank);
-            name->append(p->name());
-        }
-
-        const QString projectPath = QFileInfo(p->file()->fileName()).absolutePath();
-        const QString topLevel = findTopLevelForDirectory(projectPath);
-        if (!topLevel.isEmpty() && !toplevels.contains(topLevel))
-            toplevels.push_back(topLevel);
+        subVersionControl()->emitFilesChanged(QStringList(state.currentFile()));
     }
-    return toplevels;
 }
 
 void SubversionPlugin::diffProject()
 {
-    QString diffName;
-    const QStringList topLevels = currentProjectsTopLevels(&diffName);
-    if (!topLevels.isEmpty())
-        svnDiff(topLevels, diffName);
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasProject(), return)
+    svnDiff(state.currentProjectTopLevel(), state.relativeCurrentProject(), state.currentProjectName());
 }
 
 void SubversionPlugin::diffCurrentFile()
 {
-    svnDiff(QStringList(currentFileName()));
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
+    svnDiff(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
 }
 
 void SubversionPlugin::startCommitCurrentFile()
 {
-    const QString file = QDir::toNativeSeparators(currentFileName());
-    if (!file.isEmpty())
-        startCommit(QStringList(file));
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
+    startCommit(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
 }
 
 void SubversionPlugin::startCommitAll()
 {
-    // Make sure we have only repository for commit
-    const QStringList files = currentProjectsTopLevels();
-    switch (files.size()) {
-    case 0:
-        break;
-    case 1:
-        startCommit(files);
-        break;
-    default: {
-        const QString msg = tr("The commit list spans several repositories (%1). Please commit them one by one.").
-            arg(files.join(QString(QLatin1Char(' '))));
-        QMessageBox::warning(0, QLatin1String("svn commit"), msg, QMessageBox::Ok);
-    }
-        break;
-    }
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasTopLevel(), return);
+    startCommit(state.topLevel());
 }
 
 /* Start commit of files of a single repository by displaying
  * template and files in a submit editor. On closing, the real
  * commit will start. */
-void SubversionPlugin::startCommit(const QStringList &files)
+void SubversionPlugin::startCommit(const QString &workingDir, const QStringList &files)
 {
-    if (files.empty())
-        return;
     if (VCSBase::VCSBaseSubmitEditor::raiseSubmitEditor())
         return;
     if (isCommitEditorOpen()) {
@@ -652,19 +608,18 @@ void SubversionPlugin::startCommit(const QStringList &files)
 
     QStringList args(QLatin1String("status"));
     args += files;
-    if (args.size() == 1)
-        return;
 
-    const SubversionResponse response = runSvn(args, subversionShortTimeOut, false);
+    const SubversionResponse response = runSvn(workingDir, args, subversionShortTimeOut, false);
     if (response.error)
         return;
+
     // Get list of added/modified/deleted files
     const StatusList statusOutput = parseStatusOutput(response.stdOut);
     if (statusOutput.empty()) {
         VCSBase::VCSBaseOutputWindow::instance()->appendWarning(tr("There are no modified files."));
         return;
     }
-
+    m_commitRepository = workingDir;
     // Create a new submit change file containing the submit template
     QTemporaryFile changeTmpFile;
     changeTmpFile.setAutoRemove(false);
@@ -695,65 +650,65 @@ bool SubversionPlugin::commit(const QString &messageFile,
     QStringList args = QStringList(QLatin1String("commit"));
     args << QLatin1String(nonInteractiveOptionC) << QLatin1String("--file") << messageFile;
     args.append(subVersionFileList);
-    const SubversionResponse response = runSvn(args, subversionLongTimeOut, true);
+    const SubversionResponse response = runSvn(m_commitRepository, args, subversionLongTimeOut, true);
     return !response.error ;
 }
 
 void SubversionPlugin::filelogCurrentFile()
 {
-    const QString file = currentFileName();
-    if (!file.isEmpty())
-        filelog(file);
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return)
+   filelog(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
 }
 
-void SubversionPlugin::filelog(const QString &file)
+void SubversionPlugin::filelog(const QString &workingDir, const QStringList &files)
 {
-    QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(file);
+    QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(workingDir, files);
     // no need for temp file
     QStringList args(QLatin1String("log"));
-    args.append(QDir::toNativeSeparators(file));
+    foreach(const QString &file, files)
+        args.append(QDir::toNativeSeparators(file));
 
-    const SubversionResponse response = runSvn(args, subversionShortTimeOut, false, codec);
+    const SubversionResponse response = runSvn(workingDir, args, subversionShortTimeOut, false, codec);
     if (response.error)
         return;
 
     // Re-use an existing view if possible to support
     // the common usage pattern of continuously changing and diffing a file
 
-    if (Core::IEditor *editor = locateEditor("logFileName", file)) {
+    const QString id = VCSBase::VCSBaseEditor::getTitleId(workingDir, files);
+    if (Core::IEditor *editor = locateEditor("logFileName", id)) {
         editor->createNew(response.stdOut);
         Core::EditorManager::instance()->activateEditor(editor);
     } else {
-        const QString title = QString::fromLatin1("svn log %1").arg(QFileInfo(file).fileName());
-        Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, file, codec);
-        newEditor->setProperty("logFileName", file);
+        const QString title = QString::fromLatin1("svn log %1").arg(id);
+        const QString source = VCSBase::VCSBaseEditor::getSource(workingDir, files);
+        Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, codec);
+        newEditor->setProperty("logFileName", id);
     }
 }
 
 void SubversionPlugin::updateProject()
 {
-    const QStringList topLevels = currentProjectsTopLevels();
-    if (topLevels.empty())
-        return;
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasProject(), return);
 
     QStringList args(QLatin1String("update"));
     args.push_back(QLatin1String(nonInteractiveOptionC));
-    args.append(topLevels);
-    const SubversionResponse response = runSvn(args, subversionLongTimeOut, true);
-    if (!response.error) {
-        foreach(const QString &repo, topLevels)
-            subVersionControl()->emitRepositoryChanged(repo);
-    }
+    args.append(state.relativeCurrentProject());
+    const SubversionResponse response = runSvn(state.currentProjectTopLevel(), args, subversionLongTimeOut, true);
+    if (!response.error)
+        subVersionControl()->emitRepositoryChanged(state.currentProjectTopLevel());
 }
 
 void SubversionPlugin::annotateCurrentFile()
 {
-    const QString file = currentFileName();
-    if (!file.isEmpty())
-        annotate(file);
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasFile(), return);
+    annotate(state.currentFileTopLevel(), state.relativeCurrentFile());
 }
 
-void SubversionPlugin::annotate(const QString &file)
+void SubversionPlugin::annotate(const QString &workingDir, const QString &file)
 {
     QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(file);
 
@@ -761,38 +716,35 @@ void SubversionPlugin::annotate(const QString &file)
     args.push_back(QLatin1String("-v"));
     args.append(QDir::toNativeSeparators(file));
 
-    const SubversionResponse response = runSvn(args, subversionShortTimeOut, false, codec);
+    const SubversionResponse response = runSvn(workingDir, args, subversionShortTimeOut, false, codec);
     if (response.error)
         return;
 
     // Re-use an existing view if possible to support
     // the common usage pattern of continuously changing and diffing a file
-    const int lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(file);
+    const QString source = workingDir + QLatin1Char('/') + file;
+    const int lineNumber = VCSBase::VCSBaseEditor::lineNumberOfCurrentEditor(source);
+    const QString id = VCSBase::VCSBaseEditor::getTitleId(workingDir, QStringList(file));
 
-    if (Core::IEditor *editor = locateEditor("annotateFileName", file)) {
+    if (Core::IEditor *editor = locateEditor("annotateFileName", id)) {
         editor->createNew(response.stdOut);
         VCSBase::VCSBaseEditor::gotoLineOfEditor(editor, lineNumber);
         Core::EditorManager::instance()->activateEditor(editor);        
     } else {
-        const QString title = QString::fromLatin1("svn annotate %1").arg(QFileInfo(file).fileName());
-        Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, file, codec);
-        newEditor->setProperty("annotateFileName", file);
+        const QString title = QString::fromLatin1("svn annotate %1").arg(id);
+        Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, source, codec);
+        newEditor->setProperty("annotateFileName", id);
         VCSBase::VCSBaseEditor::gotoLineOfEditor(newEditor, lineNumber);
     }
 }
 
 void SubversionPlugin::projectStatus()
 {
-    if (!m_projectExplorer)
-        return;
-
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasProject(), return);
     QStringList args(QLatin1String("status"));
-    args += currentProjectsTopLevels();
-
-    if (args.size() == 1)
-        return;
-
-    runSvn(args, subversionShortTimeOut, true);
+    args += state.relativeCurrentProject();
+    runSvn(state.currentProjectTopLevel(), args, subversionShortTimeOut, true);
 }
 
 void SubversionPlugin::describe(const QString &source, const QString &changeNr)
@@ -815,8 +767,7 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr)
     QStringList args(QLatin1String("log"));
     args.push_back(QLatin1String("-r"));
     args.push_back(changeNr);
-    args.push_back(topLevel);
-    const SubversionResponse logResponse = runSvn(args, subversionShortTimeOut, false);
+    const SubversionResponse logResponse = runSvn(topLevel, args, subversionShortTimeOut, false);
     if (logResponse.error)
         return;
     description = logResponse.stdOut;
@@ -828,10 +779,9 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr)
     QString diffArg;
     QTextStream(&diffArg) << (number - 1) << ':' << number;
     args.push_back(diffArg);
-    args.push_back(topLevel);
 
     QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(source);
-    const SubversionResponse response = runSvn(args, subversionShortTimeOut, false, codec);
+    const SubversionResponse response = runSvn(topLevel, args, subversionShortTimeOut, false, codec);
     if (response.error)
         return;
     description += response.stdOut;
@@ -843,7 +793,7 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr)
         editor->createNew(description);
         Core::EditorManager::instance()->activateEditor(editor);
     } else {
-        const QString title = QString::fromLatin1("svn describe %1#%2").arg(QFileInfo(source).fileName(), changeNr);
+        const QString title = QString::fromLatin1("svn describe %1#%2").arg(fi.fileName(), changeNr);
         Core::IEditor *newEditor = showOutputInEditor(title, description, VCSBase::DiffOutput, source, codec);
         newEditor->setProperty("describeChange", id);
     }
@@ -851,9 +801,8 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr)
 
 void SubversionPlugin::slotDescribe()
 {
-    const QStringList topLevels = currentProjectsTopLevels();
-    if (topLevels.size() != 1)
-        return;
+    const VCSBase::VCSBasePluginState state = currentState();
+    QTC_ASSERT(state.hasTopLevel(), return);
 
     QInputDialog inputDialog(Core::ICore::instance()->mainWindow());
     inputDialog.setWindowFlags(inputDialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
@@ -865,7 +814,7 @@ void SubversionPlugin::slotDescribe()
         return;
 
     const int revision = inputDialog.intValue();
-    describe(topLevels.front(), QString::number(revision));
+    describe(state.topLevel(), QString::number(revision));
 }
 
 void SubversionPlugin::submitCurrentLog()
@@ -875,17 +824,6 @@ void SubversionPlugin::submitCurrentLog()
         << Core::EditorManager::instance()->currentEditor());
 }
 
-QString SubversionPlugin::currentFileName() const
-{
-    const QString fileName = Core::ICore::instance()->fileManager()->currentFile();
-    if (!fileName.isEmpty()) {
-        const QFileInfo fi(fileName);
-        if (fi.exists())
-            return fi.canonicalFilePath();
-    }
-    return QString();
-}
-
 static inline QString processStdErr(QProcess &proc)
 {
     return QString::fromLocal8Bit(proc.readAllStandardError()).remove(QLatin1Char('\r'));
@@ -898,7 +836,8 @@ static inline QString processStdOut(QProcess &proc, QTextCodec *outputCodec = 0)
     return stdOut.remove(QLatin1Char('\r'));
 }
 
-SubversionResponse SubversionPlugin::runSvn(const QStringList &arguments,
+SubversionResponse SubversionPlugin::runSvn(const QString &workingDir,
+                                            const QStringList &arguments,
                                             int timeOut,
                                             bool showStdOutInOutputWindow,
                                             QTextCodec *outputCodec)
@@ -923,6 +862,8 @@ SubversionResponse SubversionPlugin::runSvn(const QStringList &arguments,
 
     // Run, connect stderr to the output window
     Utils::SynchronousProcess process;
+    if (!workingDir.isEmpty())
+        process.setWorkingDirectory(workingDir);
     process.setTimeout(timeOut);
     process.setStdOutCodec(outputCodec);
 
@@ -1007,24 +948,24 @@ SubversionPlugin *SubversionPlugin::subversionPluginInstance()
     return m_subversionPluginInstance;
 }
 
-bool SubversionPlugin::vcsAdd(const QString &rawFileName)
+bool SubversionPlugin::vcsAdd(const QString &workingDir, const QString &rawFileName)
 {
     const QString file = QDir::toNativeSeparators(rawFileName);
     QStringList args(QLatin1String("add"));
     args.push_back(file);
 
-    const SubversionResponse response = runSvn(args, subversionShortTimeOut, true);
+    const SubversionResponse response = runSvn(workingDir, args, subversionShortTimeOut, true);
     return !response.error;
 }
 
-bool SubversionPlugin::vcsDelete(const QString &rawFileName)
+bool SubversionPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName)
 {
     const QString file = QDir::toNativeSeparators(rawFileName);
 
     QStringList args(QLatin1String("delete"));
     args.push_back(file);
 
-    const SubversionResponse response = runSvn(args, subversionShortTimeOut, true);
+    const SubversionResponse response = runSvn(workingDir, args, subversionShortTimeOut, true);
     return !response.error;
 }
 
diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h
index 0e6450b3ef3f9ccd8449dc1b66ba5563a64baed9..37e54bc488022e4edd75d9e2714d3df7dbbfe90c 100644
--- a/src/plugins/subversion/subversionplugin.h
+++ b/src/plugins/subversion/subversionplugin.h
@@ -33,6 +33,7 @@
 #include "subversionsettings.h"
 
 #include <vcsbase/vcsbaseplugin.h>
+#include <QtCore/QStringList>
 
 QT_BEGIN_NAMESPACE
 class QDir;
@@ -48,10 +49,6 @@ namespace Utils {
     class ParameterAction;
 }
 
-namespace ProjectExplorer {
-    class ProjectExplorerPlugin;
-}
-
 namespace VCSBase {
     class VCSBaseSubmitEditor;
 }
@@ -82,7 +79,7 @@ public:
     bool initialize(const QStringList &arguments, QString *error_message);
     void extensionsInitialized();
 
-    void svnDiff(const QStringList &files, QString diffname = QString());
+    void svnDiff(const QString  &workingDir, const QStringList &files, QString diffname = QString());
 
     SubversionSubmitEditor *openSubversionSubmitEditor(const QString &fileName);
 
@@ -90,8 +87,8 @@ public:
     void setSettings(const SubversionSettings &s);
 
     // IVersionControl
-    bool vcsAdd(const QString &fileName);
-    bool vcsDelete(const QString &fileName);
+    bool vcsAdd(const QString &workingDir, const QString &fileName);
+    bool vcsDelete(const QString &workingDir, const QString &fileName);
     bool managesDirectory(const QString &directory) const;
     QString findTopLevelForDirectory(const QString &directory) const;
 
@@ -112,7 +109,7 @@ private slots:
     void slotDescribe();
     void updateProject();
     void submitCurrentLog();
-    void diffFiles(const QStringList &);
+    void diffCommitFiles(const QStringList &);
 
 protected:
     virtual void updateActions(VCSBase::VCSBasePlugin::ActionState);
@@ -120,18 +117,17 @@ protected:
 
 private:
     inline bool isCommitEditorOpen() const;
-    QString currentFileName() const;
     Core::IEditor * showOutputInEditor(const QString& title, const QString &output,
                                        int editorType, const QString &source,
                                        QTextCodec *codec);
-    SubversionResponse runSvn(const QStringList &arguments, int timeOut,
+    SubversionResponse runSvn(const QString &workingDir,
+                              const QStringList &arguments, int timeOut,
                               bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0);
-    void annotate(const QString &file);
-    void filelog(const QString &file);
+    void annotate(const QString &workingDir, const QString &file);
+    void filelog(const QString &workingDir, const QStringList &file = QStringList());
     bool managesDirectory(const QDir &directory) const;
     QString findTopLevelForDirectoryI(const QString &directory) const;
-    QStringList currentProjectsTopLevels(QString *name = 0) const;
-    void startCommit(const QStringList &files);
+    void startCommit(const QString &workingDir, const QStringList &files = QStringList());
     bool commit(const QString &messageFile, const QStringList &subVersionFileList);
     void cleanCommitMessageFile();
     inline SubversionControl *subVersionControl() const;
@@ -140,20 +136,19 @@ private:
 
     SubversionSettings m_settings;
     QString m_commitMessageFileName;
-
-    ProjectExplorer::ProjectExplorerPlugin *m_projectExplorer;
+    QString m_commitRepository;
 
     Utils::ParameterAction *m_addAction;
     Utils::ParameterAction *m_deleteAction;
     Utils::ParameterAction *m_revertAction;
-    QAction *m_diffProjectAction;
+    Utils::ParameterAction *m_diffProjectAction;
     Utils::ParameterAction *m_diffCurrentAction;
     QAction *m_commitAllAction;
     Utils::ParameterAction *m_commitCurrentAction;
     Utils::ParameterAction *m_filelogCurrentAction;
     Utils::ParameterAction *m_annotateCurrentAction;
-    QAction *m_statusAction;
-    QAction *m_updateProjectAction;
+    Utils::ParameterAction *m_statusProjectAction;
+    Utils::ParameterAction *m_updateProjectAction;
     QAction *m_describeAction;
 
     QAction *m_submitCurrentLogAction;
diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp
index abd4287966a1dffa1504a8d872f1d1a2b90b9f12..a6c39e5de75f0b88a623be00eabef325197e8b2a 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.cpp
+++ b/src/plugins/vcsbase/vcsbaseeditor.cpp
@@ -37,6 +37,7 @@
 #include <coreplugin/uniqueidmanager.h>
 #include <coreplugin/editormanager/editormanager.h>
 #include <coreplugin/ifile.h>
+#include <coreplugin/iversioncontrol.h>
 #include <extensionsystem/pluginmanager.h>
 #include <projectexplorer/editorconfiguration.h>
 #include <projectexplorer/projectexplorer.h>
@@ -595,6 +596,13 @@ QTextCodec *VCSBaseEditor::getCodec(const QString &source)
     return sys;
 }
 
+QTextCodec *VCSBaseEditor::getCodec(const QString &workingDirectory, const QStringList &files)
+{
+    if (files.empty())
+        return getCodec(workingDirectory);
+    return getCodec(workingDirectory + QLatin1Char('/') + files.front());
+}
+
 VCSBaseEditor *VCSBaseEditor::getVcsBaseEditor(const Core::IEditor *editor)
 {
     if (const TextEditor::BaseTextEditorEditable *be = qobject_cast<const TextEditor::BaseTextEditorEditable *>(editor))
@@ -667,4 +675,33 @@ QString VCSBaseEditor::getTitleId(const QString &workingDirectory, const QString
     return fileNames.join(QLatin1String(", "));
 }
 
+// Find the complete file from a diff relative specification.
+QString VCSBaseEditor::findDiffFile(const QString &f, Core::IVersionControl *control /* = 0 */) const
+{
+    // Try the file.
+    const QFileInfo in(f);
+    if (in.isAbsolute())
+        return in.isFile() ? f : QString();
+    if (in.isFile())
+        return in.absoluteFilePath();
+    // Try in source directory
+    if (source().isEmpty())
+        return QString();
+    const QFileInfo sourceInfo(source());
+    const QString sourceDir = sourceInfo.isDir() ? sourceInfo.absoluteFilePath() : sourceInfo.absolutePath();
+    const QFileInfo sourceFileInfo(sourceDir + QLatin1Char('/') + f);
+    if (sourceFileInfo.isFile())
+        return sourceFileInfo.absoluteFilePath();
+    // Try to locate via repository.
+    if (!control)
+        return QString();
+    const QString topLevel = control->findTopLevelForDirectory(sourceDir);
+    if (topLevel.isEmpty())
+        return QString();
+    const QFileInfo topLevelFileInfo(topLevel + QLatin1Char('/') + f);
+    if (topLevelFileInfo.isFile())
+        return topLevelFileInfo.absoluteFilePath();
+    return QString();
+}
+
 } // namespace VCSBase
diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h
index d272a4cba0c94b46fe720beca778dd880fb57c75..732b40c57d7f00413ee18762c86ff48172942383 100644
--- a/src/plugins/vcsbase/vcsbaseeditor.h
+++ b/src/plugins/vcsbase/vcsbaseeditor.h
@@ -42,6 +42,10 @@ class QTextCodec;
 class QTextCursor;
 QT_END_NAMESPACE
 
+namespace Core {
+    class IVersionControl;
+}
+
 namespace VCSBase {
 
 struct VCSBaseEditorPrivate;
@@ -114,6 +118,7 @@ public:
     // The codec should be set on editors displaying diff or annotation
     // output.
     static QTextCodec *getCodec(const QString &source);
+    static QTextCodec *getCodec(const QString &workingDirectory, const QStringList &files);
 
     // Utility to return the editor from the IEditor returned by the editor
     // manager which is a BaseTextEditable.
@@ -164,6 +169,12 @@ private slots:
     void slotDiffBrowse(int);
     void slotDiffCursorPositionChanged();
 
+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 source and
+     * version control. */
+    QString findDiffFile(const QString &f, Core::IVersionControl *control = 0) const;
+
 private:
     // Implement to return a set of change identifiers in
     // annotation mode
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index e1d1d9bb618c0e70ba025efb2fe54d763ae22995..95e5cc1975f2875db4c4803eddbe18567042c77c 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -142,12 +142,12 @@ protected:
     explicit VCSBasePlugin(const QString &submitEditorKind);
 
     void initialize(Core::IVersionControl *vc);
-    Core::IVersionControl *versionControl() const;
 
 public:   
     virtual ~VCSBasePlugin();
 
     const VCSBasePluginState &currentState() const;
+    Core::IVersionControl *versionControl() const;
 
 protected:
     enum ActionState { NoVCSEnabled, OtherVCSEnabled, VCSEnabled };