diff --git a/changelogs/unreleased/22638-creating-a-branch-matching-a-wildcard-fails.yml b/changelogs/unreleased/22638-creating-a-branch-matching-a-wildcard-fails.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2c6883bcf7b5d7c7859b8f30f18cccfe6e0d89f8
--- /dev/null
+++ b/changelogs/unreleased/22638-creating-a-branch-matching-a-wildcard-fails.yml
@@ -0,0 +1,4 @@
+---
+title: Allow creating protected branches when user can merge to such branch
+merge_request: 8458
+author:
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 6c7e673fb9fbf332714a07d18a4c26fba75c0edb..6ce9b22929435512b83b58d317e0a890ac5fed43 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -35,7 +35,9 @@ module Gitlab
         return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user)
 
         access_levels = project.protected_branches.matching(ref).map(&:push_access_levels).flatten
-        access_levels.any? { |access_level| access_level.check_access(user) }
+        has_access = access_levels.any? { |access_level| access_level.check_access(user) }
+
+        has_access || !project.repository.branch_exists?(ref) && can_merge_to_branch?(ref)
       else
         user.can?(:push_code, project)
       end
diff --git a/spec/lib/gitlab/user_access_spec.rb b/spec/lib/gitlab/user_access_spec.rb
index d3c3b800b94b3683d42e0fd0a432099f87d7f6d7..369e55f61f1d490eef4aaf5b9949cc1ffe67e2fd 100644
--- a/spec/lib/gitlab/user_access_spec.rb
+++ b/spec/lib/gitlab/user_access_spec.rb
@@ -66,7 +66,8 @@ describe Gitlab::UserAccess, lib: true do
     end
 
     describe 'push to protected branch' do
-      let(:branch) { create :protected_branch, project: project }
+      let(:branch) { create :protected_branch, project: project, name: "test" }
+      let(:not_existing_branch) { create :protected_branch, :developers_can_merge, project: project }
 
       it 'returns true if user is a master' do
         project.team << [user, :master]
@@ -85,6 +86,12 @@ describe Gitlab::UserAccess, lib: true do
 
         expect(access.can_push_to_branch?(branch.name)).to be_falsey
       end
+
+      it 'returns true if branch does not exist and user has permission to merge' do
+        project.team << [user, :developer]
+
+        expect(access.can_push_to_branch?(not_existing_branch.name)).to be_truthy
+      end
     end
 
     describe 'push to protected branch if allowed for developers' do