diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 3a7f5bb932eb8cd232afeafef3de11878a99544b..9d6a6c5b237b4d16aa47fea90f322da91586edc4 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -38,9 +38,6 @@ table {
         .rotate {
           height: 140px;
           white-space: nowrap;
-        }
-
-        .rotate > div {
           transform:
                   /* Magic Numbers */
                   translate(25px, 51px)
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index a3e72fbdef14f474762471dde7f37d0d8105047b..b2ee5573bfc15dc2fe1a9cd4b44b60a0755b4c56 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -1,5 +1,5 @@
 class Projects::PipelinesController < Projects::ApplicationController
-  before_action :ci_commit, except: [:index, :new, :create]
+  before_action :pipeline, except: [:index, :new, :create]
   before_action :authorize_read_pipeline!
   before_action :authorize_create_pipeline!, only: [:new, :create]
   before_action :authorize_update_pipeline!, only: [:retry, :cancel]
@@ -7,26 +7,24 @@ class Projects::PipelinesController < Projects::ApplicationController
 
   def index
     @scope = params[:scope]
-    @all_commits = project.ci_commits
-    @commits = @all_commits.order(id: :desc)
-    @commits =
+    @all_pipelines = project.ci_commits
+    @pipelines = @all_pipelines.order(id: :desc)
+    @pipelines =
       case @scope
-      when 'latest'
-        @commits
       when 'running'
-        @commits.running_or_pending
+        @pipelines.running_or_pending
       when 'branches'
-        refs = project.repository.branches.map(&:name)
-        ids = @all_commits.where(ref: refs).group(:ref).select('max(id)')
-        @commits.where(id: ids)
+        @branches = project.repository.branches.map(&:name)
+        @branches_ids = @all_pipelines.where(ref: @branches).group(:ref).select('max(id)')
+        @pipelines.where(id: @branches_ids)
       when 'tags'
-        refs = project.repository.tags.map(&:name)
-        ids = @all_commits.where(ref: refs).group(:ref).select('max(id)')
-        @commits.where(id: ids)
+        @tags = project.repository.tags.map(&:name)
+        @tags_ids = @all_pipelines.where(ref: @tags).group(:ref).select('max(id)')
+        @pipelines.where(id: @tags_ids)
       else
-        @commits
+        @pipelines
       end
-    @commits = @commits.page(params[:page]).per(30)
+    @pipelines = @pipelines.page(params[:page]).per(30)
   end
 
   def new
@@ -47,56 +45,44 @@ class Projects::PipelinesController < Projects::ApplicationController
       return
     end
 
-    ci_commit = project.ci_commit(commit.id, params[:ref])
-    if ci_commit
-      @error = 'Pipeline already created'
-      render action: 'new'
-      return
-    end
+    pipeline = project.ci_commits.new(sha: commit.id, ref: params[:ref], before_sha: Gitlab::Git::BLANK_SHA)
 
     # Skip creating ci_commit when no gitlab-ci.yml is found
-    commit = project.ci_commits.new(sha: commit.id, ref: params[:ref], before_sha: Gitlab::Git::BLANK_SHA)
-    unless commit.config_processor
-      @error = commit.yaml_errors || 'Missing .gitlab-ci.yml file'
+    unless pipeline.config_processor
+      @error = pipeline.yaml_errors || 'Missing .gitlab-ci.yml file'
       render action: 'new'
       return
     end
 
     Ci::Commit.transaction do
       commit.save!
-      commit.create_builds(params[:ref], false, current_user)
+      commit.create_builds(current_user)
     end
 
     redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.id)
   end
 
   def show
-    @commit = @ci_commit.commit
-    @builds = @ci_commit.builds
-    @statuses = @ci_commit.statuses
-
     respond_to do |format|
       format.html
     end
   end
 
   def retry
-    ci_commit.builds.latest.failed.select(&:retryable?).each(&:retry)
+    pipeline.builds.latest.failed.select(&:retryable?).each(&:retry)
 
     redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project)
   end
 
   def cancel
-    ci_commit.builds.running_or_pending.each(&:cancel)
+    pipeline.builds.running_or_pending.each(&:cancel)
 
     redirect_back_or_default default: namespace_project_pipelines_path(project.namespace, project)
   end
 
-  def retry_builds
-  end
   private
 
-  def ci_commit
-    @ci_commit ||= project.ci_commits.find_by!(id: params[:id])
+  def pipeline
+    @pipeline ||= project.ci_commits.find_by!(id: params[:id])
   end
 end
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index 687654d3c89b2d4321dd7ecc6f27e561d6b8f3c8..7991b987e3595b26f9e6ea5a6e63943cb54a21fb 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -94,6 +94,13 @@ module Ci
       end
     end
 
+    def latest?
+      return false unless ref
+      commit = project.commit(ref)
+      return false unless commit
+      commit.sha == sha
+    end
+
     def triggered?
       trigger_requests.any?
     end
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 218d396b898470d2e9642d18c1a07c1a028f22f5..7ded4828b2fc69b7570e8fdfc65d9dfe4e438e0d 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -13,7 +13,9 @@
       %strong ##{build.id}
 
     - if build.stuck?
-      %i.fa.fa-warning.text-warning
+      %i.fa.fa-warning.text-warning.has-tooltip(title="Build is stuck. Check runners.")
+    - if defined?(retried) && retried
+      %i.fa.fa-warning.has-tooltip(title="Build was retried")
 
   - if defined?(commit_sha) && commit_sha
     %td
diff --git a/app/views/projects/ci/commits/_commit.html.haml b/app/views/projects/ci/commits/_commit.html.haml
index 7c6ba2163863131b340d68200baf9c3fc29d9d81..32f85cb8f8c4419f6dc577aa4537e2815c5d8881 100644
--- a/app/views/projects/ci/commits/_commit.html.haml
+++ b/app/views/projects/ci/commits/_commit.html.haml
@@ -1,19 +1,21 @@
 - status = commit.status
 %tr.commit
   %td.commit-link
-    = link_to namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "ci-status ci-#{status}" do
+    = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: "ci-status ci-#{status}" do
       = ci_icon_for_status(status)
       %strong ##{commit.id}
 
   %td
-    %div
+    %div.branch-commit
       - if commit.ref
-        = link_to commit.ref, namespace_project_commits_path(@project.namespace, @project, commit.ref)
+        = link_to commit.ref, namespace_project_commits_path(@project.namespace, @project, commit.ref), class: "monospace"
+        &middot;
+      = link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace"
       &nbsp;
+      - if commit.latest?
+        %span.label.label-success latest
       - if commit.tag?
         %span.label.label-primary tag
-      - if commit.branch?
-        %span.label.label-primary branch
       - if commit.triggered?
         %span.label.label-primary triggered
       - if commit.yaml_errors.present?
@@ -21,32 +23,36 @@
       - if commit.builds.any?(&:stuck?)
         %span.label.label-warning stuck
 
-      - if commit_data = commit.commit_data
-        = render 'projects/branches/commit', commit: commit_data, project: @project
-      - else
-        %p
-          Cant find HEAD commit for this branch
+      %p
+        %span
+          - if commit_data = commit.commit_data
+            = link_to_gfm commit_data.title, namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message"
+          - else
+            Cant find HEAD commit for this branch
+
 
     - stages_status = commit.statuses.stages_status
     - stages.each do |stage|
       %td
         - if status = stages_status[stage]
-          %span.has-tooltip(title="#{status}"){class: "ci-status-icon-#{status}"}
+          %span.has-tooltip(title="#{stage.titleize}: #{status}"){class: "ci-status-icon-#{status}"}
             = ci_icon_for_status(status)
 
   %td
     - if commit.started_at && commit.finished_at
       %p
-        %i.fa.fa-late-o
+        %i.fa.fa-clock-o
+        &nbsp;
         #{duration_in_words(commit.finished_at, commit.started_at)}
     - if commit.finished_at
       %p
-        %i.fa.fa-date-o
+        %i.fa.fa-calendar
+        &nbsp;
         #{time_ago_with_tooltip(commit.finished_at)}
 
-  %td.content
+  %td
     .controls.hidden-xs.pull-right
-      - artifacts = commit.builds.latest.select { |status| status.artifacts? }
+      - artifacts = commit.builds.latest
       - if artifacts.present?
         .dropdown.inline
           %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
@@ -58,15 +64,12 @@
                 = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do
                   %i.fa.fa-download
                   %span #{build.name}
-        &nbsp;
 
       - if can?(current_user, :update_pipeline, @project)
-        - if commit.retryable?
+        - if commit.retryable? && commit.builds.failed.any?
           = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do
             = icon("repeat")
-
         &nbsp;
-
         - if commit.active?
           = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do
             = icon("remove cred")
diff --git a/app/views/projects/commit/_ci_commit.html.haml b/app/views/projects/commit/_ci_commit.html.haml
index 06520e40bd96170e0fcf7cba70972a9832d15322..582ce61a64a3380121c3f897b88c883d4a9e9af2 100644
--- a/app/views/projects/commit/_ci_commit.html.haml
+++ b/app/views/projects/commit/_ci_commit.html.haml
@@ -2,12 +2,15 @@
   .pull-right
     - if can?(current_user, :update_build, @project)
       - if ci_commit.builds.latest.failed.any?(&:retryable?)
-        = link_to "Retry failed", retry_builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), class: 'btn btn-grouped btn-primary', method: :post
+        = link_to "Retry failed", retry_namespace_project_pipeline_path(@project.namespace, @project, ci_commit.id), class: 'btn btn-grouped btn-primary', method: :post
 
       - if ci_commit.builds.running_or_pending.any?
-        = link_to "Cancel running", cancel_builds_namespace_project_commit_path(@project.namespace, @project, @commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
+        = link_to "Cancel running", cancel_namespace_project_pipeline_path(@project.namespace, @project, ci_commit.id), data: { confirm: 'Are you sure?' }, class: 'btn btn-grouped btn-danger', method: :post
 
   .oneline
+    Pipeline
+    = link_to "##{ci_commit.id}", namespace_project_pipeline_path(@project.namespace, @project, ci_commit.id), class: "monospace"
+    with
     = pluralize ci_commit.statuses.count(:id), "build"
     - if ci_commit.ref
       for
@@ -17,7 +20,7 @@
       for commit
       = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit.id), class: "monospace"
     - if ci_commit.duration > 0
-      in
+      took
       = time_interval_in_words ci_commit.duration
 
 - if ci_commit.yaml_errors.present?
@@ -47,23 +50,4 @@
         %th
     - builds = ci_commit.statuses.latest.ordered
     = render builds, coverage: @project.build_coverage_enabled?, stage: true, ref: false, allow_retry: true
-
-- if ci_commit.retried.any?
-  .gray-content-block.second-block
-    Retried builds
-
-  .table-holder
-    %table.table.builds
-      %thead
-        %tr
-          %th Status
-          %th Build ID
-          %th Ref
-          %th Stage
-          %th Name
-          %th Duration
-          %th Finished at
-          - if @project.build_coverage_enabled?
-            %th Coverage
-          %th
-      = render ci_commit.retried, coverage: @project.build_coverage_enabled?, stage: true, ref: false
+    = render ci_commit.retried, coverage: @project.build_coverage_enabled?, stage: true, ref: false, retried: true
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index b9877cd37beb3c9be70040e07652ded2294d3929..838b2986d4fa5bef7094be47685f8b2d602e2ffd 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -7,25 +7,21 @@
       = link_to project_pipelines_path(@project) do
         All
         %span.badge.js-totalbuilds-count
-          = number_with_delimiter(@all_commits.count(:id))
+          = number_with_delimiter(@all_pipelines.count)
+
+    %li{class: ('active' if @scope == 'running')}
+      = link_to project_pipelines_path(@project, scope: :running) do
+        Running
+        %span.badge.js-running-count
+          = number_with_delimiter(@all_pipelines.running_or_pending.count)
 
     %li{class: ('active' if @scope == 'branches')}
       = link_to project_pipelines_path(@project, scope: :branches) do
         Branches
-        %span.badge.js-running-count
-          = number_with_delimiter(@all_commits.running_or_pending.count(:id))
 
     %li{class: ('active' if @scope == 'tags')}
       = link_to project_pipelines_path(@project, scope: :tags) do
         Tags
-        %span.badge.js-running-count
-          = number_with_delimiter(@all_commits.running_or_pending.count(:id))
-
-    %li{class: ('active' if @scope == 'running')}
-      = link_to project_pipelines_path(@project, scope: :running) do
-        Failed
-        %span.badge.js-running-count
-          = number_with_delimiter(@all_commits.running_or_pending.count(:id))
 
   .nav-controls
     - if can? current_user, :create_pipeline, @project
@@ -45,8 +41,8 @@
   Pipelines for #{(@scope || 'changes')} on this project
 
 %ul.content-list
-  - stages = @commits.stages
-  - if @commits.blank?
+  - stages = @pipelines.stages
+  - if @pipelines.blank?
     %li
       .nothing-here-block No pipelines to show
   - else
@@ -55,11 +51,12 @@
         %tbody
           %th Pipeline ID
           %th Commit
-          - @commits.stages.each do |stage|
-            %th.rotate
-              = stage.titleize
+          - @pipelines.stages.each do |stage|
+            %th
+              %span.has-tooltip(title="#{stage.titleize}")
+                = truncate(stage.titleize.pluralize, length: 8)
           %th
           %th
-        = render @commits, commit_sha: true, stage: true, allow_retry: true, stages: stages
+        = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages
 
-    = paginate @commits, theme: 'gitlab'
+    = paginate @pipelines, theme: 'gitlab'
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..9f33e2ad624acad17837a55ea05edf70c9388476
--- /dev/null
+++ b/app/views/projects/pipelines/show.html.haml
@@ -0,0 +1,3 @@
+- page_title "Pipeline"
+= render "header_title"
+= render "projects/commit/ci_commit", ci_commit: @pipeline
diff --git a/config/routes.rb b/config/routes.rb
index 841b3f262721cecffaa3aba2a02900757d1ac2c9..6384757835abaf03bac929b7bfdc9ad99be65e31 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -654,7 +654,7 @@ Rails.application.routes.draw do
         resource :variables, only: [:show, :update]
         resources :triggers, only: [:index, :create, :destroy]
 
-        resources :pipelines, only: [:index, :new, :create] do
+        resources :pipelines, only: [:index, :new, :create, :show] do
           member do
             post :cancel
             post :retry