diff --git a/app/graphql/resolvers/projects/branches_tipping_at_commit_resolver.rb b/app/graphql/resolvers/projects/branches_tipping_at_commit_resolver.rb
deleted file mode 100644
index 7e2661f3f7728f0187847477bfb903fc44c56a68..0000000000000000000000000000000000000000
--- a/app/graphql/resolvers/projects/branches_tipping_at_commit_resolver.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module Resolvers
-  module Projects
-    class BranchesTippingAtCommitResolver < RefTippingAtCommitResolver
-      MAX_LIMIT = 100
-
-      calls_gitaly!
-
-      type ::Types::Projects::CommitParentNamesType, null: true
-
-      # the methode ref_prefix is implemented
-      # because this class is prepending Resolver::CommitParentNamesResolver module
-      # through it's parent ::Resolvers::RefTippingAtCommitResolver
-      def ref_prefix
-        Gitlab::Git::BRANCH_REF_PREFIX
-      end
-    end
-  end
-end
diff --git a/app/graphql/resolvers/projects/commit_parent_names_resolver.rb b/app/graphql/resolvers/projects/commit_parent_names_resolver.rb
deleted file mode 100644
index f52776d715a8f5439ec9de0dafd20f0ac9762686..0000000000000000000000000000000000000000
--- a/app/graphql/resolvers/projects/commit_parent_names_resolver.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Resolvers
-  module Projects
-    module CommitParentNamesResolver
-      extend ActiveSupport::Concern
-
-      prepended do
-        argument :commit_sha, GraphQL::Types::String,
-          required: true,
-          description: 'Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`.'
-
-        argument :limit, GraphQL::Types::Int,
-          required: false,
-          description: 'Number of branch names to return.'
-
-        alias_method :project, :object
-      end
-
-      def compute_limit(limit)
-        max = self.class::MAX_LIMIT
-
-        limit ? [limit, max].min : max
-      end
-
-      def get_tipping_refs(project, sha, limit: 0)
-        # the methode ref_prefix needs to be implemented in all classes prepending this module
-        refs = project.repository.refs_by_oid(oid: sha, ref_patterns: [ref_prefix], limit: limit)
-        refs.map { |n| n.delete_prefix(ref_prefix) }
-      end
-    end
-  end
-end
diff --git a/app/graphql/resolvers/projects/commit_references_resolver.rb b/app/graphql/resolvers/projects/commit_references_resolver.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ca25bad468c90c5fee1e23398e99633894f154ee
--- /dev/null
+++ b/app/graphql/resolvers/projects/commit_references_resolver.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Resolvers
+  module Projects
+    class CommitReferencesResolver < BaseResolver
+      include Gitlab::Graphql::Authorize::AuthorizeResource
+
+      argument :commit_sha, GraphQL::Types::String,
+        required: true,
+        description: 'Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`.'
+
+      authorize :read_commit
+
+      alias_method :project, :object
+
+      calls_gitaly!
+
+      type ::Types::CommitReferencesType, null: true
+
+      def resolve(commit_sha:)
+        authorized_find!(oid: commit_sha)
+      end
+
+      def find_object(oid:)
+        project.repository.commit(oid)
+      end
+    end
+  end
+end
diff --git a/app/graphql/resolvers/projects/ref_tipping_at_commit_resolver.rb b/app/graphql/resolvers/projects/ref_tipping_at_commit_resolver.rb
deleted file mode 100644
index 3259a29ac9c761d6cf956bb94727b5da19810942..0000000000000000000000000000000000000000
--- a/app/graphql/resolvers/projects/ref_tipping_at_commit_resolver.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Resolvers
-  module Projects
-    class RefTippingAtCommitResolver < BaseResolver
-      include Gitlab::Graphql::Authorize::AuthorizeResource
-      prepend CommitParentNamesResolver
-
-      type ::Types::Projects::CommitParentNamesType, null: true
-
-      authorize :read_code
-
-      def resolve(commit_sha:, limit: nil)
-        final_limit = compute_limit(limit)
-
-        names = get_tipping_refs(project, commit_sha, limit: final_limit)
-
-        {
-          names: names,
-          total_count: nil
-        }
-      end
-    end
-  end
-end
diff --git a/app/graphql/resolvers/projects/tags_tipping_at_commit_resolver.rb b/app/graphql/resolvers/projects/tags_tipping_at_commit_resolver.rb
deleted file mode 100644
index 78ee9c997d51ae83580d2b82e11da9377d608f21..0000000000000000000000000000000000000000
--- a/app/graphql/resolvers/projects/tags_tipping_at_commit_resolver.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-module Resolvers
-  module Projects
-    class TagsTippingAtCommitResolver < RefTippingAtCommitResolver
-      MAX_LIMIT = 100
-
-      calls_gitaly!
-
-      type ::Types::Projects::CommitParentNamesType, null: true
-
-      # the methode ref_prefix is implemented
-      # because this class is prepending Resolver::CommitParentNamesResolver module
-      # through it's parent ::Resolvers::RefTippingAtCommitResolver
-      def ref_prefix
-        Gitlab::Git::TAG_REF_PREFIX
-      end
-    end
-  end
-end
diff --git a/app/graphql/types/commit_references_type.rb b/app/graphql/types/commit_references_type.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2844a552f3e0945aa83d3f04ed4f51c70e2becf8
--- /dev/null
+++ b/app/graphql/types/commit_references_type.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Types
+  class CommitReferencesType < BaseObject
+    graphql_name 'CommitReferences'
+
+    authorize :read_commit
+
+    def self.field_for_tipping_refs(field_name, field_description)
+      field field_name, ::Types::Projects::CommitParentNamesType,
+        null: true,
+        calls_gitaly: true,
+        description: field_description do
+          argument :limit, GraphQL::Types::Int,
+            required: true,
+            default_value: 100,
+            description: 'Number of ref names to return.',
+            validates: { numericality: { within: 1..1000 } }
+        end
+    end
+
+    def self.field_for_containing_refs(field_name, field_description)
+      field field_name, ::Types::Projects::CommitParentNamesType,
+        null: true,
+        calls_gitaly: true,
+        description: field_description do
+        argument :exclude_tipped, GraphQL::Types::Boolean,
+          required: true,
+          default_value: false,
+          description: 'Exclude tipping refs. WARNING: This argument can be confusing, if there is a limit.
+          for example set the limit to 5 and in the 5 out a total of 25 refs there is 2 tipped refs,
+          then the method will only 3 refs, even though there is more.'
+        # rubocop: disable GraphQL/ArgumentUniqueness
+        argument :limit, GraphQL::Types::Int,
+          required: true,
+          default_value: 100,
+          description: 'Number of ref names to return.',
+          validates: { numericality: { within: 1..1000 } }
+        # rubocop: enable GraphQL/ArgumentUniqueness
+      end
+    end
+
+    field_for_tipping_refs :tipping_tags, "Get tag names tipping at a given commit."
+
+    field_for_tipping_refs :tipping_branches, "Get branch names tipping at a given commit."
+
+    field_for_containing_refs :containing_tags, "Get tag names containing a given commit."
+
+    field_for_containing_refs :containing_branches, "Get branch names containing a given commit."
+
+    def tipping_tags(limit:)
+      { names: object.tipping_tags(limit: limit) }
+    end
+
+    def tipping_branches(limit:)
+      { names: object.tipping_branches(limit: limit) }
+    end
+
+    def containing_tags(limit:, exclude_tipped:)
+      { names: object.tags_containing(limit: limit, exclude_tipped: exclude_tipped) }
+    end
+
+    def containing_branches(limit:, exclude_tipped:)
+      { names: object.branches_containing(limit: limit, exclude_tipped: exclude_tipped) }
+    end
+  end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 7a26c80606155f3b3e0bd923fc57300accf229aa..f8a516501c393251457db5af08f4b98788346131 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -617,15 +617,11 @@ class ProjectType < BaseObject
           authorize: :read_cycle_analytics,
           alpha: { milestone: '15.10' }
 
-    field :tags_tipping_at_commit, ::Types::Projects::CommitParentNamesType,
-          null: true,
-          resolver: Resolvers::Projects::TagsTippingAtCommitResolver,
-          description: "Get tag names tipping at a given commit."
-
-    field :branches_tipping_at_commit, ::Types::Projects::CommitParentNamesType,
-          null: true,
-          resolver: Resolvers::Projects::BranchesTippingAtCommitResolver,
-          description: "Get branch names tipping at a given commit."
+    field :commit_references, ::Types::CommitReferencesType,
+      null: true,
+      resolver: Resolvers::Projects::CommitReferencesResolver,
+      alpha: { milestone: '16.0' },
+      description: "Get tag names containing a given commit."
 
     def timelog_categories
       object.project_namespace.timelog_categories if Feature.enabled?(:timelog_categories)
diff --git a/app/graphql/types/projects/commit_parent_names_type.rb b/app/graphql/types/projects/commit_parent_names_type.rb
index 0aa1ca768e91f53e3dc73a92c171e17efdf718ad..39f8f1cdd07922cd386fe9860878f8f407ae471d 100644
--- a/app/graphql/types/projects/commit_parent_names_type.rb
+++ b/app/graphql/types/projects/commit_parent_names_type.rb
@@ -7,7 +7,6 @@ class CommitParentNamesType < BaseObject
       graphql_name 'CommitParentNames'
 
       field :names, [GraphQL::Types::String], null: true, description: 'Names of the commit parent (branch or tag).'
-      field :total_count, GraphQL::Types::Int, null: true, description: 'Total of parent branches or tags.'
     end
     # rubocop: enable Graphql/AuthorizeTypes
   end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index b618845705c0f34d5c2050d8ad7bcf1c7efc339c..6d17d7f495d014e736e06b9490eccee13db46091 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -572,8 +572,43 @@ def user_mention_identifier
     }
   end
 
+  def tipping_branches(limit: 0)
+    tipping_refs(Gitlab::Git::BRANCH_REF_PREFIX, limit: limit)
+  end
+
+  def tipping_tags(limit: 0)
+    tipping_refs(Gitlab::Git::TAG_REF_PREFIX, limit: limit)
+  end
+
+  def branches_containing(limit: 0, exclude_tipped: false)
+    # WARNING: This argument can be confusing, if there is a limit.
+    # for example set the limit to 5 and in the 5 out a total of 25 refs there is 2 tipped refs,
+    # then the method will only 3 refs, even though there is more.
+    excluded = exclude_tipped ? tipping_branches : []
+
+    refs = repository.branch_names_contains(id, limit: limit) || []
+    refs - excluded
+  end
+
+  def tags_containing(limit: 0, exclude_tipped: false)
+    # WARNING: This argument can be confusing, if there is a limit.
+    # for example set the limit to 5 and in the 5 out a total of 25 refs there is 2 tipped refs,
+    # then the method will only 3 refs, even though there is more.
+    excluded = exclude_tipped ? tipping_tags : []
+
+    refs = repository.tag_names_contains(id, limit: limit) || []
+    refs - excluded
+  end
+
   private
 
+  def tipping_refs(ref_prefix, limit: 0)
+    strong_memoize_with(:tipping_tags, ref_prefix, limit) do
+      refs = repository.refs_by_oid(oid: id, ref_patterns: [ref_prefix], limit: limit)
+      refs.map { |n| n.delete_prefix(ref_prefix) }
+    end
+  end
+
   def expire_note_etag_cache_for_related_mrs
     MergeRequest.includes(target_project: :namespace).by_commit_sha(id).find_each(&:expire_note_etag_cache)
   end
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index c068397c50b2cab20dee842d62b6576673c5df2d..e3abed66d770dd6b731f47b7de0dde82d329a6b3 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -12792,7 +12792,60 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | Name | Type | Description |
 | ---- | ---- | ----------- |
 | <a id="commitparentnamesnames"></a>`names` | [`[String!]`](#string) | Names of the commit parent (branch or tag). |
-| <a id="commitparentnamestotalcount"></a>`totalCount` | [`Int`](#int) | Total of parent branches or tags. |
+
+### `CommitReferences`
+
+#### Fields with arguments
+
+##### `CommitReferences.containingBranches`
+
+Get branch names containing a given commit.
+
+Returns [`CommitParentNames`](#commitparentnames).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="commitreferencescontainingbranchesexcludetipped"></a>`excludeTipped` | [`Boolean!`](#boolean) | Exclude tipping refs. WARNING: This argument can be confusing, if there is a limit. for example set the limit to 5 and in the 5 out a total of 25 refs there is 2 tipped refs, then the method will only 3 refs, even though there is more. |
+| <a id="commitreferencescontainingbrancheslimit"></a>`limit` | [`Int!`](#int) | Number of ref names to return. |
+
+##### `CommitReferences.containingTags`
+
+Get tag names containing a given commit.
+
+Returns [`CommitParentNames`](#commitparentnames).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="commitreferencescontainingtagsexcludetipped"></a>`excludeTipped` | [`Boolean!`](#boolean) | Exclude tipping refs. WARNING: This argument can be confusing, if there is a limit. for example set the limit to 5 and in the 5 out a total of 25 refs there is 2 tipped refs, then the method will only 3 refs, even though there is more. |
+| <a id="commitreferencescontainingtagslimit"></a>`limit` | [`Int!`](#int) | Number of ref names to return. |
+
+##### `CommitReferences.tippingBranches`
+
+Get branch names tipping at a given commit.
+
+Returns [`CommitParentNames`](#commitparentnames).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="commitreferencestippingbrancheslimit"></a>`limit` | [`Int!`](#int) | Number of ref names to return. |
+
+##### `CommitReferences.tippingTags`
+
+Get tag names tipping at a given commit.
+
+Returns [`CommitParentNames`](#commitparentnames).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="commitreferencestippingtagslimit"></a>`limit` | [`Int!`](#int) | Number of ref names to return. |
 
 ### `ComplianceFramework`
 
@@ -19195,19 +19248,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | ---- | ---- | ----------- |
 | <a id="projectboardsid"></a>`id` | [`BoardID`](#boardid) | Find a board by its ID. |
 
-##### `Project.branchesTippingAtCommit`
-
-Get branch names tipping at a given commit.
-
-Returns [`CommitParentNames`](#commitparentnames).
-
-###### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="projectbranchestippingatcommitcommitsha"></a>`commitSha` | [`String!`](#string) | Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`. |
-| <a id="projectbranchestippingatcommitlimit"></a>`limit` | [`Int`](#int) | Number of branch names to return. |
-
 ##### `Project.ciConfigVariables`
 
 CI/CD config variable.
@@ -19283,6 +19323,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="projectclusteragentshasremotedevelopmentagentconfig"></a>`hasRemoteDevelopmentAgentConfig` | [`Boolean`](#boolean) | Returns only cluster agents which have an associated remote development agent config. |
 | <a id="projectclusteragentshasvulnerabilities"></a>`hasVulnerabilities` | [`Boolean`](#boolean) | Returns only cluster agents which have vulnerabilities. |
 
+##### `Project.commitReferences`
+
+Get tag names containing a given commit.
+
+WARNING:
+**Introduced** in 16.0.
+This feature is an Experiment. It can be changed or removed at any time.
+
+Returns [`CommitReferences`](#commitreferences).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="projectcommitreferencescommitsha"></a>`commitSha` | [`String!`](#string) | Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`. |
+
 ##### `Project.containerRepositories`
 
 Container repositories of the project.
@@ -20238,19 +20294,6 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="projectsnippetsids"></a>`ids` | [`[SnippetID!]`](#snippetid) | Array of global snippet IDs. For example, `gid://gitlab/ProjectSnippet/1`. |
 | <a id="projectsnippetsvisibility"></a>`visibility` | [`VisibilityScopesEnum`](#visibilityscopesenum) | Visibility of the snippet. |
 
-##### `Project.tagsTippingAtCommit`
-
-Get tag names tipping at a given commit.
-
-Returns [`CommitParentNames`](#commitparentnames).
-
-###### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="projecttagstippingatcommitcommitsha"></a>`commitSha` | [`String!`](#string) | Project commit SHA identifier. For example, `287774414568010855642518513f085491644061`. |
-| <a id="projecttagstippingatcommitlimit"></a>`limit` | [`Int`](#int) | Number of branch names to return. |
-
 ##### `Project.terraformState`
 
 Find a single Terraform state by name.
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index df630d6336cb3f0556cea94b775e7956f23755fb..edb856d34df84258f90afdf526f7bc9da367678d 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -885,4 +885,94 @@
       expect(commit.has_been_reverted?(user, issue.notes_with_associations)).to eq(false)
     end
   end
+
+  describe '#tipping_refs' do
+    let_it_be(:tag_name) { 'v1.1.0' }
+    let_it_be(:branch_names) { %w[master not-merged-branch v1.1.0] }
+
+    shared_examples 'tipping ref names' do
+      context 'when called without limits' do
+        it 'return tipping refs names' do
+          expect(called_method.call).to eq(expected)
+        end
+      end
+
+      context 'when called with limits' do
+        it 'return tipping refs names' do
+          limit = 1
+          expect(called_method.call(limit).size).to be <= limit
+        end
+      end
+
+      describe '#tipping_branches' do
+        let(:called_method) { ->(limit = 0) { commit.tipping_branches(limit: limit) } }
+        let(:expected) { branch_names }
+
+        it_behaves_like 'with tipping ref names'
+      end
+
+      describe '#tipping_tags' do
+        let(:called_method) { ->(limit = 0) { commit.tipping_tags(limit: limit) } }
+        let(:expected) { [tag_name] }
+
+        it_behaves_like 'with tipping ref names'
+      end
+    end
+  end
+
+  context 'containing refs' do
+    shared_examples 'containing ref names' do
+      context 'without arguments' do
+        it 'returns branch names containing the commit' do
+          expect(ref_containing.call).to eq(containing_refs)
+        end
+      end
+
+      context 'with limit argument' do
+        it 'returns the appropriate amount branch names' do
+          limit = 2
+          expect(ref_containing.call(limit: limit).size).to be <= limit
+        end
+      end
+
+      context 'with tipping refs excluded' do
+        let(:excluded_refs) do
+          project.repository.refs_by_oid(oid: commit_sha, ref_patterns: [ref_prefix]).map { |n| n.delete_prefix(ref_prefix) }
+        end
+
+        it 'returns branch names containing the commit without the one with the commit at tip' do
+          expect(ref_containing.call(excluded_tipped: true)).to eq(containing_refs - excluded_refs)
+        end
+
+        it 'returns the appropriate amount branch names with limit argument' do
+          limit = 2
+          expect(ref_containing.call(limit: limit, excluded_tipped: true).size).to be <= limit
+        end
+      end
+    end
+
+    describe '#branches_containing' do
+      let_it_be(:commit_sha) { project.commit.sha }
+      let_it_be(:containing_refs) { project.repository.branch_names_contains(commit_sha) }
+
+      let(:ref_prefix) { Gitlab::Git::BRANCH_REF_PREFIX }
+
+      let(:ref_containing) { ->(limit: 0, excluded_tipped: false) { commit.branches_containing(exclude_tipped: excluded_tipped, limit: limit) } }
+
+      it_behaves_like 'containing ref names'
+    end
+
+    describe '#tags_containing' do
+      let_it_be(:tag_name) { 'v1.1.0' }
+      let_it_be(:commit_sha) { project.repository.find_tag(tag_name).target_commit.sha }
+      let_it_be(:containing_refs) { %w[v1.1.0 v1.1.1] }
+
+      let(:ref_prefix) { Gitlab::Git::TAG_REF_PREFIX }
+
+      let(:commit) { project.repository.commit(commit_sha) }
+      let(:ref_containing) { ->(limit: 0, excluded_tipped: false) { commit.tags_containing(exclude_tipped: excluded_tipped, limit: limit) } }
+
+      it_behaves_like 'containing ref names'
+    end
+  end
 end
diff --git a/spec/requests/api/graphql/project/branches_tipping_at_commit_spec.rb b/spec/requests/api/graphql/project/branches_tipping_at_commit_spec.rb
deleted file mode 100644
index bba8977078d8dde29cb0249024c9ab4f058a6a65..0000000000000000000000000000000000000000
--- a/spec/requests/api/graphql/project/branches_tipping_at_commit_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Query.project(fullPath).tagsTippingAtCommit(commitSha)', feature_category: :source_code_management do
-  include GraphqlHelpers
-  include Presentable
-
-  let_it_be(:project) { create(:project, :repository) }
-  let_it_be(:repository) { project.repository.raw }
-  let_it_be(:current_user) { project.first_owner }
-  let_it_be(:branches_names) { %w[master not-merged-branch v1.1.0] }
-
-  let(:post_query) { post_graphql(query, current_user: current_user) }
-  let(:path) { %w[project branchesTippingAtCommit names] }
-  let(:data) { graphql_data.dig(*path) }
-
-  let(:query) do
-    graphql_query_for(
-      :project,
-      { fullPath: project.full_path },
-      query_graphql_field(:branchesTippingAtCommit, { commitSha: commit_sha }, :names)
-    )
-  end
-
-  context 'when commit exists and is tipping branches' do
-    let_it_be(:commit_sha) { repository.commit.id }
-
-    context 'with authorized user' do
-      it 'returns branches names tipping the commit' do
-        post_query
-
-        expect(data).to eq(branches_names)
-      end
-    end
-
-    context 'when user is not authorized' do
-      let(:current_user) { create(:user) }
-
-      it 'returns branches names tipping the commit' do
-        post_query
-
-        expect(data).to eq(nil)
-      end
-    end
-  end
-
-  context 'when commit does not exist' do
-    let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
-
-    it 'returns tags names tipping the commit' do
-      post_query
-
-      expect(data).to eq([])
-    end
-  end
-
-  context 'when commit exists but does not tip any branches' do
-    let(:commit_sha) { project.repository.commits(nil, { limit: 4 }).commits[2].id }
-
-    it 'returns tags names tipping the commit' do
-      post_query
-
-      expect(data).to eq([])
-    end
-  end
-end
diff --git a/spec/requests/api/graphql/project/commit_references_spec.rb b/spec/requests/api/graphql/project/commit_references_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4b545adee12fd59232ca41f816b173750155d718
--- /dev/null
+++ b/spec/requests/api/graphql/project/commit_references_spec.rb
@@ -0,0 +1,240 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Query.project(fullPath).commitReferences(commitSha)', feature_category: :source_code_management do
+  include GraphqlHelpers
+  include Presentable
+
+  let_it_be(:project) { create(:project, :repository) }
+  let_it_be(:repository) { project.repository.raw }
+  let_it_be(:current_user) { project.first_owner }
+  let_it_be(:branches_names) { %w[master not-merged-branch v1.1.0] }
+  let_it_be(:tag_name) { 'v1.0.0' }
+  let_it_be(:commit_sha) { repository.commit.id }
+
+  let(:post_query) { post_graphql(query, current_user: current_user) }
+  let(:data) { graphql_data.dig(*path) }
+  let(:base_args) { {} }
+  let(:args) { base_args }
+
+  shared_context 'with the limit argument' do
+    context 'with limit of 2' do
+      let(:args) { { limit: 2 } }
+
+      it 'returns the right amount of refs' do
+        post_query
+        expect(data.count).to be <= 2
+      end
+    end
+
+    context 'with limit of -2' do
+      let(:args) { { limit: -2 } }
+
+      it 'casts an argument error "limit must be greater then 0"' do
+        post_query
+        expect(graphql_errors).to include(custom_graphql_error(path - ['names'],
+          'limit must be within 1..1000'))
+      end
+    end
+
+    context 'with limit of 1001' do
+      let(:args) { { limit: 1001 } }
+
+      it 'casts an argument error "limit must be greater then 0"' do
+        post_query
+        expect(graphql_errors).to include(custom_graphql_error(path - ['names'],
+          'limit must be within 1..1000'))
+      end
+    end
+  end
+
+  describe 'the path commitReferences should return nil' do
+    let(:path) { %w[project commitReferences] }
+
+    let(:query) do
+      graphql_query_for(:project, { fullPath: project.full_path },
+        query_graphql_field(
+          :commitReferences,
+          { commitSha: commit_sha },
+          query_graphql_field(:tippingTags, :names)
+        )
+      )
+    end
+
+    context 'when commit does not exist' do
+      let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
+
+      it 'commitReferences returns nil' do
+        post_query
+        expect(data).to eq(nil)
+      end
+    end
+
+    context 'when sha length is incorrect' do
+      let(:commit_sha) { 'foo' }
+
+      it 'commitReferences returns nil' do
+        post_query
+        expect(data).to eq(nil)
+      end
+    end
+
+    context 'when user is not authorized' do
+      let(:commit_sha) { repository.commit.id }
+      let(:current_user) { create(:user) }
+
+      it 'commitReferences returns nil' do
+        post_query
+        expect(data).to eq(nil)
+      end
+    end
+  end
+
+  context 'with containing refs' do
+    let(:base_args) { { excludeTipped: false } }
+    let(:excluded_tipped_args) do
+      hash = base_args.dup
+      hash[:excludeTipped] = true
+      hash
+    end
+
+    context 'with path Query.project(fullPath).commitReferences(commitSha).containingTags' do
+      let_it_be(:commit_sha) { repository.find_tag(tag_name).target_commit.sha }
+      let_it_be(:path) { %w[project commitReferences containingTags names] }
+      let(:query) do
+        graphql_query_for(
+          :project,
+          { fullPath: project.full_path },
+          query_graphql_field(
+            :commitReferences,
+            { commitSha: commit_sha },
+            query_graphql_field(:containingTags, args, :names)
+          )
+        )
+      end
+
+      context 'without excludeTipped argument' do
+        it 'returns tags names containing the commit' do
+          post_query
+          expect(data).to eq(%w[v1.0.0 v1.1.0 v1.1.1])
+        end
+      end
+
+      context 'with excludeTipped argument' do
+        let_it_be(:ref_prefix) { Gitlab::Git::TAG_REF_PREFIX }
+
+        let(:args) { excluded_tipped_args }
+
+        it 'returns tags names containing the commit without the tipped tags' do
+          excluded_refs = project.repository
+                                 .refs_by_oid(oid: commit_sha, ref_patterns: [ref_prefix])
+                                 .map { |n| n.delete_prefix(ref_prefix) }
+
+          post_query
+          expect(data).to eq(%w[v1.0.0 v1.1.0 v1.1.1] - excluded_refs)
+        end
+      end
+
+      include_context 'with the limit argument'
+    end
+
+    context 'with path Query.project(fullPath).commitReferences(commitSha).containingBranches' do
+      let_it_be(:ref_prefix) { Gitlab::Git::BRANCH_REF_PREFIX }
+      let_it_be(:path) { %w[project commitReferences containingBranches names] }
+
+      let(:query) do
+        graphql_query_for(
+          :project,
+          { fullPath: project.full_path },
+          query_graphql_field(
+            :commitReferences,
+            { commitSha: commit_sha },
+            query_graphql_field(:containingBranches, args, :names)
+          )
+        )
+      end
+
+      context 'without excludeTipped argument' do
+        it 'returns branch names containing the commit' do
+          refs = project.repository.branch_names_contains(commit_sha)
+
+          post_query
+
+          expect(data).to eq(refs)
+        end
+      end
+
+      context 'with excludeTipped argument' do
+        let(:args) { excluded_tipped_args }
+
+        it 'returns branch names containing the commit without the tipped branch' do
+          refs = project.repository.branch_names_contains(commit_sha)
+
+          excluded_refs = project.repository
+                                 .refs_by_oid(oid: commit_sha, ref_patterns: [ref_prefix])
+                                 .map { |n| n.delete_prefix(ref_prefix) }
+
+          post_query
+
+          expect(data).to eq(refs - excluded_refs)
+        end
+      end
+
+      include_context 'with the limit argument'
+    end
+  end
+
+  context 'with tipping refs' do
+    context 'with path Query.project(fullPath).commitReferences(commitSha).tippingTags' do
+      let(:commit_sha) { repository.find_tag(tag_name).dereferenced_target.sha }
+      let(:path) { %w[project commitReferences tippingTags names] }
+
+      let(:query) do
+        graphql_query_for(
+          :project,
+          { fullPath: project.full_path },
+          query_graphql_field(
+            :commitReferences,
+            { commitSha: commit_sha },
+            query_graphql_field(:tippingTags, args, :names)
+          )
+        )
+      end
+
+      context 'with authorized user' do
+        it 'returns tags names tipping the commit' do
+          post_query
+
+          expect(data).to eq([tag_name])
+        end
+      end
+
+      include_context 'with the limit argument'
+    end
+
+    context 'with path Query.project(fullPath).commitReferences(commitSha).tippingBranches' do
+      let(:path) { %w[project commitReferences tippingBranches names] }
+
+      let(:query) do
+        graphql_query_for(
+          :project,
+          { fullPath: project.full_path },
+          query_graphql_field(
+            :commitReferences,
+            { commitSha: commit_sha },
+            query_graphql_field(:tippingBranches, args, :names)
+          )
+        )
+      end
+
+      it 'returns branches names tipping the commit' do
+        post_query
+
+        expect(data).to eq(branches_names)
+      end
+
+      include_context 'with the limit argument'
+    end
+  end
+end
diff --git a/spec/requests/api/graphql/project/tags_tipping_at_commit_spec.rb b/spec/requests/api/graphql/project/tags_tipping_at_commit_spec.rb
deleted file mode 100644
index a5e26482a9ef448c69453a4a19bf5f195198ff5a..0000000000000000000000000000000000000000
--- a/spec/requests/api/graphql/project/tags_tipping_at_commit_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Query.project(fullPath).tagsTippingAtCommit(commitSha)', feature_category: :source_code_management do
-  include GraphqlHelpers
-  include Presentable
-
-  let_it_be(:project) { create(:project, :repository) }
-  let_it_be(:repository) { project.repository.raw }
-  let_it_be(:current_user) { project.first_owner }
-  let_it_be(:tag_name) { 'v1.0.0' }
-
-  let(:post_query) { post_graphql(query, current_user: current_user) }
-  let(:path) { %w[project tagsTippingAtCommit names] }
-  let(:data) { graphql_data.dig(*path) }
-
-  let(:query) do
-    graphql_query_for(
-      :project,
-      { fullPath: project.full_path },
-      query_graphql_field(:tagsTippingAtCommit, { commitSha: commit_sha }, :names)
-    )
-  end
-
-  context 'when commit exists and is tipping tags' do
-    let(:commit_sha) { repository.find_tag(tag_name).dereferenced_target.sha }
-
-    context 'with authorized user' do
-      it 'returns tags names tipping the commit' do
-        post_query
-
-        expect(data).to eq([tag_name])
-      end
-    end
-
-    context 'when user is not authorized' do
-      let(:current_user) { create(:user) }
-
-      it 'returns tags names tipping the commit' do
-        post_query
-
-        expect(data).to eq(nil)
-      end
-    end
-  end
-
-  context 'when commit does not exist' do
-    let(:commit_sha) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff4' }
-
-    it 'returns tags names tipping the commit' do
-      post_query
-
-      expect(data).to eq([])
-    end
-  end
-
-  context 'when commit exists but does not tip any tags' do
-    let(:commit_sha) { project.repository.commits(nil, { limit: 4 }).commits[2].id }
-
-    it 'returns tags names tipping the commit' do
-      post_query
-
-      expect(data).to eq([])
-    end
-  end
-end