diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index 67b456755bb61013b631959f3b982b54d37d4a34..1dd2f0502e12fe72abc78583567cc72378fe598f 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -340,6 +340,37 @@ private:
     QString m_commit;
 };
 
+class RebaseManager : public QObject
+{
+    Q_OBJECT
+
+public:
+    RebaseManager(QObject *parent) : QObject(parent)
+    {
+    }
+
+public slots:
+    void readStdErr(const QString &error)
+    {
+        // rebase conflict is output to stdOut
+        QRegExp conflictedCommit(QLatin1String("Could not apply ([^\\n]*)"));
+        conflictedCommit.indexIn(error);
+        m_commit = conflictedCommit.cap(1);
+    }
+
+    void finished(bool ok, int exitCode, const QVariant &workingDirectory)
+    {
+        Q_UNUSED(ok);
+        if (exitCode != 0 && !m_commit.isEmpty()) {
+            GitPlugin::instance()->gitClient()->handleMergeConflicts(
+                        workingDirectory.toString(), m_commit, QLatin1String("rebase"));
+        }
+    }
+
+private:
+    QString m_commit;
+};
+
 Core::IEditor *locateEditor(const char *property, const QString &entry)
 {
     foreach (Core::IEditor *ed, Core::ICore::editorManager()->openedEditors())
@@ -434,7 +465,7 @@ QString GitClient::findRepositoryForDirectory(const QString &dir)
     return QString();
 }
 
-QString GitClient::findGitDirForRepository(const QString &repositoryDir)
+QString GitClient::findGitDirForRepository(const QString &repositoryDir) const
 {
     static QHash<QString, QString> repoDirCache;
     QString &res = repoDirCache[repositoryDir];
@@ -2335,6 +2366,19 @@ bool GitClient::synchronousMerge(const QString &workingDirectory, const QString
     return executeAndHandleConflicts(workingDirectory, arguments, command);
 }
 
+bool GitClient::canRebase(const QString &workingDirectory) const
+{
+    const QString gitDir = findGitDirForRepository(workingDirectory);
+    if (QFileInfo(gitDir + QLatin1String("/rebase-apply")).exists()
+            || QFileInfo(gitDir + QLatin1String("/rebase-merge")).exists()) {
+        VcsBase::VcsBaseOutputWindow::instance()->appendError(
+                    tr("Rebase, merge or am is in progress. Please finish "
+                       "or abort it then try again"));
+        return false;
+    }
+    return true;
+}
+
 bool GitClient::synchronousRebase(const QString &workingDirectory, const QString &baseBranch,
                                   const QString &topicBranch)
 {
@@ -2366,6 +2410,21 @@ bool GitClient::cherryPickCommit(const QString &workingDirectory, const QString
     return executeAndHandleConflicts(workingDirectory, arguments, command);
 }
 
+void GitClient::interactiveRebase(const QString &workingDirectory, const QString &commit)
+{
+    QStringList arguments;
+    arguments << QLatin1String("rebase") << QLatin1String("-i") << commit;
+    outputWindow()->appendCommand(workingDirectory, settings()->stringValue(GitSettings::binaryPathKey), arguments);
+    VcsBase::Command *command = createCommand(workingDirectory, 0, true);
+    command->addJob(arguments, -1);
+    command->execute();
+    command->setCookie(workingDirectory);
+    RebaseManager *rebaseManager = new RebaseManager(command);
+    connect(command, SIGNAL(errorText(QString)), rebaseManager, SLOT(readStdErr(QString)));
+    connect(command, SIGNAL(finished(bool,int,QVariant)),
+            rebaseManager, SLOT(finished(bool,int,QVariant)));
+}
+
 QString GitClient::msgNoChangedFiles()
 {
     return tr("There are no modified files.");
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 63344a8562a0ebc74d4991bbaa6a715ede0a8468..0109f44b1f4182029579d547a0b22ce29327c4a3 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -111,7 +111,7 @@ public:
     unsigned gitVersion(QString *errorMessage = 0) const;
 
     QString findRepositoryForDirectory(const QString &dir);
-    QString findGitDirForRepository(const QString &repositoryDir);
+    QString findGitDirForRepository(const QString &repositoryDir) const;
 
     void diff(const QString &workingDirectory, const QStringList &diffArgs, const QString &fileName);
     void diff(const QString &workingDirectory, const QStringList &diffArgs,
@@ -199,11 +199,13 @@ public:
     bool synchronousPull(const QString &workingDirectory, bool rebase);
     bool synchronousPush(const QString &workingDirectory, const QString &remote = QString());
     bool synchronousMerge(const QString &workingDirectory, const QString &branch);
+    bool canRebase(const QString &workingDirectory) const;
     bool synchronousRebase(const QString &workingDirectory,
                            const QString &baseBranch,
                            const QString &topicBranch = QString());
     bool revertCommit(const QString &workingDirectory, const QString &commit);
     bool cherryPickCommit(const QString &workingDirectory, const QString &commit);
+    void interactiveRebase(const QString &workingDirectory, const QString &commit);
     void synchronousAbortCommand(const QString &workingDir, const QString &abortCommand);
 
     // git svn support (asynchronous).
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 59d9d4edd4ee10293ad43d40639f07ee658b17d0..00ce0ca5f241052e63c650edd779870df14a33ba 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -435,6 +435,10 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *errorMessage)
                            tr("Reset..."), Core::Id("Git.Reset"),
                            globalcontext, false, SLOT(resetRepository()));
 
+    createRepositoryAction(localRepositoryMenu,
+                           tr("Interactive Rebase..."), Core::Id("Git.Rebase"),
+                           globalcontext, true, SLOT(startRebase()));
+
     createRepositoryAction(localRepositoryMenu,
                            tr("Revert Single Commit..."), Core::Id("Git.Revert"),
                            globalcontext, true, SLOT(startRevertCommit()));
@@ -719,6 +723,24 @@ void GitPlugin::resetRepository()
         }
 }
 
+void GitPlugin::startRebase()
+{
+    QString workingDirectory = currentState().currentDirectoryOrTopLevel();
+    if (workingDirectory.isEmpty() || !m_gitClient->canRebase(workingDirectory))
+        return;
+    GitClient::StashGuard stashGuard(workingDirectory, QLatin1String("Rebase-i"));
+    if (stashGuard.stashingFailed(true))
+        return;
+    stashGuard.preventPop();
+    LogChangeDialog dialog(false);
+    dialog.setWindowTitle(tr("Interactive Rebase"));
+    if (!dialog.runDialog(workingDirectory))
+        return;
+    const QString change = dialog.commit();
+    if (!change.isEmpty())
+        m_gitClient->interactiveRebase(workingDirectory, change);
+}
+
 void GitPlugin::startRevertCommit()
 {
     const VcsBase::VcsBasePluginState state = currentState();
diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h
index 3b373ecc7625b83be487602217c2ca4710f2d364..e0ffc8a45ab3c2499b4555ede68819e2b9479201 100644
--- a/src/plugins/git/gitplugin.h
+++ b/src/plugins/git/gitplugin.h
@@ -116,6 +116,7 @@ private slots:
     void undoFileChanges(bool revertStaging = true);
     void undoUnstagedFileChanges();
     void resetRepository();
+    void startRebase();
     void startRevertCommit();
     void startCherryPickCommit();
     void stageFile();