diff --git a/src/plugins/git/git.pro b/src/plugins/git/git.pro
index 756865db59a1ab5dcd8f1f1a93f681dbb954caaa..fb887a2e55e559d31c13d34b6de66c6d6dda9f0a 100644
--- a/src/plugins/git/git.pro
+++ b/src/plugins/git/git.pro
@@ -27,7 +27,8 @@ HEADERS += gitplugin.h \
     gitutils.h \
     remotemodel.h \
     remotedialog.h \
-    branchadddialog.h
+    branchadddialog.h \
+    resetdialog.h
 
 SOURCES += gitplugin.cpp \
     gitclient.cpp \
@@ -48,7 +49,8 @@ SOURCES += gitplugin.cpp \
     gitutils.cpp \
     remotemodel.cpp \
     remotedialog.cpp \
-    branchadddialog.cpp
+    branchadddialog.cpp \
+    resetdialog.cpp
 
 FORMS += changeselectiondialog.ui \
     settingspage.ui \
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index a810c9c33e6c22e511ee9bfcba67ec5e743ad182..1186ca8abcd6fcc0ee36b40db54d98ddcd581104 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -825,6 +825,30 @@ void GitClient::addFile(const QString &workingDirectory, const QString &fileName
     executeGit(workingDirectory, arguments, 0, true);
 }
 
+bool GitClient::synchronousLog(const QString &workingDirectory, const QStringList &arguments,
+                               QString *output, QString *errorMessageIn)
+{
+    QByteArray outputText;
+    QByteArray errorText;
+    QStringList allArguments;
+    allArguments << QLatin1String("log") << QLatin1String(GitClient::noColorOption);
+    allArguments.append(arguments);
+    const bool rc = fullySynchronousGit(workingDirectory, allArguments, &outputText, &errorText);
+    if (rc) {
+        *output = commandOutputFromLocal8Bit(outputText);
+    } else {
+        const QString errorMessage = tr("Cannot obtain log of \"%1\": %2").
+                                     arg(QDir::toNativeSeparators(workingDirectory),
+                                         commandOutputFromLocal8Bit(errorText));
+        if (errorMessageIn) {
+            *errorMessageIn = errorMessage;
+        } else {
+            outputWindow()->appendError(errorMessage);
+        }
+    }
+    return rc;
+}
+
 // Warning: 'intendToAdd' works only from 1.6.1 onwards
 bool GitClient::synchronousAdd(const QString &workingDirectory,
                                bool intendToAdd,
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 011085223803824eaff679d70de4b71fc6ad65c2..4b9856b242121424098f3b748de1150714eee611 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -107,6 +107,9 @@ public:
     void checkoutBranch(const QString &workingDirectory, const QString &branch);
     void hardReset(const QString &workingDirectory, const QString &commit = QString());
     void addFile(const QString &workingDirectory, const QString &fileName);
+    bool synchronousLog(const QString &workingDirectory,
+                        const QStringList &arguments,
+                        QString *output, QString *errorMessage = 0);
     bool synchronousAdd(const QString &workingDirectory,
                         // Warning: Works only from 1.6.1 onwards
                         bool intendToAdd,
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 427ff643506faa78539c572bcbccedd8b3b089e0..5f0b1568aaa3d3b3672378e95885dff711e0a244 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -45,6 +45,7 @@
 #include "gitoriousclonewizard.h"
 #include "stashdialog.h"
 #include "settingspage.h"
+#include "resetdialog.h"
 
 #include <gerritplugin.h>
 
@@ -643,15 +644,10 @@ void GitPlugin::undoRepositoryChanges()
 {
     const VcsBase::VcsBasePluginState state = currentState();
     QTC_ASSERT(state.hasTopLevel(), return);
-    const QString msg = tr("Undo all pending changes to the repository\n%1?").arg(QDir::toNativeSeparators(state.topLevel()));
-    const QMessageBox::StandardButton answer
-            = QMessageBox::question(Core::ICore::mainWindow(),
-                                    tr("Undo Changes"), msg,
-                                    QMessageBox::Yes|QMessageBox::No,
-                                    QMessageBox::No);
-    if (answer == QMessageBox::No)
-        return;
-    m_gitClient->hardReset(state.topLevel(), QString());
+
+    ResetDialog dialog;
+    if (dialog.runDialog(state.topLevel()))
+        m_gitClient->hardReset(state.topLevel(), dialog.commit());
 }
 
 void GitPlugin::stageFile()
diff --git a/src/plugins/git/resetdialog.cpp b/src/plugins/git/resetdialog.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..225ce2a0d66de1f8738c0125f19ffd9dd1f564b4
--- /dev/null
+++ b/src/plugins/git/resetdialog.cpp
@@ -0,0 +1,145 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#include "resetdialog.h"
+#include "gitplugin.h"
+#include "gitclient.h"
+
+#include <QTreeView>
+#include <QLabel>
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QStandardItemModel>
+#include <QItemSelectionModel>
+#include <QVBoxLayout>
+#include <QDir>
+
+namespace Git {
+namespace Internal {
+
+enum Columns
+{
+    Sha1Column,
+    SubjectColumn,
+    ColumnCount
+};
+
+ResetDialog::ResetDialog(QWidget *parent)
+    : QDialog(parent)
+    , m_treeView(new QTreeView(this))
+    , m_model(new QStandardItemModel(0, ColumnCount, this))
+    , m_dialogButtonBox(new QDialogButtonBox(this))
+{
+    QStringList headers;
+    headers << tr("Sha1")<< tr("Subject");
+    m_model->setHorizontalHeaderLabels(headers);
+    QVBoxLayout *layout = new QVBoxLayout(this);
+    layout->addWidget(new QLabel(tr("Reset to:")));
+    m_treeView->setModel(m_model);
+    m_treeView->setMinimumWidth(300);
+    m_treeView->setUniformRowHeights(true);
+    m_treeView->setRootIsDecorated(false);
+    m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
+    layout->addWidget(m_treeView);
+    layout->addWidget(m_dialogButtonBox);
+    m_dialogButtonBox->addButton(QDialogButtonBox::Cancel);
+    QPushButton *okButton = m_dialogButtonBox->addButton(QDialogButtonBox::Ok);
+    connect(m_treeView, SIGNAL(doubleClicked(QModelIndex)),
+            okButton, SLOT(animateClick()));
+
+    connect(m_dialogButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
+    connect(m_dialogButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+    resize(600, 400);
+}
+
+bool ResetDialog::runDialog(const QString &repository)
+{
+    setWindowTitle(tr("Undo Changes to %1").arg(QDir::toNativeSeparators(repository)));
+
+    if (!populateLog(repository) || !m_model->rowCount())
+        return QDialog::Rejected;
+
+    m_treeView->selectionModel()->select(m_model->index(0, 0),
+                                         QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+
+    return exec() == QDialog::Accepted;
+}
+
+QString ResetDialog::commit() const
+{
+    // Return Sha1, or empty for top commit.
+    if (const QStandardItem *sha1Item = currentItem(Sha1Column))
+        return sha1Item->row() ? sha1Item->text() :  QString();
+    return QString();
+}
+
+bool ResetDialog::populateLog(const QString &repository)
+{
+    if (const int rowCount = m_model->rowCount())
+        m_model->removeRows(0, rowCount);
+
+    // Retrieve log using a custom format "Sha1:Subject"
+    GitClient *client = GitPlugin::instance()->gitClient();
+    QStringList arguments;
+    arguments << QLatin1String("--max-count=30") << QLatin1String("--format=%h:%s");
+    QString output;
+    if (!client->synchronousLog(repository, arguments, &output))
+        return false;
+    foreach (const QString &line, output.split(QLatin1Char('\n'))) {
+        const int colonPos = line.indexOf(QLatin1Char(':'));
+        if (colonPos != -1) {
+            QList<QStandardItem *> row;
+            for (int c = 0; c < ColumnCount; ++c) {
+                QStandardItem *item = new QStandardItem;
+                item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+                row.push_back(item);
+            }
+            row[Sha1Column]->setText(line.left(colonPos));
+            row[SubjectColumn]->setText(line.right(line.size() - colonPos - 1));
+            m_model->appendRow(row);
+        }
+    }
+    return true;
+}
+
+const QStandardItem *ResetDialog::currentItem(int column) const
+{
+    const QModelIndex currentIndex = m_treeView->selectionModel()->currentIndex();
+    if (currentIndex.isValid())
+        return m_model->item(currentIndex.row(), column);
+    return 0;
+}
+
+} // namespace Internal
+} // namespace Git
diff --git a/src/plugins/git/resetdialog.h b/src/plugins/git/resetdialog.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9945aaee82c7b38573ff1e04ec688581f06b4bd
--- /dev/null
+++ b/src/plugins/git/resetdialog.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**************************************************************************/
+
+#ifndef GIT_INTERNAL_RESETDIALOG_H
+#define GIT_INTERNAL_RESETDIALOG_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+class QTreeView;
+class QDialogButtonBox;
+class QStandardItemModel;
+class QStandardItem;
+QT_END_NAMESPACE
+
+namespace Git {
+namespace Internal {
+
+// A dialog that lists SHA1 and subject of the changes
+// for reset --hard.
+
+class ResetDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    explicit ResetDialog(QWidget *parent = 0);
+
+    bool runDialog(const QString &repository);
+
+    QString commit() const;
+
+private:
+    bool populateLog(const QString &repository);
+    const QStandardItem *currentItem(int column = 0) const;
+
+    QTreeView *m_treeView;
+    QStandardItemModel *m_model;
+    QDialogButtonBox *m_dialogButtonBox;
+};
+
+} // namespace Internal
+} // namespace Git
+
+#endif // GIT_INTERNAL_RESETDIALOG_H