diff --git a/app/finders/branches_finder.rb b/app/finders/branches_finder.rb
index 970efa79dfb78107b50d26acda5337dec5108de6..45d5591e81b3d9e97186df07eaa956ccf4e8629c 100644
--- a/app/finders/branches_finder.rb
+++ b/app/finders/branches_finder.rb
@@ -7,8 +7,9 @@ def initialize(repository, params = {})
   end
 
   def execute
-    branches = @repository.branches_sorted_by(sort)
-    filter_by_name(branches)
+    branches = repository.branches_sorted_by(sort)
+    branches = by_search(branches)
+    branches
   end
 
   private
@@ -23,11 +24,39 @@ def sort
     @params[:sort].presence || 'name'
   end
 
-  def filter_by_name(branches)
-    if search
-      branches.select { |branch| branch.name.upcase.include?(search.upcase) }
+  def by_search(branches)
+    return branches unless search
+
+    case search
+    when ->(v) { v.starts_with?('^') }
+      filter_branches_with_prefix(branches, search.slice(1..-1).upcase)
+    when ->(v) { v.ends_with?('$') }
+      filter_branches_with_suffix(branches, search.chop.upcase)
     else
-      branches
+      matches = filter_branches_by_name(branches, search.upcase)
+      set_exact_match_as_first_result(matches, search)
     end
   end
+
+  def filter_branches_with_prefix(branches, prefix)
+    branches.select { |branch| branch.name.upcase.starts_with?(prefix) }
+  end
+
+  def filter_branches_with_suffix(branches, suffix)
+    branches.select { |branch| branch.name.upcase.ends_with?(suffix) }
+  end
+
+  def filter_branches_by_name(branches, term)
+    branches.select { |branch| branch.name.upcase.include?(term) }
+  end
+
+  def set_exact_match_as_first_result(matches, term)
+    exact_match_index = find_exact_match_index(matches, term)
+    matches.insert(0, matches.delete_at(exact_match_index)) if exact_match_index
+    matches
+  end
+
+  def find_exact_match_index(matches, term)
+    matches.index { |branch| branch.name.casecmp(term) == 0 }
+  end
 end
diff --git a/changelogs/unreleased/feature-improved-branch-filter-sorting.yml b/changelogs/unreleased/feature-improved-branch-filter-sorting.yml
new file mode 100644
index 0000000000000000000000000000000000000000..539c297e0dda36cb2201834a0102c8f0d3f86be9
--- /dev/null
+++ b/changelogs/unreleased/feature-improved-branch-filter-sorting.yml
@@ -0,0 +1,6 @@
+---
+title: Improving branch filter sorting by listing exact matches first and added support
+  for begins_with (^) and ends_with ($) matching.
+merge_request: 22166
+author: Jason Rutherford
+type: changed
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index 22ef11e404925f8433b08fa247cff4f3819ba9d1..06b3779668b88a973950bc4ede7f29f1974c6a0e 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -12,9 +12,11 @@ to cherry-pick the changes introduced by that merge request.
 
 ![Cherry-pick Merge Request](img/cherry_pick_changes_mr.png)
 
-After you click that button, a modal will appear where you can choose to
-cherry-pick the changes directly into the selected branch or you can opt to
-create a new merge request with the cherry-pick changes
+After you click that button, a modal will appear showing a [branch filter search box](../repository/branches/index.md#branch-filter-search-box)
+where you can choose to either:
+
+- Cherry-pick the changes directly into the selected branch.
+- Create a new merge request with the cherry-picked changes.
 
 ## Cherry-picking a Commit
 
diff --git a/doc/user/project/repository/branches/img/branch_filter_search_box.png b/doc/user/project/repository/branches/img/branch_filter_search_box.png
new file mode 100644
index 0000000000000000000000000000000000000000..c4364ef39f41329d16bc3c1d0a548a771dd4feef
Binary files /dev/null and b/doc/user/project/repository/branches/img/branch_filter_search_box.png differ
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index 19417d91fecc78d66f2195b4816b857ae77bea2c..e1d8345f4154eba6b1594ef3a8e420fad86b424e 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -6,6 +6,7 @@ Read through GiLab's branching documentation:
 - [Default branch](#default-branch)
 - [Protected branches](../../protected_branches.md#protected-branches)
 - [Delete merged branches](#delete-merged-branches)
+- [Branch filter search box](#branch-filter-search-box)
 
 See also:
 
@@ -40,5 +41,22 @@ this operation.
 It's particularly useful to clean up old branches that were not deleted
 automatically when a merge request was merged.
 
+
+## Branch filter search box
+
+> [Introduced][https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22166] in GitLab 11.5.
+
+![Branch filter search box](img/branch_filter_search_box.png)
+
+This feature allows you to search and select branches quickly. Search results appear in the following order:
+
+- Branches with names that matched search terms exactly.
+- Other branches with names that include search terms, sorted alphabetically.
+
+Sometimes when you have hundreds of branches you may want a more flexible matching pattern. In such cases you can use the following:
+
+- `^feature` will only match branch names that begin with 'feature'.
+- `feature$` will only match branch names that end with 'feature'.
+
 [ce-6449]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6449 "Add button to delete all merged branches"
 [protected]: ../../protected_branches.md
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index 4d016277824a27dacfd4d31b17e8e78802ae20c3..ce79bfc0a0330cc78cf7d8c616e3884075c909e9 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -85,12 +85,13 @@ You can live preview changes submitted to a new branch with
 With [GitLab Starter](https://about.gitlab.com/pricing/), you can also request
 [approval](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your managers.
 
-To create, delete, and [branches](branches/index.md) via GitLab's UI:
+To create, delete, and view [branches](branches/index.md) via GitLab's UI:
 
 - [Default branches](branches/index.md#default-branch)
 - [Create a branch](web_editor.md#create-a-new-branch)
 - [Protected branches](../protected_branches.md#protected-branches)
 - [Delete merged branches](branches/index.md#delete-merged-branches)
+- [Branch filter search box](branches/index.md#branch-filter-search-box)
 
 Alternatively, you can use the
 [command line](../../../gitlab-basics/start-using-git.md#create-a-branch).
@@ -169,7 +170,7 @@ vendored code, and most markup languages are excluded.
 
 ## Compare
 
-Select branches to compare and view the changes inline:
+Select branches to compare using the [branch filter search box](branches/index.md#branch-filter-search-box), then click the **Compare** button to view the changes inline:
 
 ![compare branches](img/compare_branches.png)
 
diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb
index 9e3f2c69606b505a8bb45c78a08d9a3110db22e1..7d164539d9a66d4dd16590be20248a3a9e00b439 100644
--- a/spec/finders/branches_finder_spec.rb
+++ b/spec/finders/branches_finder_spec.rb
@@ -66,7 +66,7 @@
 
     context 'filter and sort' do
       it 'filters branches by name and sorts by recently_updated' do
-        params = { sort: 'updated_desc', search: 'feature' }
+        params = { sort: 'updated_desc', search: 'feat' }
         branches_finder = described_class.new(repository, params)
 
         result = branches_finder.execute
@@ -75,6 +75,17 @@
         expect(result.count).to eq(2)
       end
 
+      it 'filters branches by name and sorts by recently_updated, with exact matches first' do
+        params = { sort: 'updated_desc', search: 'feature' }
+        branches_finder = described_class.new(repository, params)
+
+        result = branches_finder.execute
+
+        expect(result.first.name).to eq('feature')
+        expect(result.second.name).to eq('feature_conflict')
+        expect(result.count).to eq(2)
+      end
+
       it 'filters branches by name and sorts by last_updated' do
         params = { sort: 'updated_asc', search: 'feature' }
         branches_finder = described_class.new(repository, params)
@@ -84,6 +95,26 @@
         expect(result.first.name).to eq('feature')
         expect(result.count).to eq(2)
       end
+
+      it 'filters branches by name that begins with' do
+        params = { search: '^feature_' }
+        branches_finder = described_class.new(repository, params)
+
+        result = branches_finder.execute
+
+        expect(result.first.name).to eq('feature_conflict')
+        expect(result.count).to eq(1)
+      end
+
+      it 'filters branches by name that ends with' do
+        params = { search: 'feature$' }
+        branches_finder = described_class.new(repository, params)
+
+        result = branches_finder.execute
+
+        expect(result.first.name).to eq('feature')
+        expect(result.count).to eq(1)
+      end
     end
   end
 end