diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp
index cdb30368fb844dbfa2454c36bd95e3f0550725e1..fe36c0e449276e5c4124575a19bb95c7fee86a16 100644
--- a/src/plugins/clearcase/clearcaseplugin.cpp
+++ b/src/plugins/clearcase/clearcaseplugin.cpp
@@ -1377,7 +1377,6 @@ ClearCaseResponse
     const Utils::SynchronousProcessResponse sp_resp =
             VcsBase::VcsBasePlugin::runVcs(workingDir, executable,
                                            arguments, timeOut,
-                                           VcsBase::VcsBasePlugin::sshPrompt(),
                                            flags, outputCodec);
 
     response.error = sp_resp.result != Utils::SynchronousProcessResponse::Finished;
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index 1371e2418a4ea8c6ea0f0a4869eca41607f02743..f02744c5b96a3446ecb1155b493c105189387e0d 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -1237,7 +1237,7 @@ CvsResponse CvsPlugin::runCvs(const QString &workingDirectory,
     // Run, connect stderr to the output window
     const Utils::SynchronousProcessResponse sp_resp =
             runVcs(workingDirectory, executable, m_settings.addOptions(arguments),
-                   timeOut, VcsBase::VcsBasePlugin::sshPrompt(), flags, outputCodec);
+                   timeOut, flags, outputCodec);
 
     response.result = CvsResponse::OtherError;
     response.stdErr = sp_resp.stdErr;
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 54c7e230213a9f7cae8be05e736b80372309fdfe..c7e5dfeac7dbfdf01cfb8f3b3a980ea9f9552e6e 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -2253,7 +2253,6 @@ VcsBase::Command *GitClient::executeGit(const QString &workingDirectory,
     outputWindow()->appendCommand(workingDirectory, settings()->stringValue(GitSettings::binaryPathKey), arguments);
     VcsBase::Command *command = createCommand(workingDirectory, editor, useOutputToWindow, editorLineNumber);
     command->addJob(arguments, settings()->intValue(GitSettings::timeoutKey));
-    command->setUnixTerminalDisabled(false);
     if (expectChanges)
         command->addFlags(VcsBasePlugin::ExpectRepoChanges);
     command->execute();
@@ -2320,8 +2319,7 @@ Utils::SynchronousProcessResponse GitClient::synchronousGit(const QString &worki
 {
     return VcsBasePlugin::runVcs(workingDirectory, gitBinaryPath(), gitArguments,
                                  settings()->intValue(GitSettings::timeoutKey) * 1000,
-                                 processEnvironment(), VcsBase::VcsBasePlugin::sshPrompt(),
-                                 flags, outputCodec);
+                                 flags, outputCodec, processEnvironment());
 }
 
 bool GitClient::fullySynchronousGit(const QString &workingDirectory,
@@ -2330,10 +2328,11 @@ bool GitClient::fullySynchronousGit(const QString &workingDirectory,
                                     QByteArray* errorText,
                                     unsigned flags) const
 {
-    return VcsBasePlugin::runFullySynchronous(workingDirectory, gitBinaryPath(), gitArguments,
-                                              processEnvironment(), outputText, errorText,
-                                              settings()->intValue(GitSettings::timeoutKey) * 1000,
-                                              flags);
+    VcsBase::Command command(gitBinaryPath(), workingDirectory, processEnvironment());
+    command.addFlags(flags);
+    return command.runFullySynchronous(gitArguments,
+                                       settings()->intValue(GitSettings::timeoutKey) * 1000,
+                                       outputText, errorText);
 }
 
 void GitClient::updateSubmodulesIfNeeded(const QString &workingDirectory, bool prompt)
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index 2a98a4ecb05a56755c356d73f92eaea83d319e2f..eef368c1d8b80cc3d7391e210861f35e409fe2fb 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -146,8 +146,7 @@ bool MercurialClient::synchronousPull(const QString &workingDir, const QString &
     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
     env.insert(QLatin1String("LANGUAGE"), QLatin1String("C"));
     const Utils::SynchronousProcessResponse resp = VcsBase::VcsBasePlugin::runVcs(
-                workingDir, binary, args, timeoutSec * 1000, env,
-                VcsBase::VcsBasePlugin::sshPrompt(), flags);
+                workingDir, binary, args, timeoutSec * 1000, flags, 0, env);
     const bool ok = resp.result == Utils::SynchronousProcessResponse::Finished;
 
     parsePullOutput(resp.stdOut.trimmed());
@@ -276,8 +275,6 @@ void MercurialClient::incoming(const QString &repositoryRoot, const QString &rep
     VcsBase::VcsBaseEditorWidget *editor = createVcsEditor(Constants::DIFFLOG, title, repositoryRoot,
                                                      true, "incoming", id);
     VcsBase::Command *cmd = createCommand(repository, editor);
-    if (!repository.isEmpty() && VcsBase::VcsBasePlugin::isSshPromptConfigured())
-        cmd->setUnixTerminalDisabled(true);
     enqueueJob(cmd, args);
 }
 
@@ -293,7 +290,6 @@ void MercurialClient::outgoing(const QString &repositoryRoot)
                                                      "outgoing", repositoryRoot);
 
     VcsBase::Command *cmd = createCommand(repositoryRoot, editor);
-    cmd->setUnixTerminalDisabled(VcsBase::VcsBasePlugin::isSshPromptConfigured());
     enqueueJob(cmd, args);
 }
 
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index aff1a6e8b277f97b65ae80be4791ba34388b1cdf..4a173e3bf675d4704d8c03885fb6815f40c4c761 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -1120,8 +1120,7 @@ SubversionPlugin::Version SubversionPlugin::svnVersion()
         args << QLatin1String("--version") << QLatin1String("-q");
         const Utils::SynchronousProcessResponse response =
                 VcsBase::VcsBasePlugin::runVcs(QDir().absolutePath(), m_settings.binaryPath(),
-                                               args, m_settings.timeOutMs(),
-                                               VcsBase::VcsBasePlugin::sshPrompt(), 0);
+                                               args, m_settings.timeOutMs());
         if (response.result == Utils::SynchronousProcessResponse::Finished &&
                 response.exitCode == 0) {
             m_svnVersionBinary = m_settings.binaryPath();
@@ -1156,7 +1155,7 @@ SubversionResponse SubversionPlugin::runSvn(const QString &workingDir,
     const QStringList completeArguments = SubversionPlugin::addAuthenticationOptions(arguments, userName, password);
     const Utils::SynchronousProcessResponse sp_resp =
             VcsBase::VcsBasePlugin::runVcs(workingDir, executable, completeArguments, timeOut,
-                                           VcsBase::VcsBasePlugin::sshPrompt(), flags, outputCodec);
+                                           flags, outputCodec);
 
     response.error = sp_resp.result != Utils::SynchronousProcessResponse::Finished;
     if (response.error)
diff --git a/src/plugins/vcsbase/command.cpp b/src/plugins/vcsbase/command.cpp
index a719c44d27bf1b82bd75c47175d2be1d0dddc3c6..42b6ccd6d2571dadd5fbd877d9391a8a984cb9a8 100644
--- a/src/plugins/vcsbase/command.cpp
+++ b/src/plugins/vcsbase/command.cpp
@@ -33,6 +33,7 @@
 #include <coreplugin/icore.h>
 #include <coreplugin/progressmanager/progressmanager.h>
 #include <coreplugin/vcsmanager.h>
+#include <vcsbase/vcsbaseoutputwindow.h>
 #include <utils/synchronousprocess.h>
 #include <utils/runextensions.h>
 
@@ -49,6 +50,8 @@
 
 Q_DECLARE_METATYPE(QVariant)
 
+enum { debugExecution = 0 };
+
 namespace VcsBase {
 namespace Internal {
 
@@ -70,7 +73,6 @@ public:
     const QString m_workingDirectory;
     const QProcessEnvironment m_environment;
     QVariant m_cookie;
-    bool m_unixTerminalDisabled;
     int m_defaultTimeout;
     unsigned m_flags;
     QTextCodec *m_codec;
@@ -88,7 +90,6 @@ CommandPrivate::CommandPrivate(const QString &binary,
     m_binaryPath(binary),
     m_workingDirectory(workingDirectory),
     m_environment(environment),
-    m_unixTerminalDisabled(false),
     m_defaultTimeout(10),
     m_flags(0),
     m_codec(0),
@@ -146,16 +147,6 @@ void Command::setDefaultTimeout(int timeout)
     d->m_defaultTimeout = timeout;
 }
 
-bool Command::unixTerminalDisabled() const
-{
-    return d->m_unixTerminalDisabled;
-}
-
-void Command::setUnixTerminalDisabled(bool e)
-{
-    d->m_unixTerminalDisabled = e;
-}
-
 unsigned Command::flags() const
 {
     return d->m_flags;
@@ -220,12 +211,9 @@ void Command::run(QFutureInterface<void> &future)
     d->m_lastExecSuccess = true;
     for (int j = 0; j < count; j++) {
         const int timeOutSeconds = d->m_jobs.at(j).timeout;
-        Utils::SynchronousProcessResponse resp =
-                VcsBasePlugin::runVcs(d->m_workingDirectory, d->m_binaryPath,
-                                      d->m_jobs.at(j).arguments,
-                                      timeOutSeconds >= 0 ? timeOutSeconds * 1000 : -1,
-                                      d->m_environment, d->m_sshPasswordPrompt,
-                                      d->m_flags, d->m_codec);
+        Utils::SynchronousProcessResponse resp = runVcs(
+                    d->m_jobs.at(j).arguments,
+                    timeOutSeconds >= 0 ? timeOutSeconds * 1000 : -1);
         stdOut += resp.stdOut;
         stdErr += resp.stdErr;
         d->m_lastExecExitCode = resp.exitCode;
@@ -248,6 +236,248 @@ void Command::run(QFutureInterface<void> &future)
     this->deleteLater();
 }
 
+class OutputProxy : public QObject
+{
+    Q_OBJECT
+
+    friend class Command;
+
+public:
+    OutputProxy()
+    {
+        // Users of this class can either be in the GUI thread or in other threads.
+        // Use Qt::AutoConnection to always append in the GUI thread (directly or queued)
+        VcsBase::VcsBaseOutputWindow *outputWindow = VcsBase::VcsBaseOutputWindow::instance();
+        connect(this, SIGNAL(append(QString)), outputWindow, SLOT(append(QString)));
+        connect(this, SIGNAL(appendSilently(QString)), outputWindow, SLOT(appendSilently(QString)));
+        connect(this, SIGNAL(appendError(QString)), outputWindow, SLOT(appendError(QString)));
+        connect(this, SIGNAL(appendCommand(QString,QString,QStringList)),
+                outputWindow, SLOT(appendCommand(QString,QString,QStringList)));
+        connect(this, SIGNAL(appendMessage(QString)), outputWindow, SLOT(appendMessage(QString)));
+    }
+
+signals:
+    void append(const QString &text);
+    void appendSilently(const QString &text);
+    void appendError(const QString &text);
+    void appendCommand(const QString &workingDirectory,
+                       const QString &binary,
+                       const QStringList &args);
+    void appendMessage(const QString &text);
+};
+
+Utils::SynchronousProcessResponse Command::runVcs(const QStringList &arguments, int timeoutMS)
+{
+    Utils::SynchronousProcessResponse response;
+    OutputProxy outputProxy;
+
+    if (d->m_binaryPath.isEmpty()) {
+        response.result = Utils::SynchronousProcessResponse::StartFailed;
+        return response;
+    }
+
+    VcsBase::VcsBaseOutputWindow *outputWindow = VcsBase::VcsBaseOutputWindow::instance();
+
+    if (!(d->m_flags & VcsBasePlugin::SuppressCommandLogging))
+        emit outputProxy.appendCommand(d->m_workingDirectory, d->m_binaryPath, arguments);
+
+    const bool sshPromptConfigured = !d->m_sshPasswordPrompt.isEmpty();
+    if (debugExecution) {
+        QDebug nsp = qDebug().nospace();
+        nsp << "Command::runVcs" << d->m_workingDirectory << d->m_binaryPath << arguments
+                << timeoutMS;
+        if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow)
+            nsp << "stdout";
+        if (d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)
+            nsp << "suppress_stderr";
+        if (d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow)
+            nsp << "suppress_fail_msg";
+        if (d->m_flags & VcsBasePlugin::MergeOutputChannels)
+            nsp << "merge_channels";
+        if (d->m_flags & VcsBasePlugin::SshPasswordPrompt)
+            nsp << "ssh (" << sshPromptConfigured << ')';
+        if (d->m_flags & VcsBasePlugin::SuppressCommandLogging)
+            nsp << "suppress_log";
+        if (d->m_flags & VcsBasePlugin::ForceCLocale)
+            nsp << "c_locale";
+        if (d->m_flags & VcsBasePlugin::FullySynchronously)
+            nsp << "fully_synchronously";
+        if (d->m_flags & VcsBasePlugin::ExpectRepoChanges)
+            nsp << "expect_repo_changes";
+        if (d->m_codec)
+            nsp << " Codec: " << d->m_codec->name();
+    }
+
+    // TODO tell the document manager about expected repository changes
+    //    if (d->m_flags & ExpectRepoChanges)
+    //        Core::DocumentManager::expectDirectoryChange(d->m_workingDirectory);
+    if (d->m_flags & VcsBasePlugin::FullySynchronously) {
+        response = runSynchronous(arguments, timeoutMS);
+    } else {
+        // Run, connect stderr to the output window
+        Utils::SynchronousProcess process;
+        if (!d->m_workingDirectory.isEmpty())
+            process.setWorkingDirectory(d->m_workingDirectory);
+
+        QProcessEnvironment env = d->m_environment;
+        VcsBasePlugin::setProcessEnvironment(&env,
+                                             (d->m_flags & VcsBasePlugin::ForceCLocale),
+                                             d->m_sshPasswordPrompt);
+        process.setProcessEnvironment(env);
+        process.setTimeout(timeoutMS);
+        if (d->m_codec)
+            process.setCodec(d->m_codec);
+
+        // Suppress terminal on UNIX for ssh prompts if it is configured.
+        if (sshPromptConfigured && (d->m_flags & VcsBasePlugin::SshPasswordPrompt))
+            process.setFlags(Utils::SynchronousProcess::UnixTerminalDisabled);
+
+        // connect stderr to the output window if desired
+        if (d->m_flags & VcsBasePlugin::MergeOutputChannels) {
+            process.setProcessChannelMode(QProcess::MergedChannels);
+        } else if (!(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow)) {
+            process.setStdErrBufferedSignalsEnabled(true);
+            connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(appendError(QString)));
+        }
+
+        // connect stdout to the output window if desired
+        if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) {
+            process.setStdOutBufferedSignalsEnabled(true);
+            connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
+        }
+
+        process.setTimeOutMessageBoxEnabled(true);
+
+        // Run!
+        response = process.run(d->m_binaryPath, arguments);
+    }
+
+    // Success/Fail message in appropriate window?
+    if (response.result == Utils::SynchronousProcessResponse::Finished) {
+        if (d->m_flags & VcsBasePlugin::ShowSuccessMessage)
+            emit outputProxy.appendMessage(response.exitMessage(d->m_binaryPath, timeoutMS));
+    } else if (!(d->m_flags & VcsBasePlugin::SuppressFailMessageInLogWindow)) {
+        emit outputProxy.appendError(response.exitMessage(d->m_binaryPath, timeoutMS));
+    }
+    if (d->m_flags & VcsBasePlugin::ExpectRepoChanges) {
+        // TODO tell the document manager that the directory now received all expected changes
+        // Core::DocumentManager::unexpectDirectoryChange(d->m_workingDirectory);
+        Core::ICore::vcsManager()->emitRepositoryChanged(d->m_workingDirectory);
+    }
+
+    return response;
+}
+
+Utils::SynchronousProcessResponse Command::runSynchronous(const QStringList &arguments, int timeoutMS)
+{
+    Utils::SynchronousProcessResponse response;
+
+    // Set up process
+    unsigned processFlags = 0;
+    if (!d->m_sshPasswordPrompt.isEmpty() && (d->m_flags & VcsBasePlugin::SshPasswordPrompt))
+        processFlags |= Utils::SynchronousProcess::UnixTerminalDisabled;
+    QSharedPointer<QProcess> process = Utils::SynchronousProcess::createProcess(processFlags);
+    if (!d->m_workingDirectory.isEmpty())
+        process->setWorkingDirectory(d->m_workingDirectory);
+    QProcessEnvironment env = d->m_environment;
+    VcsBasePlugin::setProcessEnvironment(&env,
+                                         (d->m_flags & VcsBasePlugin::ForceCLocale),
+                                         d->m_sshPasswordPrompt);
+    process->setProcessEnvironment(env);
+    if (d->m_flags & VcsBasePlugin::MergeOutputChannels)
+        process->setProcessChannelMode(QProcess::MergedChannels);
+
+    // Start
+    process->start(d->m_binaryPath, arguments, QIODevice::ReadOnly);
+    process->closeWriteChannel();
+    if (!process->waitForStarted()) {
+        response.result = Utils::SynchronousProcessResponse::StartFailed;
+        return response;
+    }
+
+    // process output
+    QByteArray stdOut;
+    QByteArray stdErr;
+    const bool timedOut =
+            !Utils::SynchronousProcess::readDataFromProcess(*process.data(), timeoutMS,
+                                                            &stdOut, &stdErr, true);
+
+    OutputProxy outputProxy;
+    if (!stdErr.isEmpty()) {
+        response.stdErr = Utils::SynchronousProcess::normalizeNewlines(
+                    d->m_codec ? d->m_codec->toUnicode(stdErr) : QString::fromLocal8Bit(stdErr));
+        if (!(d->m_flags & VcsBasePlugin::SuppressStdErrInLogWindow))
+            emit outputProxy.append(response.stdErr);
+    }
+
+    if (!stdOut.isEmpty()) {
+        response.stdOut = Utils::SynchronousProcess::normalizeNewlines(
+                    d->m_codec ? d->m_codec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut));
+        if (d->m_flags & VcsBasePlugin::ShowStdOutInLogWindow) {
+            if (d->m_flags & VcsBasePlugin::SilentOutput)
+                emit outputProxy.appendSilently(response.stdOut);
+            else
+                emit outputProxy.append(response.stdOut);
+        }
+    }
+
+    // Result
+    if (timedOut) {
+        response.result = Utils::SynchronousProcessResponse::Hang;
+    } else if (process->exitStatus() != QProcess::NormalExit) {
+        response.result = Utils::SynchronousProcessResponse::TerminatedAbnormally;
+    } else {
+        response.result = process->exitCode() == 0 ?
+                          Utils::SynchronousProcessResponse::Finished :
+                          Utils::SynchronousProcessResponse::FinishedError;
+    }
+    return response;
+}
+
+bool Command::runFullySynchronous(const QStringList &arguments, int timeoutMS,
+                                  QByteArray *outputData, QByteArray *errorData)
+{
+    if (d->m_binaryPath.isEmpty())
+        return false;
+
+    OutputProxy outputProxy;
+    if (!(d->m_flags & VcsBasePlugin::SuppressCommandLogging))
+        emit outputProxy.appendCommand(d->m_workingDirectory, d->m_binaryPath, arguments);
+
+    // TODO tell the document manager about expected repository changes
+    // if (d->m_flags & ExpectRepoChanges)
+    //    Core::DocumentManager::expectDirectoryChange(workingDirectory);
+    QProcess process;
+    process.setWorkingDirectory(d->m_workingDirectory);
+    process.setProcessEnvironment(d->m_environment);
+
+    process.start(d->m_binaryPath, arguments);
+    process.closeWriteChannel();
+    if (!process.waitForStarted()) {
+        if (errorData) {
+            const QString msg = QString::fromLatin1("Unable to execute '%1': %2:")
+                                .arg(d->m_binaryPath, process.errorString());
+            *errorData = msg.toLocal8Bit();
+        }
+        return false;
+    }
+
+    if (!Utils::SynchronousProcess::readDataFromProcess(process, timeoutMS, outputData, errorData, true)) {
+        if (errorData)
+            errorData->append(tr("Error: Executable timed out after %1s.").arg(timeoutMS / 1000).toLocal8Bit());
+        Utils::SynchronousProcess::stopProcess(process);
+        return false;
+    }
+
+    if (d->m_flags & VcsBasePlugin::ExpectRepoChanges) {
+        // TODO tell the document manager that the directory now received all expected changes
+        // Core::DocumentManager::unexpectDirectoryChange(workingDirectory);
+        Core::ICore::vcsManager()->emitRepositoryChanged(d->m_workingDirectory);
+    }
+
+    return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
+}
+
 const QVariant &Command::cookie() const
 {
     return d->m_cookie;
@@ -269,3 +499,5 @@ void Command::setCodec(QTextCodec *codec)
 }
 
 } // namespace VcsBase
+
+#include "command.moc"
diff --git a/src/plugins/vcsbase/command.h b/src/plugins/vcsbase/command.h
index 32a2bee5f7af474704bdcfa3b698432840feb39d..84b4d7c398cd0e1881691479e0f8ee4818163ef1 100644
--- a/src/plugins/vcsbase/command.h
+++ b/src/plugins/vcsbase/command.h
@@ -32,6 +32,8 @@
 
 #include "vcsbase_global.h"
 
+#include <utils/synchronousprocess.h>
+
 #include <QObject>
 
 QT_BEGIN_NAMESPACE
@@ -69,10 +71,6 @@ public:
     int defaultTimeout() const;
     void setDefaultTimeout(int timeout);
 
-    // Disable Terminal on UNIX (see VCS SSH handling)
-    bool unixTerminalDisabled() const;
-    void setUnixTerminalDisabled(bool);
-
     unsigned flags() const;
     void addFlags(unsigned f);
 
@@ -82,8 +80,15 @@ public:
     QTextCodec *codec() const;
     void setCodec(QTextCodec *codec);
 
+
+    Utils::SynchronousProcessResponse runVcs(const QStringList &arguments, int timeoutMS);
+    // Make sure to not pass through the event loop at all:
+    bool runFullySynchronous(const QStringList &arguments, int timeoutMS,
+                             QByteArray *outputData, QByteArray *errorData);
+
 private:
     void run(QFutureInterface<void> &future);
+    Utils::SynchronousProcessResponse runSynchronous(const QStringList &arguments, int timeoutMS);
 
 signals:
     void output(const QString &);
diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp
index 0b3a4a28e623204d69e91b8e1085791223851b20..a35aeafdc3fa14fe76ec2bcf084069f340861b8e 100644
--- a/src/plugins/vcsbase/vcsbaseclient.cpp
+++ b/src/plugins/vcsbase/vcsbaseclient.cpp
@@ -319,7 +319,7 @@ Utils::SynchronousProcessResponse VcsBaseClient::vcsSynchronousExec(
     const QString binary = settings()->binaryPath();
     const int timeoutSec = settings()->intValue(VcsBaseClientSettings::timeoutKey);
     return VcsBase::VcsBasePlugin::runVcs(workingDirectory, binary, args, timeoutSec * 1000,
-                                          VcsBase::VcsBasePlugin::sshPrompt(), flags, outputCodec);
+                                          flags, outputCodec);
 }
 
 void VcsBaseClient::annotate(const QString &workingDir, const QString &file,
@@ -492,7 +492,6 @@ void VcsBaseClient::update(const QString &repositoryRoot, const QString &revisio
     args << revisionSpec(revision) << extraOptions;
     Command *cmd = createCommand(repositoryRoot);
     cmd->setCookie(repositoryRoot);
-    cmd->setUnixTerminalDisabled(VcsBase::VcsBasePlugin::isSshPromptConfigured());
     connect(cmd, SIGNAL(success(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection);
     enqueueJob(cmd, args);
 }
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index a33c054f3c89062d8dc16725249ccf837516dad5..0b1247e8923bcda6e2f70c19b6c760db5b559a0d 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -33,6 +33,7 @@
 #include "commonvcssettings.h"
 #include "vcsbaseoutputwindow.h"
 #include "corelistener.h"
+#include "command.h"
 
 #include <coreplugin/documentmanager.h>
 #include <coreplugin/icore.h>
@@ -59,7 +60,7 @@
 
 using namespace Utils;
 
-enum { debug = 0, debugRepositorySearch = 0, debugExecution = 0 };
+enum { debug = 0, debugRepositorySearch = 0 };
 
 /*!
     \namespace VcsBase
@@ -468,36 +469,6 @@ VCSBASE_EXPORT QDebug operator<<(QDebug in, const VcsBasePluginState &state)
     return in;
 }
 
-class OutputProxy : public QObject
-{
-    Q_OBJECT
-
-    friend class VcsBasePlugin;
-
-public:
-    OutputProxy()
-    {
-        // Users of this class can either be in the GUI thread or in other threads.
-        // Use Qt::AutoConnection to always append in the GUI thread (directly or queued)
-        VcsBase::VcsBaseOutputWindow *outputWindow = VcsBase::VcsBaseOutputWindow::instance();
-        connect(this, SIGNAL(append(QString)), outputWindow, SLOT(append(QString)));
-        connect(this, SIGNAL(appendSilently(QString)), outputWindow, SLOT(appendSilently(QString)));
-        connect(this, SIGNAL(appendError(QString)), outputWindow, SLOT(appendError(QString)));
-        connect(this, SIGNAL(appendCommand(QString,QString,QStringList)),
-                outputWindow, SLOT(appendCommand(QString,QString,QStringList)));
-        connect(this, SIGNAL(appendMessage(QString)), outputWindow, SLOT(appendMessage(QString)));
-    }
-
-signals:
-    void append(const QString &text);
-    void appendSilently(const QString &text);
-    void appendError(const QString &text);
-    void appendCommand(const QString &workingDirectory,
-                       const QString &binary,
-                       const QStringList &args);
-    void appendMessage(const QString &text);
-};
-
 /*!
     \class VcsBase::VcsBasePlugin
 
@@ -838,11 +809,6 @@ bool VcsBasePlugin::isSshPromptConfigured()
     return !sshPrompt().isEmpty();
 }
 
-void VcsBasePlugin::setProcessEnvironment(QProcessEnvironment *e, bool forceCLocale)
-{
-    setProcessEnvironment(e, forceCLocale, sshPrompt());
-}
-
 void VcsBasePlugin::setProcessEnvironment(QProcessEnvironment *e,
                                           bool forceCLocale,
                                           const QString &sshPromptBinary)
@@ -853,254 +819,21 @@ void VcsBasePlugin::setProcessEnvironment(QProcessEnvironment *e,
         e->insert(QLatin1String("SSH_ASKPASS"), sshPromptBinary);
 }
 
-// Run a process fully synchronously, returning Utils::SynchronousProcessResponse
+// Run a process synchronously, returning Utils::SynchronousProcessResponse
 // response struct and using the VcsBasePlugin flags as applicable
-SynchronousProcessResponse VcsBasePlugin::runVcsFullySynchronously(
-                              const QString &workingDir,
-                              const QString &binary,
-                              const QStringList &arguments,
-                              int timeOutMS,
-                              QProcessEnvironment env,
-                              const QString &sshPasswordPrompt,
-                              unsigned flags,
-                              QTextCodec *outputCodec)
-{
-    SynchronousProcessResponse response;
-    if (binary.isEmpty()) {
-        response.result = SynchronousProcessResponse::StartFailed;
-        return response;
-    }
-
-    // Set up process
-    unsigned processFlags = 0;
-    if (!sshPasswordPrompt.isEmpty() && (flags & VcsBasePlugin::SshPasswordPrompt))
-        processFlags |= SynchronousProcess::UnixTerminalDisabled;
-    QSharedPointer<QProcess> process = SynchronousProcess::createProcess(processFlags);
-    if (!workingDir.isEmpty())
-        process->setWorkingDirectory(workingDir);
-    process->setProcessEnvironment(env);
-    if (flags & VcsBasePlugin::MergeOutputChannels)
-        process->setProcessChannelMode(QProcess::MergedChannels);
-
-    // Start
-    process->start(binary, arguments, QIODevice::ReadOnly);
-    process->closeWriteChannel();
-    if (!process->waitForStarted()) {
-        response.result = SynchronousProcessResponse::StartFailed;
-        return response;
-    }
-
-    // process output
-    QByteArray stdOut;
-    QByteArray stdErr;
-    const bool timedOut =
-            !SynchronousProcess::readDataFromProcess(*process.data(), timeOutMS,
-                                                            &stdOut, &stdErr, true);
-
-    OutputProxy output;
-    if (!stdErr.isEmpty()) {
-        response.stdErr = Utils::SynchronousProcess::normalizeNewlines(
-                    outputCodec ? outputCodec->toUnicode(stdErr) : QString::fromLocal8Bit(stdErr));
-        if (!(flags & VcsBasePlugin::SuppressStdErrInLogWindow))
-            emit output.append(response.stdErr);
-    }
-
-    if (!stdOut.isEmpty()) {
-        response.stdOut = Utils::SynchronousProcess::normalizeNewlines(
-                    outputCodec ? outputCodec->toUnicode(stdOut) : QString::fromLocal8Bit(stdOut));
-        if (flags & VcsBasePlugin::ShowStdOutInLogWindow) {
-            if (flags & VcsBasePlugin::SilentOutput)
-                emit output.appendSilently(response.stdOut);
-            else
-                emit output.append(response.stdOut);
-        }
-    }
-
-    // Result
-    if (timedOut) {
-        response.result = SynchronousProcessResponse::Hang;
-    } else if (process->exitStatus() != QProcess::NormalExit) {
-        response.result = SynchronousProcessResponse::TerminatedAbnormally;
-    } else {
-        response.result = process->exitCode() == 0 ?
-                          SynchronousProcessResponse::Finished :
-                          SynchronousProcessResponse::FinishedError;
-    }
-    return response;
-}
-
-
-SynchronousProcessResponse VcsBasePlugin::runVcs(const QString &workingDir,
-                      const QString &binary,
-                      const QStringList &arguments,
-                      int timeOutMS,
-                      const QString &sshPasswordPrompt,
-                      unsigned flags,
-                      QTextCodec *outputCodec)
-{
-    const QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
-    return runVcs(workingDir, binary, arguments, timeOutMS, env,
-                  sshPasswordPrompt, flags, outputCodec);
-}
-
 SynchronousProcessResponse VcsBasePlugin::runVcs(const QString &workingDir,
                                                  const QString &binary,
                                                  const QStringList &arguments,
                                                  int timeOutMS,
-                                                 QProcessEnvironment env,
-                                                 const QString &sshPasswordPrompt,
                                                  unsigned flags,
-                                                 QTextCodec *outputCodec)
-{
-    SynchronousProcessResponse response;
-    OutputProxy output;
-
-    if (binary.isEmpty()) {
-        response.result = SynchronousProcessResponse::StartFailed;
-        return response;
-    }
-
-    VcsBase::VcsBaseOutputWindow *outputWindow = VcsBase::VcsBaseOutputWindow::instance();
-
-    if (!(flags & SuppressCommandLogging))
-        emit output.appendCommand(workingDir, binary, arguments);
-
-    const bool sshPromptConfigured = !sshPasswordPrompt.isEmpty();
-    if (debugExecution) {
-        QDebug nsp = qDebug().nospace();
-        nsp << "VcsBasePlugin::runVcs" << workingDir << binary << arguments
-                << timeOutMS;
-        if (flags & ShowStdOutInLogWindow)
-            nsp << "stdout";
-        if (flags & SuppressStdErrInLogWindow)
-            nsp << "suppress_stderr";
-        if (flags & SuppressFailMessageInLogWindow)
-            nsp << "suppress_fail_msg";
-        if (flags & MergeOutputChannels)
-            nsp << "merge_channels";
-        if (flags & SshPasswordPrompt)
-            nsp << "ssh (" << sshPromptConfigured << ')';
-        if (flags & SuppressCommandLogging)
-            nsp << "suppress_log";
-        if (flags & ForceCLocale)
-            nsp << "c_locale";
-        if (flags & FullySynchronously)
-            nsp << "fully_synchronously";
-        if (flags & ExpectRepoChanges)
-            nsp << "expect_repo_changes";
-        if (outputCodec)
-            nsp << " Codec: " << outputCodec->name();
-    }
-
-    setProcessEnvironment(&env, (flags & ForceCLocale), sshPasswordPrompt);
-
-    // TODO tell the document manager about expected repository changes
-    //    if (flags & ExpectRepoChanges)
-    //        Core::DocumentManager::expectDirectoryChange(workingDir);
-    if (flags & FullySynchronously) {
-        response = runVcsFullySynchronously(workingDir, binary, arguments, timeOutMS,
-                                            env, sshPasswordPrompt, flags, outputCodec);
-    } else {
-        // Run, connect stderr to the output window
-        SynchronousProcess process;
-        if (!workingDir.isEmpty())
-            process.setWorkingDirectory(workingDir);
-
-        process.setProcessEnvironment(env);
-        process.setTimeout(timeOutMS);
-        if (outputCodec)
-            process.setCodec(outputCodec);
-
-        // Suppress terminal on UNIX for ssh prompts if it is configured.
-        if (sshPromptConfigured && (flags & SshPasswordPrompt))
-            process.setFlags(SynchronousProcess::UnixTerminalDisabled);
-
-        // connect stderr to the output window if desired
-        if (flags & MergeOutputChannels) {
-            process.setProcessChannelMode(QProcess::MergedChannels);
-        } else {
-            if (!(flags & SuppressStdErrInLogWindow)) {
-                process.setStdErrBufferedSignalsEnabled(true);
-                connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
-            }
-        }
-
-        // connect stdout to the output window if desired
-        if (flags & ShowStdOutInLogWindow) {
-            process.setStdOutBufferedSignalsEnabled(true);
-            connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
-        }
-
-        process.setTimeOutMessageBoxEnabled(true);
-
-        // Run!
-        response = process.run(binary, arguments);
-    }
-
-    // Success/Fail message in appropriate window?
-    if (response.result == SynchronousProcessResponse::Finished) {
-        if (flags & ShowSuccessMessage)
-            emit output.appendMessage(response.exitMessage(binary, timeOutMS));
-    } else if (!(flags & SuppressFailMessageInLogWindow)) {
-        emit output.appendError(response.exitMessage(binary, timeOutMS));
-    }
-    if (flags & ExpectRepoChanges) {
-        // TODO tell the document manager that the directory now received all expected changes
-        // Core::DocumentManager::unexpectDirectoryChange(workingDir);
-        Core::ICore::vcsManager()->emitRepositoryChanged(workingDir);
-    }
-
-    return response;
-}
-
-bool VcsBasePlugin::runFullySynchronous(const QString &workingDirectory,
-                                        const QString &binary,
-                                        const QStringList &arguments,
-                                        const QProcessEnvironment &env,
-                                        QByteArray* outputText,
-                                        QByteArray* errorText,
-                                        int timeoutMS,
-                                        unsigned flags)
-{
-    if (binary.isEmpty())
-        return false;
-
-    OutputProxy output;
-    if (!(flags & SuppressCommandLogging))
-        emit output.appendCommand(workingDirectory, binary, arguments);
-
-    // TODO tell the document manager about expected repository changes
-    // if (flags & ExpectRepoChanges)
-    //    Core::DocumentManager::expectDirectoryChange(workingDirectory);
-    QProcess process;
-    process.setWorkingDirectory(workingDirectory);
-    process.setProcessEnvironment(env);
-
-    process.start(binary, arguments);
-    process.closeWriteChannel();
-    if (!process.waitForStarted()) {
-        if (errorText) {
-            const QString msg = QString::fromLatin1("Unable to execute '%1': %2:")
-                                .arg(binary, process.errorString());
-            *errorText = msg.toLocal8Bit();
-        }
-        return false;
-    }
-
-    if (!SynchronousProcess::readDataFromProcess(process, timeoutMS, outputText, errorText, true)) {
-        if (errorText)
-            errorText->append(tr("Error: Executable timed out after %1s.").arg(timeoutMS / 1000).toLocal8Bit());
-        SynchronousProcess::stopProcess(process);
-        return false;
-    }
-
-    if (flags & ExpectRepoChanges) {
-        // TODO tell the document manager that the directory now received all expected changes
-        // Core::DocumentManager::unexpectDirectoryChange(workingDirectory);
-        Core::ICore::vcsManager()->emitRepositoryChanged(workingDirectory);
-    }
-
-    return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
+                                                 QTextCodec *outputCodec,
+                                                 const QProcessEnvironment &env)
+{
+    Command command(binary, workingDir,
+                    env.isEmpty() ? QProcessEnvironment::systemEnvironment() : env);
+    command.addFlags(flags);
+    command.setCodec(outputCodec);
+    return command.runVcs(arguments, timeOutMS);
 }
 
 bool VcsBasePlugin::runPatch(const QByteArray &input, const QString &workingDirectory,
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index 5df80930eea32e22792218518c64fc127ce4fe05..5799f8bf991a2ac612853a0ac9b115306f4304f3 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -36,10 +36,10 @@
 
 #include <QSharedDataPointer>
 #include <QList>
+#include <QProcessEnvironment>
 
 QT_BEGIN_NAMESPACE
 class QAction;
-class QProcessEnvironment;
 class QTextCodec;
 QT_END_NAMESPACE
 
@@ -150,7 +150,9 @@ public:
     // Sets up SSH graphical password prompting (note that the latter
     // requires a terminal-less process) and sets LANG to 'C' to force English
     // (suppress LOCALE warnings/parse commands output) if desired.
-    static void setProcessEnvironment(QProcessEnvironment *e, bool forceCLocale);
+    static void setProcessEnvironment(QProcessEnvironment *e,
+                                      bool forceCLocale,
+                                      const QString &sshPasswordPrompt = sshPrompt());
     // Returns SSH prompt configured in settings.
     static QString sshPrompt();
     // Returns whether an SSH prompt is configured.
@@ -176,28 +178,9 @@ public:
                                                     const QString &binary,
                                                     const QStringList &arguments,
                                                     int timeOutMS,
-                                                    QProcessEnvironment env,
-                                                    const QString &sshPasswordPrompt,
                                                     unsigned flags = 0,
-                                                    QTextCodec *outputCodec = 0);
-
-    static Utils::SynchronousProcessResponse runVcs(const QString &workingDir,
-                                                    const QString &binary,
-                                                    const QStringList &arguments,
-                                                    int timeOutMS,
-                                                    const QString &sshPasswordPrompt,
-                                                    unsigned flags = 0,
-                                                    QTextCodec *outputCodec = 0);
-
-    // Make sure to not pass through the event loop at all:
-    static bool runFullySynchronous(const QString &workingDirectory,
-                                    const QString &binary,
-                                    const QStringList &arguments,
-                                    const QProcessEnvironment &env,
-                                    QByteArray* outputText,
-                                    QByteArray *errorText,
-                                    int timeoutMS,
-                                    unsigned flags);
+                                                    QTextCodec *outputCodec = 0,
+                                                    const QProcessEnvironment &env = QProcessEnvironment());
 
     // Utility to run the 'patch' command
     static bool runPatch(const QByteArray &input, const QString &workingDirectory = QString(),
@@ -245,20 +228,6 @@ private slots:
     void slotTestRemoveSnapshot();
 
 private:
-    static void setProcessEnvironment(QProcessEnvironment *e,
-                                      bool forceCLocale,
-                                      const QString &sshPasswordPrompt);
-
-    static Utils::SynchronousProcessResponse runVcsFullySynchronously(
-            const QString &workingDir,
-            const QString &binary,
-            const QStringList &arguments,
-            int timeOutMS,
-            QProcessEnvironment env,
-            const QString &sshPasswordPrompt,
-            unsigned flags,
-            QTextCodec *outputCodec = 0);
-
     VcsBasePluginPrivate *d;
 };