diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp
index b7f0f461fb0467b3aa040080768eabecd5baf410..ce449df8e16a2c8e1ca5ed86a56909776ceff8e2 100644
--- a/src/plugins/cvs/cvsplugin.cpp
+++ b/src/plugins/cvs/cvsplugin.cpp
@@ -473,7 +473,8 @@ void CVSPlugin::cvsDiff(const QString &workingDir, const QStringList &files)
 
     // CVS returns the diff exit code (1 if files differ), which is
     // undistinguishable from a "file not found" error, unfortunately.
-    const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, codec);
+    const CVSResponse response =
+            runCVS(workingDir, args, m_settings.timeOutMS(), 0, codec);
     switch (response.result) {
     case CVSResponse::NonNullExitCode:
     case CVSResponse::Ok:
@@ -560,7 +561,9 @@ void CVSPlugin::revertAll()
         return;
     QStringList args;
     args << QLatin1String("update") << QLatin1String("-C") << state.topLevel();
-    const CVSResponse revertResponse = runCVS(state.topLevel(), args, m_settings.timeOutMS(), true);
+    const CVSResponse revertResponse =
+            runCVS(state.topLevel(), args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     if (revertResponse.result == CVSResponse::Ok) {
         cvsVersionControl()->emitRepositoryChanged(state.topLevel());
     } else {
@@ -574,7 +577,8 @@ void CVSPlugin::revertCurrentFile()
     QTC_ASSERT(state.hasFile(), return)
     QStringList args;
     args << QLatin1String("diff") << state.relativeCurrentFile();
-    const CVSResponse diffResponse = runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(), false);
+    const CVSResponse diffResponse =
+            runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(), 0);
     switch (diffResponse.result) {
     case CVSResponse::Ok:
         return; // Not modified, diff exit code 0
@@ -595,7 +599,9 @@ void CVSPlugin::revertCurrentFile()
     // revert
     args.clear();
     args << QLatin1String("update") << QLatin1String("-C") << state.relativeCurrentFile();
-    const CVSResponse revertResponse = runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(), true);
+    const CVSResponse revertResponse =
+            runCVS(state.currentFileTopLevel(), args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     if (revertResponse.result == CVSResponse::Ok) {
         cvsVersionControl()->emitFilesChanged(QStringList(state.currentFile()));
     }
@@ -644,7 +650,8 @@ void CVSPlugin::startCommit(const QString &workingDir, const QStringList &files)
     // We need the "Examining <subdir>" stderr output to tell
     // where we are, so, have stdout/stderr channels merged.
     QStringList args = QStringList(QLatin1String("status"));
-    const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, 0, true);
+    const CVSResponse response =
+            runCVS(workingDir, args, m_settings.timeOutMS(), MergeOutputChannels);
     if (response.result != CVSResponse::Ok)
         return;
     // Get list of added/modified/deleted files and purge out undesired ones
@@ -693,7 +700,9 @@ bool CVSPlugin::commit(const QString &messageFile,
     QStringList args = QStringList(QLatin1String("commit"));
     args << QLatin1String("-F") << messageFile;
     args.append(fileList);
-    const CVSResponse response = runCVS(m_commitRepository, args, m_settings.longTimeOutMS(), true);
+    const CVSResponse response =
+            runCVS(m_commitRepository, args, m_settings.longTimeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     return response.result == CVSResponse::Ok ;
 }
 
@@ -729,7 +738,9 @@ void CVSPlugin::filelog(const QString &workingDir,
     QStringList args;
     args << QLatin1String("log");
     args.append(files);
-    const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, codec);
+    const CVSResponse response =
+            runCVS(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt, codec);
     if (response.result != CVSResponse::Ok)
         return;
 
@@ -755,7 +766,9 @@ void CVSPlugin::updateProject()
    QStringList args(QLatin1String("update"));
    args.push_back(QLatin1String("-dR"));
    args.append(state.relativeCurrentProject());
-   const CVSResponse response = runCVS(state.currentProjectTopLevel(), args, m_settings.longTimeOutMS(), true);
+   const CVSResponse response =
+           runCVS(state.currentProjectTopLevel(), args, m_settings.longTimeOutMS(),
+                  SshPasswordPrompt|ShowStdOutInLogWindow);
    if (response.result == CVSResponse::Ok)
        cvsVersionControl()->emitRepositoryChanged(state.currentProjectTopLevel());
 }
@@ -786,7 +799,9 @@ void CVSPlugin::annotate(const QString &workingDir, const QString &file,
     if (!revision.isEmpty())
         args << QLatin1String("-r") << revision;
     args << file;
-    const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), false, codec);
+    const CVSResponse response =
+            runCVS(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt, codec);
     if (response.result != CVSResponse::Ok)
         return;
 
@@ -813,7 +828,8 @@ void CVSPlugin::projectStatus()
     QTC_ASSERT(state.hasProject(), return)
     QStringList args;
     args << QLatin1String("status") << state.relativeCurrentProject();
-    const CVSResponse response = runCVS(state.currentProjectTopLevel(), args, m_settings.timeOutMS(), false);
+    const CVSResponse response =
+            runCVS(state.currentProjectTopLevel(), args, m_settings.timeOutMS(), 0);
     if (response.result == CVSResponse::Ok)
         showOutputInEditor(tr("Project status"), response.stdOut, VCSBase::RegularCommandOutput, state.currentProjectTopLevel(), 0);
 }
@@ -857,7 +873,8 @@ bool CVSPlugin::describe(const QString &toplevel, const QString &file, const
     // Run log to obtain commit id and details
     QStringList args;
     args << QLatin1String("log") << (QLatin1String("-r") + changeNr) << file;
-    const CVSResponse logResponse = runCVS(toplevel, args, m_settings.timeOutMS(), false);
+    const CVSResponse logResponse =
+            runCVS(toplevel, args, m_settings.timeOutMS(), SshPasswordPrompt);
     if (logResponse.result != CVSResponse::Ok) {
         *errorMessage = logResponse.message;
         return false;
@@ -878,7 +895,8 @@ bool CVSPlugin::describe(const QString &toplevel, const QString &file, const
         args.clear();
         args << QLatin1String("log") << QLatin1String("-d") << (dateS  + QLatin1Char('<') + nextDayS);
 
-        const CVSResponse repoLogResponse = runCVS(toplevel, args, m_settings.longTimeOutMS(), false);
+        const CVSResponse repoLogResponse =
+                runCVS(toplevel, args, m_settings.longTimeOutMS(), SshPasswordPrompt);
         if (repoLogResponse.result != CVSResponse::Ok) {
             *errorMessage = repoLogResponse.message;
             return false;
@@ -914,7 +932,8 @@ bool CVSPlugin::describe(const QString &repositoryPath,
         // Run log
         QStringList args(QLatin1String("log"));
         args << (QLatin1String("-r") + it->revisions.front().revision) << it->file;
-        const CVSResponse logResponse = runCVS(repositoryPath, args, m_settings.timeOutMS(), false);
+        const CVSResponse logResponse =
+                runCVS(repositoryPath, args, m_settings.timeOutMS(), SshPasswordPrompt);
         if (logResponse.result != CVSResponse::Ok) {
             *errorMessage =  logResponse.message;
             return false;
@@ -930,7 +949,8 @@ bool CVSPlugin::describe(const QString &repositoryPath,
             args << m_settings.cvsDiffOptions << QLatin1String("-r") << previousRev
                     << QLatin1String("-r") << it->revisions.front().revision
                     << it->file;
-            const CVSResponse diffResponse = runCVS(repositoryPath, args, m_settings.timeOutMS(), false, codec);
+            const CVSResponse diffResponse =
+                    runCVS(repositoryPath, args, m_settings.timeOutMS(), 0, codec);
             switch (diffResponse.result) {
             case CVSResponse::Ok:
             case CVSResponse::NonNullExitCode: // Diff exit code != 0
@@ -970,29 +990,13 @@ void CVSPlugin::submitCurrentLog()
         << Core::EditorManager::instance()->currentEditor());
 }
 
-static inline QString processStdErr(QProcess &proc)
-{
-    return QString::fromLocal8Bit(proc.readAllStandardError()).remove(QLatin1Char('\r'));
-}
-
-// Format log entry for command
-static inline QString msgExecutionLogEntry(const QString &workingDir, const QString &executable, const QStringList &arguments)
-{
-    //: Executing: <executable> <arguments>
-    const QString args = arguments.join(QString(QLatin1Char(' ')));
-    if (workingDir.isEmpty())
-        return CVSPlugin::tr("Executing: %1 %2\n").arg(executable, args);
-    return CVSPlugin::tr("Executing in %1: %2 %3\n").
-            arg(QDir::toNativeSeparators(workingDir), executable, args);
-}
-
 // Run CVS. At this point, file arguments must be relative to
 // the working directory (see above).
 CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
                               const QStringList &arguments,
                               int timeOut,
-                              bool showStdOutInOutputWindow, QTextCodec *outputCodec,
-                              bool mergeStderr)
+                              unsigned flags,
+                              QTextCodec *outputCodec)
 {
     const QString executable = m_settings.cvsCommand;
     CVSResponse response;
@@ -1001,37 +1005,12 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
         response.message =tr("No cvs executable specified!");
         return response;
     }
-    // Fix files and compile complete arguments
-    const QStringList allArgs = m_settings.addOptions(arguments);
-
-    const QString outputText = msgExecutionLogEntry(workingDirectory, executable, allArgs);
-    VCSBase::VCSBaseOutputWindow::instance()->appendCommand(outputText);
-
-    if (CVS::Constants::debug)
-        qDebug() << "runCVS" << timeOut << outputText;
-
     // Run, connect stderr to the output window
-    Utils::SynchronousProcess process;
-    if (!workingDirectory.isEmpty())
-        process.setWorkingDirectory(workingDirectory);
-
-    if (mergeStderr)
-        process.setProcessChannelMode(QProcess::MergedChannels);
-
-    process.setTimeout(timeOut);
-    process.setStdOutCodec(outputCodec);
+    const Utils::SynchronousProcessResponse sp_resp =
+            runVCS(workingDirectory, executable,
+                   m_settings.addOptions(arguments),
+                   timeOut, flags, outputCodec);
 
-    process.setStdErrBufferedSignalsEnabled(true);
-    VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
-    connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
-
-    // connect stdout to the output window if desired
-    if (showStdOutInOutputWindow) {
-        process.setStdOutBufferedSignalsEnabled(true);
-        connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
-    }
-
-    const Utils::SynchronousProcessResponse sp_resp = process.run(executable, allArgs);
     response.result = CVSResponse::OtherError;
     response.stdErr = sp_resp.stdErr;
     response.stdOut = sp_resp.stdOut;
@@ -1041,20 +1020,15 @@ CVSResponse CVSPlugin::runCVS(const QString &workingDirectory,
         break;
     case Utils::SynchronousProcessResponse::FinishedError:
         response.result = CVSResponse::NonNullExitCode;
-        response.message = tr("The process terminated with exit code %1.").arg(sp_resp.exitCode);
         break;
     case Utils::SynchronousProcessResponse::TerminatedAbnormally:
-        response.message = tr("The process terminated abnormally.");
-        break;
     case Utils::SynchronousProcessResponse::StartFailed:
-        response.message = tr("Could not start cvs '%1'. Please check your settings in the preferences.").arg(executable);
-        break;
     case Utils::SynchronousProcessResponse::Hang:
-        response.message = tr("CVS did not respond within timeout limit (%1 ms).").arg(timeOut);
         break;
     }
+
     if (response.result != CVSResponse::Ok)
-        VCSBase::VCSBaseOutputWindow::instance()->appendError(response.message);
+        response.message = sp_resp.exitMessage(executable, timeOut);
 
     return response;
 }
@@ -1110,7 +1084,9 @@ bool CVSPlugin::vcsAdd(const QString &workingDir, const QString &rawFileName)
 {
     QStringList args;
     args << QLatin1String("add") << rawFileName;
-    const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), true);
+    const CVSResponse response =
+            runCVS(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     return response.result == CVSResponse::Ok;
 }
 
@@ -1118,7 +1094,9 @@ bool CVSPlugin::vcsDelete(const QString &workingDir, const QString &rawFileName)
 {
     QStringList args;
     args << QLatin1String("remove") << QLatin1String("-f") << rawFileName;
-    const CVSResponse response = runCVS(workingDir, args, m_settings.timeOutMS(), true);
+    const CVSResponse response =
+            runCVS(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     return response.result == CVSResponse::Ok;
 }
 
diff --git a/src/plugins/cvs/cvsplugin.h b/src/plugins/cvs/cvsplugin.h
index c95cb8369f9dc453be65a68ed1c858ddc992fbff..c1516595510c99d85fe51f0b4a27cf6aee260289 100644
--- a/src/plugins/cvs/cvsplugin.h
+++ b/src/plugins/cvs/cvsplugin.h
@@ -133,8 +133,7 @@ private:
     CVSResponse runCVS(const QString &workingDirectory,
                        const QStringList &arguments,
                        int timeOut,
-                       bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0,
-                       bool mergeStderr = false);
+                       unsigned flags, QTextCodec *outputCodec = 0);
 
     void annotate(const QString &workingDir, const QString &file,
                   const QString &revision = QString(), int lineNumber= -1);
diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp
index f4677bbcb58e6be25f1115e57dd36df8816a3236..ee7b4fae3dda67e496f292dfc318af5f5ee4e2fe 100644
--- a/src/plugins/debugger/debuggerdialogs.cpp
+++ b/src/plugins/debugger/debuggerdialogs.cpp
@@ -232,7 +232,7 @@ static QList<ProcData> unixProcessListPS()
     if (!psProcess.waitForStarted())
         return rc;
     QByteArray output;
-    if (!Utils::SynchronousProcess::readDataFromProcess(psProcess, 30000, &output))
+    if (!Utils::SynchronousProcess::readDataFromProcess(psProcess, 30000, &output, 0, false))
         return rc;
     // Split "457 S+   /Users/foo.app"
     const QStringList lines = QString::fromLocal8Bit(output).split(QLatin1Char('\n'));
diff --git a/src/plugins/git/clonewizardpage.cpp b/src/plugins/git/clonewizardpage.cpp
index e2e3fdeb8b8bcd2eb0bf2efaced34f24c96b19a3..860a0c80633349c39bdadd17d262c6b08acbe2df 100644
--- a/src/plugins/git/clonewizardpage.cpp
+++ b/src/plugins/git/clonewizardpage.cpp
@@ -112,8 +112,9 @@ QSharedPointer<VCSBase::AbstractCheckoutJob> CloneWizardPage::createCheckoutJob(
      args << QLatin1String("clone") << repository() << checkoutDir;
      const QString binary = args.front();
      args.pop_front();
-     VCSBase::AbstractCheckoutJob *job = new VCSBase::ProcessCheckoutJob(binary, args, workingDirectory,
-                                                                         client->processEnvironment());
+     VCSBase::AbstractCheckoutJob *job =
+             new VCSBase::ProcessCheckoutJob(binary, args, workingDirectory,
+                                             client->processEnvironment().toStringList());
      return QSharedPointer<VCSBase::AbstractCheckoutJob>(job);
 }
 
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index d613a604c8ea6960dcbc3c40f186f964c23084d5..6bde23cb327035c84a9b92e7bb6e61cc21d3c81a 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -123,13 +123,6 @@ static inline QString msgParseFilesFailed()
     return  GitClient::tr("Unable to parse the file output.");
 }
 
-// Format a command for the status window
-static QString formatCommand(const QString &binary, const QStringList &args)
-{
-    //: Executing: <executable> <arguments>
-    return GitClient::tr("Executing: %1 %2\n").arg(binary, args.join(QString(QLatin1Char(' '))));
-}
-
 // ---------------- GitClient
 
 const char *GitClient::stashNamePrefix = "stash@{";
@@ -226,20 +219,20 @@ void GitClient::diff(const QString &workingDirectory,
     if (unstagedFileNames.empty() && stagedFileNames.empty()) {
        QStringList arguments(commonDiffArgs);
        arguments << diffArgs;
-       outputWindow()->appendCommand(formatCommand(binary, arguments));
+       outputWindow()->appendCommand(workingDirectory, binary, arguments);
        command->addJob(arguments, m_settings.timeoutSeconds);
     } else {
         // Files diff.
         if (!unstagedFileNames.empty()) {
            QStringList arguments(commonDiffArgs);
            arguments << QLatin1String("--") << unstagedFileNames;
-           outputWindow()->appendCommand(formatCommand(binary, arguments));
+           outputWindow()->appendCommand(workingDirectory, binary, arguments);
            command->addJob(arguments, m_settings.timeoutSeconds);
         }
         if (!stagedFileNames.empty()) {
            QStringList arguments(commonDiffArgs);
            arguments << QLatin1String("--cached") << diffArgs << QLatin1String("--") << stagedFileNames;
-           outputWindow()->appendCommand(formatCommand(binary, arguments));
+           outputWindow()->appendCommand(workingDirectory, binary, arguments);
            command->addJob(arguments, m_settings.timeoutSeconds);
         }
     }
@@ -1061,12 +1054,14 @@ GitCommand *GitClient::executeGit(const QString &workingDirectory,
                                   VCSBase::VCSBaseEditor* editor,
                                   bool outputToWindow,
                                   GitCommand::TerminationReportMode tm,
-                                  int editorLineNumber)
+                                  int editorLineNumber,
+                                  bool unixTerminalDisabled)
 {
-    outputWindow()->appendCommand(formatCommand(QLatin1String(Constants::GIT_BINARY), arguments));
+    outputWindow()->appendCommand(workingDirectory, QLatin1String(Constants::GIT_BINARY), arguments);
     GitCommand *command = createCommand(workingDirectory, editor, outputToWindow, editorLineNumber);
     command->addJob(arguments, m_settings.timeoutSeconds);
     command->setTerminationReportMode(tm);
+    command->setUnixTerminalDisabled(unixTerminalDisabled);
     command->execute();
     return command;
 }
@@ -1083,14 +1078,14 @@ QStringList GitClient::binary() const
 #endif
 }
 
-QStringList GitClient::processEnvironment() const
+QProcessEnvironment GitClient::processEnvironment() const
 {
-    ProjectExplorer::Environment environment = ProjectExplorer::Environment::systemEnvironment();
+    QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
     if (m_settings.adoptPath)
-        environment.set(QLatin1String("PATH"), m_settings.path);
-    // git svn runs perl which barfs at non-C locales.
-    environment.set(QLatin1String("LANG"), QString(QLatin1Char('C')));
-    return environment.toStringList();
+        environment.insert(QLatin1String("PATH"), m_settings.path);
+    // Set up SSH and C locale (required by git using perl).
+    VCSBase::VCSBasePlugin::setProcessEnvironment(&environment);
+    return environment;
 }
 
 bool GitClient::synchronousGit(const QString &workingDirectory,
@@ -1103,11 +1098,11 @@ bool GitClient::synchronousGit(const QString &workingDirectory,
         qDebug() << "synchronousGit" << workingDirectory << gitArguments;
 
     if (logCommandToWindow)
-        outputWindow()->appendCommand(formatCommand(m_binaryPath, gitArguments));
+        outputWindow()->appendCommand(workingDirectory, m_binaryPath, gitArguments);
 
     QProcess process;
     process.setWorkingDirectory(workingDirectory);
-    process.setEnvironment(processEnvironment());
+    process.setProcessEnvironment(processEnvironment());
 
     QStringList args = binary(); // "cmd /c git" on Windows
     const QString executable = args.front();
@@ -1125,7 +1120,7 @@ bool GitClient::synchronousGit(const QString &workingDirectory,
     }
 
     if (!Utils::SynchronousProcess::readDataFromProcess(process, m_settings.timeoutSeconds * 1000,
-                                                        outputText, errorText)) {
+                                                        outputText, errorText, true)) {
         *errorText->append(GitCommand::msgTimeout(m_settings.timeoutSeconds).toLocal8Bit());
         Utils::SynchronousProcess::stopProcess(process);
         return false;
@@ -1506,7 +1501,10 @@ void GitClient::pull(const QString &workingDirectory, bool rebase)
     QStringList arguments(QLatin1String("pull"));
     if (rebase)
         arguments << QLatin1String("--rebase");
-    GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true, GitCommand::ReportStderr);
+    // Disable UNIX terminals to suppress SSH prompting.
+    GitCommand *cmd = executeGit(workingDirectory, arguments, 0, true,
+                                 GitCommand::ReportStderr, -1,
+                                 VCSBase::VCSBasePlugin::isSshPromptConfigured());
     connectRepositoryChanged(workingDirectory, cmd);
     // Need to clean up if something goes wrong
     if (rebase) {
@@ -1539,7 +1537,11 @@ void GitClient::subversionFetch(const QString &workingDirectory)
 {
     QStringList args;
     args << QLatin1String("svn") << QLatin1String("fetch");
-    GitCommand *cmd = executeGit(workingDirectory, args, 0, true, GitCommand::ReportStderr);
+    // Disable UNIX terminals to suppress SSH prompting.
+    GitCommand *cmd = executeGit(workingDirectory, args, 0, true, GitCommand::ReportStderr,
+                                 -1, true);
+    // Enable SSH prompting
+    cmd->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
     connectRepositoryChanged(workingDirectory, cmd);
 }
 
@@ -1563,7 +1565,10 @@ void GitClient::subversionLog(const QString &workingDirectory)
 
 void GitClient::push(const QString &workingDirectory)
 {
-    executeGit(workingDirectory, QStringList(QLatin1String("push")), 0, true, GitCommand::ReportStderr);
+    // Disable UNIX terminals to suppress SSH prompting.
+    executeGit(workingDirectory, QStringList(QLatin1String("push")), 0,
+               true, GitCommand::ReportStderr,
+               VCSBase::VCSBasePlugin::isSshPromptConfigured());
 }
 
 QString GitClient::msgNoChangedFiles()
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 26423fce1d5bdc43d16f7ffce7a4ddfa41693764..4b2882d0e6051c3fad8892f5aa26bb02dbfdffd0 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE
 class QErrorMessage;
 class QSignalMapper;
 class QDebug;
+class QProcessEnvironment;
 QT_END_NAMESPACE
 
 namespace Core {
@@ -202,7 +203,7 @@ public:
     void setSettings(const GitSettings &s);
 
     QStringList binary() const; // Executable + basic arguments
-    QStringList processEnvironment() const;
+    QProcessEnvironment processEnvironment() const;
 
     static QString msgNoChangedFiles();
 
@@ -233,7 +234,8 @@ private:
                            VCSBase::VCSBaseEditor* editor = 0,
                            bool outputToWindow = false,
                            GitCommand::TerminationReportMode tm = GitCommand::NoReport,
-                           int editorLineNumber = -1);
+                           int editorLineNumber = -1,
+                           bool unixTerminalDisabled = false);
 
     bool synchronousGit(const QString &workingDirectory,
                         const QStringList &arguments,
diff --git a/src/plugins/git/gitcommand.cpp b/src/plugins/git/gitcommand.cpp
index 7483428eb91e7be18d3ce42b0baa81eed84e3a4c..b176e143436731765b035d494f93d72ca0aef60d 100644
--- a/src/plugins/git/gitcommand.cpp
+++ b/src/plugins/git/gitcommand.cpp
@@ -70,13 +70,14 @@ GitCommand::Job::Job(const QStringList &a, int t) :
 
 GitCommand::GitCommand(const QStringList &binary,
                         const QString &workingDirectory,
-                        const QStringList &environment,
+                        const QProcessEnvironment&environment,
                         const QVariant &cookie)  :
     m_binaryPath(binary.front()),
     m_basicArguments(binary),
     m_workingDirectory(workingDirectory),
     m_environment(environment),
     m_cookie(cookie),
+    m_unixTerminalDisabled(false),
     m_reportTerminationMode(NoReport)
 {
     m_basicArguments.pop_front();
@@ -92,6 +93,16 @@ void GitCommand::setTerminationReportMode(TerminationReportMode m)
     m_reportTerminationMode = m;
 }
 
+bool GitCommand::unixTerminalDisabled() const
+{
+    return m_unixTerminalDisabled;
+}
+
+void GitCommand::setUnixTerminalDisabled(bool e)
+{
+    m_unixTerminalDisabled = e;
+}
+
 void GitCommand::addJob(const QStringList &arguments, int timeout)
 {
     m_jobs.push_back(Job(arguments, timeout));
@@ -121,12 +132,18 @@ QString GitCommand::msgTimeout(int seconds)
 void GitCommand::run()
 {
     if (Git::Constants::debug)
-        qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size();
-    QProcess process;
+        qDebug() << "GitCommand::run" << m_workingDirectory << m_jobs.size()
+                 << "terminal_disabled" << m_unixTerminalDisabled;
+
+    const unsigned processFlags = m_unixTerminalDisabled ?
+                            unsigned(Utils::SynchronousProcess::UnixTerminalDisabled) :
+                            unsigned(0);
+    const QSharedPointer<QProcess> process =
+            Utils::SynchronousProcess::createProcess(processFlags);
     if (!m_workingDirectory.isEmpty())
-        process.setWorkingDirectory(m_workingDirectory);
+        process->setWorkingDirectory(m_workingDirectory);
 
-    process.setEnvironment(m_environment);
+    process->setProcessEnvironment(m_environment);
 
     QByteArray stdOut;
     QByteArray stdErr;
@@ -139,25 +156,25 @@ void GitCommand::run()
         if (Git::Constants::debug)
             qDebug() << "GitCommand::run" << j << '/' << count << m_jobs.at(j).arguments;
 
-        process.start(m_binaryPath, m_basicArguments + m_jobs.at(j).arguments);
-        if(!process.waitForStarted()) {
+        process->start(m_binaryPath, m_basicArguments + m_jobs.at(j).arguments);
+        if(!process->waitForStarted()) {
             ok = false;
-            error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process.errorString());
+            error += QString::fromLatin1("Error: \"%1\" could not be started: %2").arg(m_binaryPath, process->errorString());
             break;
         }
 
-        process.closeWriteChannel();
+        process->closeWriteChannel();
         const int timeOutSeconds = m_jobs.at(j).timeout;
-        if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOutSeconds * 1000,
-                                                            &stdOut, &stdErr)) {
-            Utils::SynchronousProcess::stopProcess(process);
+        if (!Utils::SynchronousProcess::readDataFromProcess(*process, timeOutSeconds * 1000,
+                                                            &stdOut, &stdErr, false)) {
+            Utils::SynchronousProcess::stopProcess(*process);
             ok = false;
             error += msgTimeout(timeOutSeconds);
             break;
         }
 
         error += QString::fromLocal8Bit(stdErr);
-        exitCode = process.exitCode();
+        exitCode = process->exitCode();
         switch (m_reportTerminationMode) {
         case NoReport:
             break;
diff --git a/src/plugins/git/gitcommand.h b/src/plugins/git/gitcommand.h
index c9cc058d0199076e019fe918cecd875ad59671f6..420e6f4dfaf893cf9625e16f0e1f2515304740ea 100644
--- a/src/plugins/git/gitcommand.h
+++ b/src/plugins/git/gitcommand.h
@@ -33,6 +33,7 @@
 #include <QtCore/QObject>
 #include <QtCore/QStringList>
 #include <QtCore/QVariant>
+#include <QtCore/QProcessEnvironment>
 
 QT_BEGIN_NAMESPACE
 class QProcess;
@@ -55,7 +56,7 @@ public:
 
     explicit GitCommand(const QStringList &binary,
                         const QString &workingDirectory,
-                        const QStringList &environment,
+                        const QProcessEnvironment &environment,
                         const QVariant &cookie = QVariant());
 
 
@@ -70,6 +71,10 @@ public:
     TerminationReportMode reportTerminationMode() const;
     void setTerminationReportMode(TerminationReportMode m);
 
+    // Disable Terminal on UNIX (see VCS SSH handling).
+    bool unixTerminalDisabled() const;
+    void setUnixTerminalDisabled(bool);
+
     static QString msgTimeout(int seconds);
 
     void setCookie(const QVariant &cookie);
@@ -95,8 +100,9 @@ private:
     const QString m_binaryPath;
     QStringList m_basicArguments;
     const QString m_workingDirectory;
-    const QStringList m_environment;
+    const QProcessEnvironment m_environment;
     QVariant m_cookie;
+    bool m_unixTerminalDisabled;
 
     QList<Job> m_jobs;
     TerminationReportMode m_reportTerminationMode;
diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp
index ff78f0dc4bb101d2e5bf818128172c066618e953..a7bf38b09fb522f5ecb24b1d414e96c2dec982fc 100644
--- a/src/plugins/mercurial/mercurialclient.cpp
+++ b/src/plugins/mercurial/mercurialclient.cpp
@@ -136,7 +136,7 @@ bool MercurialClient::executeHgSynchronously(const QString  &workingDir,
     const QStringList arguments = settings.standardArguments() + args;
 
     VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
-    outputWindow->appendCommand(MercurialJobRunner::msgExecute(binary, arguments));
+    outputWindow->appendCommand(workingDir, binary, args);
 
     hgProcess.start(binary, arguments);
 
@@ -149,7 +149,7 @@ bool MercurialClient::executeHgSynchronously(const QString  &workingDir,
 
     QByteArray stdErr;
     if (!Utils::SynchronousProcess::readDataFromProcess(hgProcess, settings.timeoutMilliSeconds(),
-                                                        output, &stdErr)) {
+                                                        output, &stdErr, true)) {
         Utils::SynchronousProcess::stopProcess(hgProcess);
         outputWindow->appendError(MercurialJobRunner::msgTimeout(settings.timeoutSeconds()));
         return false;
@@ -457,6 +457,8 @@ void MercurialClient::pull(const QString &repositoryRoot, const QString &reposit
     if (!repository.isEmpty())
         args.append(repository);
     QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, false, QVariant(repositoryRoot)));
+    // Suppress SSH prompting
+    job->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
     connect(job.data(), SIGNAL(succeeded(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection);
     enqueueJob(job);
 }
@@ -468,6 +470,8 @@ void MercurialClient::push(const QString &repositoryRoot, const QString &reposit
         args.append(repository);
 
     QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, false));
+    // Suppress SSH prompting
+    job->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
     enqueueJob(job);
 }
 
@@ -491,6 +495,9 @@ void MercurialClient::incoming(const QString &repositoryRoot, const QString &rep
                                                      true, "incoming", id);
 
     QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, editor));
+    // Suppress SSH prompting.
+    if (!repository.isEmpty() && VCSBase::VCSBasePlugin::isSshPromptConfigured())
+            job->setUnixTerminalDisabled(true);
     enqueueJob(job);
 }
 
@@ -506,6 +513,8 @@ void MercurialClient::outgoing(const QString &repositoryRoot)
                                                      "outgoing", repositoryRoot);
 
     QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, editor));
+    // Suppress SSH prompting
+    job->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
     enqueueJob(job);
 }
 
@@ -532,6 +541,8 @@ void MercurialClient::update(const QString &repositoryRoot, const QString &revis
         args << revision;
 
     QSharedPointer<HgTask> job(new HgTask(repositoryRoot, args, false, QVariant(repositoryRoot)));
+    // Suppress SSH prompting
+    job->setUnixTerminalDisabled(VCSBase::VCSBasePlugin::isSshPromptConfigured());
     connect(job.data(), SIGNAL(succeeded(QVariant)), this, SIGNAL(changed(QVariant)), Qt::QueuedConnection);
     enqueueJob(job);
 }
diff --git a/src/plugins/mercurial/mercurialjobrunner.cpp b/src/plugins/mercurial/mercurialjobrunner.cpp
index 54f343c122ddb04a90bd7e453efb0a5dbe7e80aa..0c0be01ed38c08db1b32cb20fba8f0214ad08e1e 100644
--- a/src/plugins/mercurial/mercurialjobrunner.cpp
+++ b/src/plugins/mercurial/mercurialjobrunner.cpp
@@ -34,6 +34,7 @@
 
 #include <vcsbase/vcsbaseoutputwindow.h>
 #include <vcsbase/vcsbaseeditor.h>
+#include <vcsbase/vcsbaseplugin.h>
 #include <utils/synchronousprocess.h>
 
 #include <QtCore/QProcess>
@@ -52,8 +53,8 @@ HgTask::HgTask(const QString &repositoryRoot,
     arguments(arguments),
     emitRaw(emitRaw),
     m_cookie(cookie),
-    editor(0)
-
+    editor(0),
+    m_unixTerminalDisabled(false)
 {
 }
 
@@ -65,7 +66,8 @@ HgTask::HgTask(const QString &repositoryRoot,
     arguments(arguments),
     emitRaw(false),
     m_cookie(cookie),
-    editor(editor)
+    editor(editor),
+    m_unixTerminalDisabled(false)
 {
 }
 
@@ -147,11 +149,6 @@ void MercurialJobRunner::run()
     }
 }
 
-QString MercurialJobRunner::msgExecute(const QString &binary, const QStringList &args)
-{
-    return tr("Executing: %1 %2\n").arg(binary, args.join(QString(QLatin1Char(' '))));
-}
-
 QString MercurialJobRunner::msgStartFailed(const QString &binary, const QString &why)
 {
     return tr("Unable to start mercurial process '%1': %2").arg(binary, why);
@@ -168,7 +165,7 @@ QString MercurialJobRunner::msgTimeout(int timeoutSeconds)
 void MercurialJobRunner::setProcessEnvironment(QProcess &p)
 {
     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
-    env.insert(QLatin1String("LANG"), QString(QLatin1Char('C')));
+    VCSBase::VCSBasePlugin::setProcessEnvironment(&env);
     p.setProcessEnvironment(env);
 }
 
@@ -196,35 +193,41 @@ void MercurialJobRunner::task(const QSharedPointer<HgTask> &job)
     }
 
     const QStringList args = standardArguments + taskData->args();
-    emit commandStarted(msgExecute(binary, args));
+    emit commandStarted(VCSBase::VCSBaseOutputWindow::msgExecutionLogEntry(taskData->repositoryRoot(), binary, args));
     //infom the user of what we are going to try and perform
 
     if (Constants::debug)
-        qDebug() << Q_FUNC_INFO << "Repository root is " << taskData->repositoryRoot();
+        qDebug() << Q_FUNC_INFO << "Repository root is "
+                << taskData->repositoryRoot() << " terminal_disabled"
+                << taskData->unixTerminalDisabled();
+
+    const unsigned processFlags = taskData->unixTerminalDisabled() ?
+                            unsigned(Utils::SynchronousProcess::UnixTerminalDisabled) :
+                            unsigned(0);
 
-    QProcess hgProcess;
-    hgProcess.setWorkingDirectory(taskData->repositoryRoot());
-    MercurialJobRunner::setProcessEnvironment(hgProcess);
+    QSharedPointer<QProcess> hgProcess = Utils::SynchronousProcess::createProcess(processFlags);
+    hgProcess->setWorkingDirectory(taskData->repositoryRoot());
+    MercurialJobRunner::setProcessEnvironment(*hgProcess);
 
-    hgProcess.start(binary, args);
+    hgProcess->start(binary, args);
 
-    if (!hgProcess.waitForStarted()) {
-        emit error(msgStartFailed(binary, hgProcess.errorString()));
+    if (!hgProcess->waitForStarted()) {
+        emit error(msgStartFailed(binary, hgProcess->errorString()));
         return;
     }
 
-    hgProcess.closeWriteChannel();
+    hgProcess->closeWriteChannel();
 
     QByteArray stdOutput;
     QByteArray stdErr;
 
-    if (!Utils::SynchronousProcess::readDataFromProcess(hgProcess, m_timeoutMS, &stdOutput, &stdErr)) {
-        Utils::SynchronousProcess::stopProcess(hgProcess);
+    if (!Utils::SynchronousProcess::readDataFromProcess(*hgProcess, m_timeoutMS, &stdOutput, &stdErr, false)) {
+        Utils::SynchronousProcess::stopProcess(*hgProcess);
         emit error(msgTimeout(m_timeoutMS / 1000));
         return;
     }
 
-    if (hgProcess.exitStatus() == QProcess::NormalExit && hgProcess.exitCode() == 0) {
+    if (hgProcess->exitStatus() == QProcess::NormalExit && hgProcess->exitCode() == 0) {
         /*
           * sometimes success means output is actually on error channel (stderr)
           * e.g. "hg revert" outputs "no changes needed to 'file'" on stderr if file has not changed
@@ -238,7 +241,7 @@ void MercurialJobRunner::task(const QSharedPointer<HgTask> &job)
         emit error(QString::fromLocal8Bit(stdErr));
     }
 
-    hgProcess.close();
+    hgProcess->close();
     //the signal connection is to last only for the duration of a job/task.  next time a new
     //output signal connection must be made
     disconnect(this, SIGNAL(output(QByteArray)), 0, 0);
diff --git a/src/plugins/mercurial/mercurialjobrunner.h b/src/plugins/mercurial/mercurialjobrunner.h
index df6f1f79d632b214cdc74e0d9694f6131eff4410..a7bc219c16ef02bad0eb073487bafc43f4499e44 100644
--- a/src/plugins/mercurial/mercurialjobrunner.h
+++ b/src/plugins/mercurial/mercurialjobrunner.h
@@ -69,6 +69,10 @@ public:
     QStringList args() { return arguments; }
     QString repositoryRoot() { return m_repositoryRoot; }
 
+    // Disable terminal to suppress SSH prompting.
+    bool unixTerminalDisabled() const     { return m_unixTerminalDisabled; }
+    void setUnixTerminalDisabled(bool v)  { m_unixTerminalDisabled = v; }
+
 signals:
     void succeeded(const QVariant &cookie); // Use a queued connection
     void rawData(const QByteArray &data);
@@ -82,6 +86,7 @@ private:
     const bool emitRaw;
     const QVariant m_cookie;
     VCSBase::VCSBaseEditor *editor;
+    bool m_unixTerminalDisabled;
 };
 
 /* A job queue running in a separate thread, executing commands
@@ -95,7 +100,6 @@ public:
     void enqueueJob(const QSharedPointer<HgTask> &job);
     void restart();
 
-    static QString msgExecute(const QString &binary, const QStringList &args);
     static QString msgStartFailed(const QString &binary, const QString &why);
     static QString msgTimeout(int timeoutSeconds);
 
diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp
index 4a44dc43a5021ac6b8fadddc0f50efdf8dc91bc9..49ea0afd3814e2a3df103e7d8827c363c72340a8 100644
--- a/src/plugins/perforce/perforceplugin.cpp
+++ b/src/plugins/perforce/perforceplugin.cpp
@@ -947,15 +947,6 @@ bool PerforcePlugin::vcsMove(const QString &workingDir, const QString &from, con
     return !moveResult.error;
 }
 
-static QString formatCommand(const QString &cmd, const QStringList &args)
-{
-    const QChar blank = QLatin1Char(' ');
-    QString command = cmd;
-    command += blank;
-    command += args.join(QString(blank));
-    return PerforcePlugin::tr("Executing: %1\n").arg(command);
-}
-
 // Write extra args to temporary file
 QSharedPointer<QTemporaryFile>
         PerforcePlugin::createTemporaryArgumentFile(const QStringList &extraArgs) const
@@ -1041,6 +1032,7 @@ PerforceResponse PerforcePlugin::synchronousProcess(const QString &workingDir,
     }
     if (Perforce::Constants::debug)
         qDebug() << "PerforcePlugin::run syncp actual args [" << process.workingDirectory() << ']' << args;
+    process.setTimeOutMessageBoxEnabled(true);
     const Utils::SynchronousProcessResponse sp_resp = process.run(m_settings.p4Command(), args);
     if (Perforce::Constants::debug)
         qDebug() << sp_resp;
@@ -1111,7 +1103,7 @@ PerforceResponse PerforcePlugin::fullySynchronousProcess(const QString &workingD
     QByteArray stdOut;
     QByteArray stdErr;
     const int timeOut = (flags & LongTimeOut) ? m_settings.longTimeOutMS() : m_settings.timeOutMS();
-    if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOut, &stdOut, &stdErr)) {
+    if (!Utils::SynchronousProcess::readDataFromProcess(process, timeOut, &stdOut, &stdErr, true)) {
         Utils::SynchronousProcess::stopProcess(process);
         response.error = true;
         response.message = msgTimeout(timeOut);
@@ -1164,7 +1156,7 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QString &workingDir,
     actualArgs.append(args);
 
     if (flags & CommandToWindow)
-        outputWindow->appendCommand(formatCommand(m_settings.p4Command(), actualArgs));
+        outputWindow->appendCommand(workingDir, m_settings.p4Command(), actualArgs);
 
     if (flags & ShowBusyCursor)
         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp
index ff299b1912903f0c62e29bee9f7db3cad34d8dc7..7ae56c8d4f58372543ce2f4de3242efcfa0da54f 100644
--- a/src/plugins/subversion/subversionplugin.cpp
+++ b/src/plugins/subversion/subversionplugin.cpp
@@ -105,6 +105,8 @@ static const char * const CMD_ID_DESCRIBE           = "Subversion.Describe";
 
 static const char *nonInteractiveOptionC = "--non-interactive";
 
+
+
 static const VCSBase::VCSBaseEditorParameters editorParameters[] = {
 {
     VCSBase::RegularCommandOutput,
@@ -548,7 +550,8 @@ void SubversionPlugin::svnDiff(const QString &workingDir, const QStringList &fil
     QStringList args(QLatin1String("diff"));
     args << files;
 
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), false, codec);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(), 0);
     if (response.error)
         return;
 
@@ -635,7 +638,9 @@ void SubversionPlugin::revertAll()
     // NoteL: Svn "revert ." doesn not work.
     QStringList args;
     args << QLatin1String("revert") << QLatin1String("--recursive") << state.topLevel();
-    const SubversionResponse revertResponse = runSvn(state.topLevel(), args, m_settings.timeOutMS(), true);
+    const SubversionResponse revertResponse =
+            runSvn(state.topLevel(), args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     if (revertResponse.error) {
         QMessageBox::warning(0, title, tr("Revert failed: %1").arg(revertResponse.message), QMessageBox::Ok);
     } else {
@@ -651,7 +656,8 @@ void SubversionPlugin::revertCurrentFile()
     QStringList args(QLatin1String("diff"));
     args.push_back(state.relativeCurrentFile());
 
-    const SubversionResponse diffResponse = runSvn(state.currentFileTopLevel(), args, m_settings.timeOutMS(), false);
+    const SubversionResponse diffResponse =
+            runSvn(state.currentFileTopLevel(), args, m_settings.timeOutMS(), 0);
     if (diffResponse.error)
         return;
 
@@ -668,7 +674,10 @@ void SubversionPlugin::revertCurrentFile()
     args.clear();
     args << QLatin1String("revert") << state.relativeCurrentFile();
 
-    const SubversionResponse revertResponse = runSvn(state.currentFileTopLevel(), args, m_settings.timeOutMS(), true);
+    const SubversionResponse revertResponse =
+            runSvn(state.currentFileTopLevel(), args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
+
     if (!revertResponse.error) {
         subVersionControl()->emitFilesChanged(QStringList(state.currentFile()));
     }
@@ -724,7 +733,8 @@ void SubversionPlugin::startCommit(const QString &workingDir, const QStringList
     QStringList args(QLatin1String("status"));
     args += files;
 
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), false);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(), 0);
     if (response.error)
         return;
 
@@ -765,7 +775,9 @@ bool SubversionPlugin::commit(const QString &messageFile,
     QStringList args = QStringList(QLatin1String("commit"));
     args << QLatin1String(nonInteractiveOptionC) << QLatin1String("--file") << messageFile;
     args.append(subVersionFileList);
-    const SubversionResponse response = runSvn(m_commitRepository, args, m_settings.longTimeOutMS(), true);
+    const SubversionResponse response =
+            runSvn(m_commitRepository, args, m_settings.longTimeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     return !response.error ;
 }
 
@@ -820,7 +832,8 @@ void SubversionPlugin::svnStatus(const QString &workingDir, const QStringList &r
         args.append(relativePaths);
     VCSBase::VCSBaseOutputWindow *outwin = VCSBase::VCSBaseOutputWindow::instance();
     outwin->setRepository(workingDir);
-    runSvn(workingDir, args, m_settings.timeOutMS(), true);
+    runSvn(workingDir, args, m_settings.timeOutMS(),
+           ShowStdOutInLogWindow);
     outwin->clearRepository();
 }
 
@@ -836,7 +849,9 @@ void SubversionPlugin::filelog(const QString &workingDir,
     foreach(const QString &file, files)
         args.append(QDir::toNativeSeparators(file));
 
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), false, codec);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt, codec);
     if (response.error)
         return;
 
@@ -870,7 +885,9 @@ void SubversionPlugin::svnUpdate(const QString &workingDir, const QStringList &r
     args.push_back(QLatin1String(nonInteractiveOptionC));
     if (!relativePaths.isEmpty())
         args.append(relativePaths);
-        const SubversionResponse response = runSvn(workingDir, args, m_settings.longTimeOutMS(), true);
+        const SubversionResponse response =
+                runSvn(workingDir, args, m_settings.longTimeOutMS(),
+                       SshPasswordPrompt|ShowStdOutInLogWindow);
     if (!response.error)
         subVersionControl()->emitRepositoryChanged(workingDir);
 }
@@ -904,7 +921,9 @@ void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &fil
     args.push_back(QLatin1String("-v"));
     args.append(QDir::toNativeSeparators(file));
 
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), false, codec);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt, codec);
     if (response.error)
         return;
 
@@ -956,7 +975,8 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr)
     QStringList args(QLatin1String("log"));
     args.push_back(QLatin1String("-r"));
     args.push_back(changeNr);
-    const SubversionResponse logResponse = runSvn(topLevel, args, m_settings.timeOutMS(), false);
+    const SubversionResponse logResponse =
+            runSvn(topLevel, args, m_settings.timeOutMS(), SshPasswordPrompt);
     if (logResponse.error)
         return;
     description = logResponse.stdOut;
@@ -970,7 +990,9 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr)
     args.push_back(diffArg);
 
     QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(source);
-    const SubversionResponse response = runSvn(topLevel, args, m_settings.timeOutMS(), false, codec);
+    const SubversionResponse response =
+            runSvn(topLevel, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt, codec);
     if (response.error)
         return;
     description += response.stdOut;
@@ -1013,32 +1035,10 @@ void SubversionPlugin::submitCurrentLog()
         << Core::EditorManager::instance()->currentEditor());
 }
 
-static inline QString processStdErr(QProcess &proc)
-{
-    return QString::fromLocal8Bit(proc.readAllStandardError()).remove(QLatin1Char('\r'));
-}
-
-static inline QString processStdOut(QProcess &proc, QTextCodec *outputCodec = 0)
-{
-    const QByteArray stdOutData = proc.readAllStandardOutput();
-    QString stdOut = outputCodec ? outputCodec->toUnicode(stdOutData) : QString::fromLocal8Bit(stdOutData);
-    return stdOut.remove(QLatin1Char('\r'));
-}
-
-// Format log entry for command
-static inline QString msgExecutionLogEntry(const QString &workingDir, const QString &executable, const QStringList &arguments)
-{
-    const QString argsS = SubversionSettings::formatArguments(arguments);
-    if (workingDir.isEmpty())
-        return SubversionPlugin::tr("Executing: %1 %2\n").arg(executable, argsS);
-    return SubversionPlugin::tr("Executing in %1: %2 %3\n").
-            arg(QDir::toNativeSeparators(workingDir), executable, argsS);
-}
-
 SubversionResponse SubversionPlugin::runSvn(const QString &workingDir,
                                             const QStringList &arguments,
                                             int timeOut,
-                                            bool showStdOutInOutputWindow,
+                                            unsigned flags,
                                             QTextCodec *outputCodec)
 {
     const QString executable = m_settings.svnCommand;
@@ -1048,60 +1048,17 @@ SubversionResponse SubversionPlugin::runSvn(const QString &workingDir,
         response.message =tr("No subversion executable specified!");
         return response;
     }
-    const QStringList allArgs = m_settings.addOptions(arguments);
 
-    VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
-    // Hide passwords, etc in the log window
-    //: Executing: <executable> <arguments>
-    const QString outputText = msgExecutionLogEntry(workingDir, executable, allArgs);
-    outputWindow->appendCommand(outputText);
+    const Utils::SynchronousProcessResponse sp_resp =
+            VCSBase::VCSBasePlugin::runVCS(workingDir, executable,
+                                           m_settings.addOptions(arguments),
+                                           timeOut, flags, outputCodec);
 
-    if (Subversion::Constants::debug)
-        qDebug() << "runSvn" << timeOut << outputText;
-
-    // Run, connect stderr to the output window
-    Utils::SynchronousProcess process;
-    if (!workingDir.isEmpty())
-        process.setWorkingDirectory(workingDir);
-    QProcessEnvironment env = process.processEnvironment();
-    env.insert(QLatin1String("LANG"), QString(QLatin1Char('C')));
-    process.setProcessEnvironment(env);
-    process.setTimeout(timeOut);
-    process.setStdOutCodec(outputCodec);
-
-    process.setStdErrBufferedSignalsEnabled(true);
-    connect(&process, SIGNAL(stdErrBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
-
-    // connect stdout to the output window if desired
-    if (showStdOutInOutputWindow) {
-        process.setStdOutBufferedSignalsEnabled(true);
-        connect(&process, SIGNAL(stdOutBuffered(QString,bool)), outputWindow, SLOT(append(QString)));
-    }
-
-    const Utils::SynchronousProcessResponse sp_resp = process.run(executable, allArgs);
-    response.error = true;
+    response.error = sp_resp.result != Utils::SynchronousProcessResponse::Finished;
+    if (response.error)
+        response.message = sp_resp.exitMessage(executable, timeOut);
     response.stdErr = sp_resp.stdErr;
     response.stdOut = sp_resp.stdOut;
-    switch (sp_resp.result) {
-    case Utils::SynchronousProcessResponse::Finished:
-        response.error = false;
-        break;
-    case Utils::SynchronousProcessResponse::FinishedError:
-        response.message = tr("The process terminated with exit code %1.").arg(sp_resp.exitCode);
-        break;
-    case Utils::SynchronousProcessResponse::TerminatedAbnormally:
-        response.message = tr("The process terminated abnormally.");
-        break;
-    case Utils::SynchronousProcessResponse::StartFailed:
-        response.message = tr("Could not start subversion '%1'. Please check your settings in the preferences.").arg(executable);
-        break;
-    case Utils::SynchronousProcessResponse::Hang:
-        response.message = tr("Subversion did not respond within timeout limit (%1 ms).").arg(timeOut);
-        break;
-    }
-    if (response.error)
-        outputWindow->appendError(response.message);
-
     return response;
 }
 
@@ -1167,7 +1124,9 @@ bool SubversionPlugin::vcsAdd15(const QString &workingDir, const QString &rawFil
     const QString file = QDir::toNativeSeparators(rawFileName);
     QStringList args;
     args << QLatin1String("add") << QLatin1String("--parents") << file;
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), true);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     return !response.error;
 }
 
@@ -1188,7 +1147,9 @@ bool SubversionPlugin::vcsAdd14(const QString &workingDir, const QString &rawFil
             if (!checkSVNSubDir(QDir(path))) {
                 QStringList addDirArgs;
                 addDirArgs << QLatin1String("add") << QLatin1String("--non-recursive") << QDir::toNativeSeparators(path);
-                const SubversionResponse addDirResponse = runSvn(workingDir, addDirArgs, m_settings.timeOutMS(), true);
+                const SubversionResponse addDirResponse =
+                        runSvn(workingDir, addDirArgs, m_settings.timeOutMS(),
+                               SshPasswordPrompt|ShowStdOutInLogWindow);
                 if (addDirResponse.error)
                     return false;
             }
@@ -1197,7 +1158,9 @@ bool SubversionPlugin::vcsAdd14(const QString &workingDir, const QString &rawFil
     // Add file
     QStringList args;
     args << QLatin1String("add") << QDir::toNativeSeparators(rawFileName);
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), true);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     return !response.error;
 }
 
@@ -1208,7 +1171,9 @@ bool SubversionPlugin::vcsDelete(const QString &workingDir, const QString &rawFi
     QStringList args(QLatin1String("delete"));
     args.push_back(file);
 
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), true);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     return !response.error;
 }
 
@@ -1217,7 +1182,9 @@ bool SubversionPlugin::vcsMove(const QString &workingDir, const QString &from, c
     QStringList args(QLatin1String("move"));
     args << QDir::toNativeSeparators(from) << QDir::toNativeSeparators(to);
     qDebug()<<args;
-    const SubversionResponse response = runSvn(workingDir, args, m_settings.timeOutMS(), true);
+    const SubversionResponse response =
+            runSvn(workingDir, args, m_settings.timeOutMS(),
+                   SshPasswordPrompt|ShowStdOutInLogWindow);
     qDebug() << response.stdOut << "\n"<<response.stdErr;
     return !response.error;
 }
diff --git a/src/plugins/subversion/subversionplugin.h b/src/plugins/subversion/subversionplugin.h
index 278cb2d30336041a64d82d34a60fcb337594c430..31ef436ebf29a5bf96f4dc7e2e1d4946b1f5452c 100644
--- a/src/plugins/subversion/subversionplugin.h
+++ b/src/plugins/subversion/subversionplugin.h
@@ -138,7 +138,7 @@ private:
                                        QTextCodec *codec);
     SubversionResponse runSvn(const QString &workingDir,
                               const QStringList &arguments, int timeOut,
-                              bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0);
+                              unsigned flags, QTextCodec *outputCodec = 0);
     void filelog(const QString &workingDir,
                  const QStringList &file = QStringList(),
                  bool enableAnnotationContextMenu = false);
diff --git a/src/plugins/subversion/subversionsettings.cpp b/src/plugins/subversion/subversionsettings.cpp
index 3a38c7a618d5ecbed8f3a3f18f9cb007559a18fc..91796f08cd67e4558ce74660262958e23e664029 100644
--- a/src/plugins/subversion/subversionsettings.cpp
+++ b/src/plugins/subversion/subversionsettings.cpp
@@ -30,20 +30,19 @@
 #include "subversionsettings.h"
 
 #include <QtCore/QSettings>
-#include <QtCore/QTextStream>
 
-static const char *groupC = "Subversion";
-static const char *commandKeyC = "Command";
-static const char *userKeyC = "User";
-static const char *passwordKeyC = "Password";
-static const char *authenticationKeyC = "Authentication";
+static const char groupC[] = "Subversion";
+static const char commandKeyC[] = "Command";
+static const char userKeyC[] = "User";
+static const char passwordKeyC[] = "Password";
+static const char authenticationKeyC[] = "Authentication";
 
-static const char *userNameOptionC = "--username";
-static const char *passwordOptionC = "--password";
-static const char *promptToSubmitKeyC = "PromptForSubmit";
-static const char *timeOutKeyC = "TimeOut";
-static const char *spaceIgnorantAnnotationKeyC = "SpaceIgnorantAnnotation";
-static const char *logCountKeyC = "LogCount";
+static const char userNameOptionC[] = "--username";
+static const char passwordOptionC[] = "--password";
+static const char promptToSubmitKeyC[] = "PromptForSubmit";
+static const char timeOutKeyC[] = "TimeOut";
+static const char spaceIgnorantAnnotationKeyC[] = "SpaceIgnorantAnnotation";
+static const char logCountKeyC[] = "LogCount";
 
 enum { defaultTimeOutS = 30, defaultLogCount = 1000 };
 
@@ -128,23 +127,3 @@ QStringList SubversionSettings::addOptions(const QStringList &args) const
     rc.append(args);
     return rc;
 }
-
-// Format arguments for log windows hiding passwords, etc.
-QString SubversionSettings::formatArguments(const QStringList &args)
-{
-    QString rc;
-    QTextStream str(&rc);
-    const int size = args.size();
-    // Skip authentication options
-    for (int i = 0; i < size; i++) {
-        const QString &arg = args.at(i);
-        if (i)
-            str << ' ';
-        str << arg;
-        if (arg == QLatin1String(userNameOptionC) || arg == QLatin1String(passwordOptionC)) {
-            str << " ********";
-            i++;
-        }
-    }
-    return rc;
-}
diff --git a/src/plugins/subversion/subversionsettings.h b/src/plugins/subversion/subversionsettings.h
index 1fca010d06f6596550cc9a050bef1cbe5ce22d2a..9eaa8e0c9e715be9fc9f9679c17e21353790d90a 100644
--- a/src/plugins/subversion/subversionsettings.h
+++ b/src/plugins/subversion/subversionsettings.h
@@ -53,8 +53,6 @@ struct SubversionSettings
     // Add authentication and (maybe future) options to the
     // command line
     QStringList addOptions(const QStringList &args) const;
-    // Format arguments for log windows hiding passwords, etc.
-    static QString formatArguments(const QStringList &args);
 
     bool equals(const SubversionSettings &s) const;
 
diff --git a/src/plugins/vcsbase/checkoutjobs.cpp b/src/plugins/vcsbase/checkoutjobs.cpp
index 3d18fed83e2a1510a431dc47dadd6eae30b6d669..e707595637b764e7c3bdde0e899a52ccd49f7050 100644
--- a/src/plugins/vcsbase/checkoutjobs.cpp
+++ b/src/plugins/vcsbase/checkoutjobs.cpp
@@ -29,6 +29,8 @@
 
 #include "checkoutjobs.h"
 
+#include <vcsbaseplugin.h>
+
 #include <QtCore/QDebug>
 #include <utils/synchronousprocess.h>
 
@@ -46,22 +48,35 @@ struct ProcessCheckoutJobPrivate {
                               const QString &workingDirectory,
                               const QStringList &env);
 
-    QProcess process;
+    QSharedPointer<QProcess> process;
     const QString binary;
     const QStringList args;
 };
 
+// Use a terminal-less process to suppress SSH prompts.
+static inline QSharedPointer<QProcess> createProcess()
+{
+    unsigned flags = 0;
+    if (VCSBasePlugin::isSshPromptConfigured())
+        flags = Utils::SynchronousProcess::UnixTerminalDisabled;
+    return Utils::SynchronousProcess::createProcess(flags);
+}
+
 ProcessCheckoutJobPrivate::ProcessCheckoutJobPrivate(const QString &b,
                               const QStringList &a,
                               const QString &workingDirectory,
                               const QStringList &env) :
+    process(createProcess()),
     binary(b),
     args(a)
-{
+{    
     if (!workingDirectory.isEmpty())
-        process.setWorkingDirectory(workingDirectory);
+        process->setWorkingDirectory(workingDirectory);
     if (!env.empty())
-        process.setEnvironment(env);
+        process->setEnvironment(env);
+    QProcessEnvironment processEnv = process->processEnvironment();
+    VCSBasePlugin::setProcessEnvironment(&processEnv);
+    process->setProcessEnvironment(processEnv);
 }
 
 ProcessCheckoutJob::ProcessCheckoutJob(const QString &binary,
@@ -74,11 +89,11 @@ ProcessCheckoutJob::ProcessCheckoutJob(const QString &binary,
 {
     if (debug)
         qDebug() << "ProcessCheckoutJob" << binary << args << workingDirectory;
-    connect(&d->process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(slotError(QProcess::ProcessError)));
-    connect(&d->process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotFinished(int,QProcess::ExitStatus)));
-    connect(&d->process, SIGNAL(readyReadStandardOutput()), this, SLOT(slotOutput()));
-    d->process.setProcessChannelMode(QProcess::MergedChannels);
-    d->process.closeWriteChannel();
+    connect(d->process.data(), SIGNAL(error(QProcess::ProcessError)), this, SLOT(slotError(QProcess::ProcessError)));
+    connect(d->process.data(), SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotFinished(int,QProcess::ExitStatus)));
+    connect(d->process.data(), SIGNAL(readyReadStandardOutput()), this, SLOT(slotOutput()));
+    d->process->setProcessChannelMode(QProcess::MergedChannels);
+    d->process->closeWriteChannel();
 }
 
 ProcessCheckoutJob::~ProcessCheckoutJob()
@@ -88,7 +103,7 @@ ProcessCheckoutJob::~ProcessCheckoutJob()
 
 void ProcessCheckoutJob::slotOutput()
 {
-    const QByteArray data = d->process.readAllStandardOutput();
+    const QByteArray data = d->process->readAllStandardOutput();
     const QString s = QString::fromLocal8Bit(data, data.endsWith('\n') ? data.size() - 1: data.size());
     if (debug)
         qDebug() << s;
@@ -99,10 +114,10 @@ void ProcessCheckoutJob::slotError(QProcess::ProcessError error)
 {
     switch (error) {
     case QProcess::FailedToStart:
-        emit failed(tr("Unable to start %1: %2").arg(d->binary, d->process.errorString()));
+        emit failed(tr("Unable to start %1: %2").arg(d->binary, d->process->errorString()));
         break;
     default:
-        emit failed(d->process.errorString());
+        emit failed(d->process->errorString());
         break;
     }
 }
@@ -129,7 +144,7 @@ void ProcessCheckoutJob::slotFinished (int exitCode, QProcess::ExitStatus exitSt
 
 void ProcessCheckoutJob::start()
 {
-    d->process.start(d->binary, d->args);
+    d->process->start(d->binary, d->args);
 }
 
 void ProcessCheckoutJob::cancel()
@@ -138,7 +153,7 @@ void ProcessCheckoutJob::cancel()
         qDebug() << "ProcessCheckoutJob::start";
 
     emit output(tr("Stopping..."));
-    Utils::SynchronousProcess::stopProcess(d->process);
+    Utils::SynchronousProcess::stopProcess(*d->process);
 }
 
 } // namespace VCSBase
diff --git a/src/plugins/vcsbase/commonsettingspage.cpp b/src/plugins/vcsbase/commonsettingspage.cpp
index d9d2ffb1511e709fc05776aaad9f11040b2af009..c382170b3148308048abe8271e753978d9aa2474 100644
--- a/src/plugins/vcsbase/commonsettingspage.cpp
+++ b/src/plugins/vcsbase/commonsettingspage.cpp
@@ -53,6 +53,7 @@ CommonSettingsWidget::CommonSettingsWidget(QWidget *parent) :
     m_ui->submitMessageCheckScriptChooser->setExpectedKind(Utils::PathChooser::Command);
     m_ui->nickNameFieldsFileChooser->setExpectedKind(Utils::PathChooser::File);
     m_ui->nickNameMailMapChooser->setExpectedKind(Utils::PathChooser::File);
+    m_ui->sshPromptChooser->setExpectedKind(Utils::PathChooser::Command);
 }
 
 CommonSettingsWidget::~CommonSettingsWidget()
@@ -68,6 +69,7 @@ CommonVcsSettings CommonSettingsWidget::settings() const
     rc.submitMessageCheckScript = m_ui->submitMessageCheckScriptChooser->path();
     rc.lineWrap= m_ui->lineWrapCheckBox->isChecked();
     rc.lineWrapWidth = m_ui->lineWrapSpinBox->value();
+    rc.sshPasswordPrompt = m_ui->sshPromptChooser->path();
     return rc;
 }
 
@@ -78,6 +80,7 @@ void CommonSettingsWidget::setSettings(const CommonVcsSettings &s)
     m_ui->submitMessageCheckScriptChooser->setPath(s.submitMessageCheckScript);
     m_ui->lineWrapCheckBox->setChecked(s.lineWrap);
     m_ui->lineWrapSpinBox->setValue(s.lineWrapWidth);
+    m_ui->sshPromptChooser->setPath(s.sshPasswordPrompt);
 }
 
 QString CommonSettingsWidget::searchKeyWordMatchString() const
diff --git a/src/plugins/vcsbase/commonsettingspage.ui b/src/plugins/vcsbase/commonsettingspage.ui
index 16065aa48f80dfa53b3492fa99cd469287509c46..c15f9cd96f3fe5816f492c9a088f8d97a6a1c6bc 100644
--- a/src/plugins/vcsbase/commonsettingspage.ui
+++ b/src/plugins/vcsbase/commonsettingspage.ui
@@ -6,11 +6,11 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>359</width>
-    <height>105</height>
+    <width>338</width>
+    <height>166</height>
    </rect>
   </property>
-  <layout class="QGridLayout" name="gridLayout">
+  <layout class="QFormLayout" name="formLayout">
    <item row="0" column="0">
     <widget class="QCheckBox" name="lineWrapCheckBox">
      <property name="text">
@@ -37,7 +37,7 @@
      </property>
     </widget>
    </item>
-   <item row="0" column="2">
+   <item row="1" column="1">
     <spacer name="horizontalSpacer">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
@@ -50,7 +50,7 @@
      </property>
     </spacer>
    </item>
-   <item row="1" column="0">
+   <item row="2" column="0">
     <widget class="QLabel" name="submitMessageCheckScriptLabel">
      <property name="toolTip">
       <string>An executable which is called with the submit message in a temporary file as first argument. It should return with an exit != 0 and a message on standard error to indicate failure.</string>
@@ -60,10 +60,10 @@
      </property>
     </widget>
    </item>
-   <item row="1" column="1" colspan="2">
+   <item row="2" column="1">
     <widget class="Utils::PathChooser" name="submitMessageCheckScriptChooser" native="true"/>
    </item>
-   <item row="2" column="0">
+   <item row="3" column="0">
     <widget class="QLabel" name="nickNameMailMapLabel">
      <property name="toolTip">
       <string>A file listing user names and email addresses in a 4-column mailmap format:
@@ -74,10 +74,10 @@ name &lt;email&gt; alias &lt;email&gt;</string>
      </property>
     </widget>
    </item>
-   <item row="2" column="1" colspan="2">
+   <item row="3" column="1">
     <widget class="Utils::PathChooser" name="nickNameMailMapChooser" native="true"/>
    </item>
-   <item row="3" column="0">
+   <item row="4" column="0">
     <widget class="QLabel" name="nickNameFieldsFileLabel">
      <property name="toolTip">
       <string>A simple file containing lines with field names like &quot;Reviewed-By:&quot; which will be added below the submit editor.</string>
@@ -87,10 +87,10 @@ name &lt;email&gt; alias &lt;email&gt;</string>
      </property>
     </widget>
    </item>
-   <item row="3" column="1" colspan="2">
+   <item row="4" column="1">
     <widget class="Utils::PathChooser" name="nickNameFieldsFileChooser" native="true"/>
    </item>
-   <item row="4" column="0" colspan="3">
+   <item row="6" column="0" colspan="2">
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
@@ -106,6 +106,20 @@ name &lt;email&gt; alias &lt;email&gt;</string>
      </property>
     </spacer>
    </item>
+   <item row="5" column="0">
+    <widget class="QLabel" name="sshPromptLabel">
+     <property name="toolTip">
+      <string>Specifies a command that is executed to graphically prompt for a password, 
+should a repository require SSH-authentication (see documentation on SSH and the environment variable SSH_ASKPASS).</string>
+     </property>
+     <property name="text">
+      <string>SSH prompt command:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="1">
+    <widget class="Utils::PathChooser" name="sshPromptChooser" native="true"/>
+   </item>
   </layout>
  </widget>
  <customwidgets>
diff --git a/src/plugins/vcsbase/commonvcssettings.cpp b/src/plugins/vcsbase/commonvcssettings.cpp
index 95186a23fc3988f1f3f50b3b85aa811c2feb48dd..621e85f895f5be14d11fabf0f95eda0cc57c7281 100644
--- a/src/plugins/vcsbase/commonvcssettings.cpp
+++ b/src/plugins/vcsbase/commonvcssettings.cpp
@@ -32,20 +32,28 @@
 #include <QtCore/QSettings>
 #include <QtCore/QDebug>
 
-static const char *settingsGroupC = "VCS";
-static const char *nickNameMailMapKeyC = "NickNameMailMap";
-static const char *nickNameFieldListFileKeyC = "NickNameFieldListFile";
-static const char *submitMessageCheckScriptKeyC = "SubmitMessageCheckScript";
-static const char *lineWrapKeyC = "LineWrap";
-static const char *lineWrapWidthKeyC = "LineWrapWidth";
+static const char settingsGroupC[] = "VCS";
+static const char nickNameMailMapKeyC[] = "NickNameMailMap";
+static const char nickNameFieldListFileKeyC[] = "NickNameFieldListFile";
+static const char submitMessageCheckScriptKeyC[] = "SubmitMessageCheckScript";
+static const char lineWrapKeyC[] = "LineWrap";
+static const char lineWrapWidthKeyC[] = "LineWrapWidth";
+static const char sshPasswordPromptKeyC[] = "SshPasswordPrompt";
 
 static const int lineWrapWidthDefault = 72;
 static const bool lineWrapDefault = true;
 
+#ifdef Q_OS_WIN
+static const char sshPasswordPromptDefaultC[] = "win-ssh-askpass";
+#else
+static const char sshPasswordPromptDefaultC[] = "ssh-askpass";
+#endif
+
 namespace VCSBase {
 namespace Internal {
 
 CommonVcsSettings::CommonVcsSettings() :
+    sshPasswordPrompt(QLatin1String(sshPasswordPromptDefaultC)),
     lineWrap(lineWrapDefault),
     lineWrapWidth(lineWrapWidthDefault)
 {
@@ -59,6 +67,7 @@ void CommonVcsSettings::toSettings(QSettings *s) const
     s->setValue(QLatin1String(submitMessageCheckScriptKeyC), submitMessageCheckScript);
     s->setValue(QLatin1String(lineWrapKeyC), lineWrap);
     s->setValue(QLatin1String(lineWrapWidthKeyC), lineWrapWidth);
+    s->setValue(QLatin1String(sshPasswordPromptKeyC), sshPasswordPrompt);
     s->endGroup();
 }
 
@@ -70,6 +79,7 @@ void CommonVcsSettings::fromSettings(QSettings *s)
     submitMessageCheckScript = s->value(QLatin1String(submitMessageCheckScriptKeyC), QString()).toString();
     lineWrap = s->value(QLatin1String(lineWrapKeyC), lineWrapDefault).toBool();
     lineWrapWidth = s->value(QLatin1String(lineWrapWidthKeyC), lineWrapWidthDefault).toInt();
+    sshPasswordPrompt = s->value(QLatin1String(sshPasswordPromptKeyC), QLatin1String(sshPasswordPromptDefaultC)).toString();
     s->endGroup();
 }
 
@@ -79,7 +89,8 @@ bool CommonVcsSettings::equals(const CommonVcsSettings &rhs) const
            && lineWrapWidth == rhs.lineWrapWidth
            && nickNameMailMap == rhs.nickNameMailMap
            && nickNameFieldListFile == rhs.nickNameFieldListFile
-           && submitMessageCheckScript == rhs.submitMessageCheckScript;
+           && submitMessageCheckScript == rhs.submitMessageCheckScript
+           && sshPasswordPrompt == rhs.sshPasswordPrompt;
 }
 
 QDebug operator<<(QDebug d,const CommonVcsSettings& s)
@@ -88,7 +99,9 @@ QDebug operator<<(QDebug d,const CommonVcsSettings& s)
             << " lineWrapWidth=" <<  s.lineWrapWidth
             << " nickNameMailMap='" <<  s.nickNameMailMap
             << "' nickNameFieldListFile='" << s.nickNameFieldListFile
-            << "'submitMessageCheckScript='" << s.submitMessageCheckScript << "'\n";
+            << "'submitMessageCheckScript='" << s.submitMessageCheckScript
+            << "'sshPasswordPrompt='" << s.sshPasswordPrompt
+            << "'\n";
     return d;
 }
 
diff --git a/src/plugins/vcsbase/commonvcssettings.h b/src/plugins/vcsbase/commonvcssettings.h
index 985683d28db2c4182477f474291dfa4cb3495ebd..d10666beae2ad6795f2bd010a034578f2754edaf 100644
--- a/src/plugins/vcsbase/commonvcssettings.h
+++ b/src/plugins/vcsbase/commonvcssettings.h
@@ -51,6 +51,9 @@ struct CommonVcsSettings
 
     QString submitMessageCheckScript;
 
+    // Executable run to graphically prompt for a SSH-password.
+    QString sshPasswordPrompt;
+
     bool lineWrap;
     int lineWrapWidth;
 
diff --git a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp
index df6f201d9ad510aea48e31871e7fa48f61978394..6f6036d3804089739ee78e2b484c2fc257806ee5 100644
--- a/src/plugins/vcsbase/vcsbaseoutputwindow.cpp
+++ b/src/plugins/vcsbase/vcsbaseoutputwindow.cpp
@@ -43,6 +43,8 @@
 
 #include <QtCore/QPointer>
 #include <QtCore/QTextCodec>
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
 #include <QtCore/QTime>
 #include <QtCore/QPoint>
 #include <QtCore/QFileInfo>
@@ -367,11 +369,53 @@ void VCSBaseOutputWindow::appendWarning(const QString &text)
         popup(false); // Pop up without focus
 }
 
+// Helper to format arguments for log windows hiding common password
+// options.
+static inline QString formatArguments(const QStringList &args)
+{
+    const char passwordOptionC[] = "--password";
+
+    QString rc;
+    QTextStream str(&rc);
+    const int size = args.size();
+    // Skip authentication options
+    for (int i = 0; i < size; i++) {
+        const QString &arg = args.at(i);
+        if (i)
+            str << ' ';
+        str << arg;
+        if (arg == QLatin1String(passwordOptionC)) {
+            str << " ********";
+            i++;
+        }
+    }
+    return rc;
+}
+
+QString VCSBaseOutputWindow::msgExecutionLogEntry(const QString &workingDir,
+                                                  const QString &executable,
+                                                  const QStringList &arguments)
+{
+    const QString args = formatArguments(arguments);
+    if (workingDir.isEmpty())
+        return tr("Executing: %1 %2\n").arg(executable, args);
+    return tr("Executing in %1: %2 %3\n").
+            arg(QDir::toNativeSeparators(workingDir), executable, args);
+}
+
 void VCSBaseOutputWindow::appendCommand(const QString &text)
 {
     d->plainTextEdit()->appendCommand(text);
 }
 
+void VCSBaseOutputWindow::appendCommand(const QString &workingDirectory,
+                                        const QString &binary,
+                                        const QStringList &args)
+{
+    appendCommand(msgExecutionLogEntry(workingDirectory, binary, args));
+}
+
+
 void VCSBaseOutputWindow::appendData(const QByteArray &data)
 {
     appendDataSilently(data);
diff --git a/src/plugins/vcsbase/vcsbaseoutputwindow.h b/src/plugins/vcsbase/vcsbaseoutputwindow.h
index de65d210d0acb681283c9976112634e5c510db0d..2008c202d7db98e63da60d3d671404e25657c2ad 100644
--- a/src/plugins/vcsbase/vcsbaseoutputwindow.h
+++ b/src/plugins/vcsbase/vcsbaseoutputwindow.h
@@ -77,6 +77,13 @@ public:
 
     QString repository() const;
 
+    // Helper to consistently format log entries for commands as
+    // 'Executing <dir>: <cmd> <args>'. Hides well-known password option
+    // arguments.
+    static QString msgExecutionLogEntry(const QString &workingDir,
+                                        const QString &executable,
+                                        const QStringList &arguments);
+
 public slots:
     void setRepository(const QString &);
     void clearRepository();
@@ -105,6 +112,11 @@ public slots:
     // Append a command, prepended by a log time stamp. "Executing: vcs -diff"
     // will result in "10:00 Executing: vcs -diff" in bold
     void appendCommand(const QString &text);
+    // Append a standard-formatted entry for command execution
+    // (see msgExecutionLogEntry).
+    void appendCommand(const QString &workingDirectory,
+                       const QString &binary,
+                       const QStringList &args);
 
 private:
     VCSBaseOutputWindow();
diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp
index 7b1c3f40c1c3be467ed78692afdc2ab758fb0b1c..6f5d24c48f1839850e6e80196a61eaf8f41d3f72 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.cpp
+++ b/src/plugins/vcsbase/vcsbaseplugin.cpp
@@ -30,6 +30,7 @@
 #include "vcsbaseplugin.h"
 #include "vcsbasesubmiteditor.h"
 #include "vcsplugin.h"
+#include "commonvcssettings.h"
 #include "vcsbaseoutputwindow.h"
 #include "corelistener.h"
 
@@ -43,18 +44,22 @@
 #include <projectexplorer/projectexplorer.h>
 #include <projectexplorer/project.h>
 #include <utils/qtcassert.h>
+#include <utils/synchronousprocess.h>
 
 #include <QtCore/QDebug>
 #include <QtCore/QDir>
 #include <QtCore/QSharedData>
 #include <QtCore/QScopedPointer>
+#include <QtCore/QProcessEnvironment>
+#include <QtCore/QTextStream>
+#include <QtCore/QTextCodec>
 
 #include <QtGui/QAction>
 #include <QtGui/QMessageBox>
 #include <QtGui/QFileDialog>
 #include <QtGui/QMainWindow>
 
-enum { debug = 0, debugRepositorySearch = 0 };
+enum { debug = 0, debugRepositorySearch = 0, debugExecution = 0 };
 
 namespace VCSBase {
 
@@ -670,6 +675,116 @@ QString VCSBasePlugin::findRepositoryForDirectory(const QString &dirS,
     return QString();
 }
 
+// Is SSH prompt configured?
+static inline QString sshPrompt()
+{
+    return VCSBase::Internal::VCSPlugin::instance()->settings().sshPasswordPrompt;
+}
+
+bool VCSBasePlugin::isSshPromptConfigured()
+{
+    return !sshPrompt().isEmpty();
+}
+
+void VCSBasePlugin::setProcessEnvironment(QProcessEnvironment *e)
+{
+    e->insert(QLatin1String("LANG"), QString(QLatin1Char('C')));
+    const QString sshPromptBinary = sshPrompt();
+    if (!sshPromptBinary.isEmpty())
+        e->insert(QLatin1String("SSH_ASKPASS"), sshPromptBinary);
+}
+
+Utils::SynchronousProcessResponse
+        VCSBasePlugin::runVCS(const QString &workingDir,
+                              const QString &binary,
+                              const QStringList &arguments,
+                              int timeOutMS,
+                              unsigned flags,
+                              QTextCodec *outputCodec /* = 0 */)
+{
+    const QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+    return runVCS(workingDir, binary, arguments, timeOutMS, env,
+                  flags, outputCodec);
+}
+
+Utils::SynchronousProcessResponse
+        VCSBasePlugin::runVCS(const QString &workingDir,
+                              const QString &binary,
+                              const QStringList &arguments,
+                              int timeOutMS,
+                              QProcessEnvironment env,
+                              unsigned flags,
+                              QTextCodec *outputCodec /* = 0 */)
+{
+    VCSBase::VCSBaseOutputWindow *outputWindow = VCSBase::VCSBaseOutputWindow::instance();
+
+    if (!(flags & SuppressCommandLogging))
+        outputWindow->appendCommand(workingDir, binary, arguments);
+
+    const bool sshPromptConfigured = VCSBasePlugin::isSshPromptConfigured();
+    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 (outputCodec)
+            nsp << " Codec: " << outputCodec->name();
+    }
+
+    // Run, connect stderr to the output window
+    Utils::SynchronousProcess process;
+    if (!workingDir.isEmpty())
+        process.setWorkingDirectory(workingDir);
+
+    VCSBase::VCSBasePlugin::setProcessEnvironment(&env);
+    process.setProcessEnvironment(env);
+    process.setTimeout(timeOutMS);
+    if (outputCodec)
+        process.setStdOutCodec(outputCodec);
+
+    // Suppress terminal on UNIX for ssh prompts if it is configured.
+    if (sshPromptConfigured && (flags & SshPasswordPrompt))
+        process.setFlags(Utils::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!
+    const Utils::SynchronousProcessResponse sp_resp = process.run(binary, arguments);
+
+    // Fail message?
+    if (sp_resp.result != Utils::SynchronousProcessResponse::Finished &&
+        (!(flags & SuppressFailMessageInLogWindow)))
+        outputWindow->appendError(sp_resp.exitMessage(binary, timeOutMS));
+
+    return sp_resp;
+}
 } // namespace VCSBase
 
 #include "vcsbaseplugin.moc"
diff --git a/src/plugins/vcsbase/vcsbaseplugin.h b/src/plugins/vcsbase/vcsbaseplugin.h
index 5d697fa3af9dbdfde40f34975bd386b39be70ce9..2e090fe62202b29889f85ed8cf3c981731739714 100644
--- a/src/plugins/vcsbase/vcsbaseplugin.h
+++ b/src/plugins/vcsbase/vcsbaseplugin.h
@@ -39,8 +39,14 @@
 
 QT_BEGIN_NAMESPACE
 class QAction;
+class QProcessEnvironment;
+class QTextCodec;
 QT_END_NAMESPACE
 
+namespace Utils {
+    struct SynchronousProcessResponse;
+}
+
 namespace Core {
     class IVersionControl;
 }
@@ -169,6 +175,41 @@ public:
     // a well known file. See implementation for gory details.
     static QString findRepositoryForDirectory(const QString &dir, const QString &checkFile);
 
+    // Set up the environment for a version control command line call.
+    // Sets LANG to 'C' to force English (suppress LOCALE warnings)
+    // and sets up SSH graphical password prompting (note that the latter
+    // requires a terminal-less process).
+    static void setProcessEnvironment(QProcessEnvironment *e);
+    // Returns whether an SSH prompt is configured.
+    static bool isSshPromptConfigured();
+
+    // Convenience to synchronously run VCS commands
+    enum RunVCSFlags {
+        ShowStdOutInLogWindow = 0x1, // Append standard output to VCS output window.
+        MergeOutputChannels = 0x2,   // see QProcess: Merge stderr/stdout.
+        SshPasswordPrompt = 0x40,    // Disable terminal on UNIX to force graphical prompt.
+        SuppressStdErrInLogWindow = 0x8, // No standard error output to VCS output window.
+        SuppressFailMessageInLogWindow = 0x10, // No message VCS about failure in VCS output window.
+        SuppressCommandLogging = 0x20 // No command log entry in VCS output window.
+    };
+
+    static Utils::SynchronousProcessResponse
+            runVCS(const QString &workingDir,
+                   const QString &binary,
+                   const QStringList &arguments,
+                   int timeOutMS,
+                   QProcessEnvironment env,
+                   unsigned flags = 0,
+                   QTextCodec *outputCodec = 0);
+
+    static Utils::SynchronousProcessResponse
+            runVCS(const QString &workingDir,
+                   const QString &binary,
+                   const QStringList &arguments,
+                   int timeOutMS,
+                   unsigned flags = 0,
+                   QTextCodec *outputCodec = 0);
+
 public slots:
     // Convenience slot for "Delete current file" action. Prompts to
     // delete the file via VCSManager.
diff --git a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
index 4ad802e32f696c6e27d9fbad966576ab3b784125..98241014c8cd89c3c16f410c22646a202b07b562 100644
--- a/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
+++ b/src/plugins/vcsbase/vcsbasesubmiteditor.cpp
@@ -584,7 +584,7 @@ bool VCSBaseSubmitEditor::runSubmitMessageCheckScript(const QString &checkScript
     }
     QByteArray stdOutData;
     QByteArray stdErrData;
-    if (!Utils::SynchronousProcess::readDataFromProcess(checkProcess, 30000, &stdOutData, &stdErrData)) {
+    if (!Utils::SynchronousProcess::readDataFromProcess(checkProcess, 30000, &stdOutData, &stdErrData, false)) {
         Utils::SynchronousProcess::stopProcess(checkProcess);
         *errorMessage = tr("The check script '%1' timed out.").arg(checkScript);
         return false;