diff --git a/CHANGELOG b/CHANGELOG
index 760d3c0e2de303703f75d42594d89328dd6b3020..a0a7fe59e86f8c209059528f9870184c725651e7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 Please view this file on the master branch, on stable branches it's out of date.
 
 v 8.12.0 (unreleased)
+  - Filter tags by name !6121
   - Make push events have equal vertical spacing.
   - Add two-factor recovery endpoint to internal API !5510
   - Remove vendor prefixes for linear-gradient CSS (ClemMakesApps)
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 8592579abbd18a6174f6401e637fc6c135fabd23..6ea8ee62bc59e57fc1248347dbf0938b69272556 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -1,4 +1,6 @@
 class Projects::TagsController < Projects::ApplicationController
+  include SortingHelper
+
   # Authorize
   before_action :require_non_empty_project
   before_action :authorize_download_code!
@@ -6,8 +8,10 @@ class Projects::TagsController < Projects::ApplicationController
   before_action :authorize_admin_project!, only: [:destroy]
 
   def index
-    @sort = params[:sort] || 'name'
-    @tags = @repository.tags_sorted_by(@sort)
+    params[:sort] = params[:sort].presence || 'name'
+
+    @sort = params[:sort]
+    @tags = TagsFinder.new(@repository, params).execute
     @tags = Kaminari.paginate_array(@tags).page(params[:page])
 
     @releases = project.releases.where(tag: @tags.map(&:name))
diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b474f0805dcdddd9c15f060819e0b8dfbabcfeff
--- /dev/null
+++ b/app/finders/tags_finder.rb
@@ -0,0 +1,29 @@
+class TagsFinder
+  def initialize(repository, params)
+    @repository = repository
+    @params = params
+  end
+
+  def execute
+    tags = @repository.tags_sorted_by(sort)
+    filter_by_name(tags)
+  end
+
+  private
+
+  def sort
+    @params[:sort].presence
+  end
+
+  def search
+    @params[:search].presence
+  end
+
+  def filter_by_name(tags)
+    if search
+      tags.select { |tag| tag.name.include?(search) }
+    else
+      tags
+    end
+  end
+end
diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb
index fb85544df2d7a9da130de651631bf962562cfd6a..c0ec1634cdb83b5cb004afcd8e06886892e430e1 100644
--- a/app/helpers/tags_helper.rb
+++ b/app/helpers/tags_helper.rb
@@ -3,6 +3,16 @@ module TagsHelper
     "/tags/#{tag}"
   end
 
+  def filter_tags_path(options = {})
+    exist_opts = {
+      search: params[:search],
+      sort: params[:sort]
+    }
+
+    options = exist_opts.merge(options)
+    namespace_project_tags_path(@project.namespace, @project, @id, options)
+  end
+
   def tag_list(project)
     html = ''
     project.tag_list.each do |tag|
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 368231e73fe6cae1daa6c85b64badebad0b2aa99..6adbe9351dcec5d3c7b3734c08c990d7139dd98e 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -8,21 +8,24 @@
       Tags give the ability to mark specific points in history as being important
 
     .nav-controls
-      - if can? current_user, :push_code, @project
-        = link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do
-          New tag
+      = form_tag(filter_tags_path, method: :get) do
+        = search_field_tag :search, params[:search], { placeholder: 'Filter by tag name', id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false }
       .dropdown.inline
         %button.dropdown-toggle.btn{ type: 'button', data: { toggle: 'dropdown'} }
-          %span.light= @sort.humanize
+          %span.light
+            = @sort.humanize
           %b.caret
         %ul.dropdown-menu.dropdown-menu-align-right
           %li
-            = link_to namespace_project_tags_path(sort: nil) do
+            = link_to filter_tags_path(sort: nil) do
               Name
-            = link_to namespace_project_tags_path(sort: sort_value_recently_updated) do
+            = link_to filter_tags_path(sort: sort_value_recently_updated) do
               = sort_title_recently_updated
-            = link_to namespace_project_tags_path(sort: sort_value_oldest_updated) do
+            = link_to filter_tags_path(sort: sort_value_oldest_updated) do
               = sort_title_oldest_updated
+      - if can?(current_user, :push_code, @project)
+        = link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do
+          New tag
 
   .tags
     - if @tags.any?
diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2ac810e478ae7de82fbbb925f0882a887d4d8be2
--- /dev/null
+++ b/spec/finders/tags_finder_spec.rb
@@ -0,0 +1,79 @@
+require 'spec_helper'
+
+describe TagsFinder do
+  let(:user) { create(:user) }
+  let(:project) { create(:project) }
+  let(:repository) { project.repository }
+
+  describe '#execute' do
+    context 'sort only' do
+      it 'sorts by name' do
+        tags_finder = described_class.new(repository, {})
+
+        result = tags_finder.execute
+
+        expect(result.first.name).to eq("v1.0.0")
+      end
+
+      it 'sorts by recently_updated' do
+        tags_finder = described_class.new(repository, { sort: 'updated_desc' })
+
+        result = tags_finder.execute
+        recently_updated_tag = repository.tags.max do |a, b|
+          repository.commit(a.target).committed_date <=> repository.commit(b.target).committed_date
+        end
+
+        expect(result.first.name).to eq(recently_updated_tag.name)
+      end
+
+      it 'sorts by last_updated' do
+        tags_finder = described_class.new(repository, { sort: 'updated_asc' })
+
+        result = tags_finder.execute
+
+        expect(result.first.name).to eq('v1.0.0')
+      end
+    end
+
+    context 'filter only' do
+      it 'filters tags by name' do
+        tags_finder = described_class.new(repository, { search: '1.0.0' })
+
+        result = tags_finder.execute
+
+        expect(result.first.name).to eq('v1.0.0')
+        expect(result.count).to eq(1)
+      end
+
+      it 'does not find any tags with that name' do
+        tags_finder = described_class.new(repository, { search: 'hey' })
+
+        result = tags_finder.execute
+
+        expect(result.count).to eq(0)
+      end
+    end
+
+    context 'filter and sort' do
+      it 'filters tags by name and sorts by recently_updated' do
+        params = { sort: 'updated_desc', search: 'v1' }
+        tags_finder = described_class.new(repository, params)
+
+        result = tags_finder.execute
+
+        expect(result.first.name).to eq('v1.1.0')
+        expect(result.count).to eq(2)
+      end
+
+      it 'filters tags by name and sorts by last_updated' do
+        params = { sort: 'updated_asc', search: 'v1' }
+        tags_finder = described_class.new(repository, params)
+
+        result = tags_finder.execute
+
+        expect(result.first.name).to eq('v1.0.0')
+        expect(result.count).to eq(2)
+      end
+    end
+  end
+end