diff --git a/app/views/shared/issuable/form/_branch_chooser.html.haml b/app/views/shared/issuable/form/_branch_chooser.html.haml
index 01f1dbdb3cfd83c068afd7326ffcdd26ff6ed7ab..34815026ff276e480243b7c13e2bb906cd8664b6 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -11,9 +11,11 @@
 - vis1020 = _('This merge request is from an internal project to a public project.')
 - i18n = { '010' => vis010, '020' => vis020, '1020' => vis1020 }
 
-- source_level = @merge_request.source_project.visibility_level
-- source_visibility = @merge_request.source_project.visibility
-- target_level = @merge_request.target_project.visibility_level
+- source_project = @merge_request.source_project
+- target_project = @merge_request.target_project
+- source_level = source_project.visibility_level
+- source_visibility = source_project.visibility
+- target_level = target_project.visibility_level
 
 - visibilityMismatchString = i18n["#{source_level}#{target_level}"]
 
@@ -39,10 +41,18 @@
         = dropdown_filter(_("Search branches"))
         = dropdown_content
         = dropdown_loading
-
 - if source_level < target_level
   = render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-4' }) do |c|
     - c.with_body do
       = visibilityMismatchString
       %br
       = _('Review the target project before submitting to avoid exposing %{source} changes.') % { source: source_visibility }
+- elsif target_level > Gitlab::VisibilityLevel::PRIVATE
+  - source_access_level = source_project.project_feature.repository_access_level
+  - target_access_level =  target_project.project_feature.repository_access_level
+  - if source_access_level < target_access_level
+    = render Pajamas::AlertComponent.new(title: _('Should these changes be private?'), variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-4' }) do |c|
+      - c.with_body do
+        - warning_message = html_escape(_("Project %{code_open}%{source_project}%{code_close} has more restricted access settings than %{code_open}%{target_project}%{code_close}. To avoid exposing private changes, make sure you're submitting changes to the correct project."))
+        = warning_message % {code_open: '<code>'.html_safe, code_close: '</code>'.html_safe, source_project: source_project.name_with_namespace, target_project: target_project.name_with_namespace}
+
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8526d1fdf0a7e6927c791ca17ec238d1cddf7227..7ca93369c27a85b7ee889968b21b67f8217342f5 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -35926,6 +35926,9 @@ msgstr ""
 msgid "Project \"%{name}\" is no longer available. Select another project to continue."
 msgstr ""
 
+msgid "Project %{code_open}%{source_project}%{code_close} has more restricted access settings than %{code_open}%{target_project}%{code_close}. To avoid exposing private changes, make sure you're submitting changes to the correct project."
+msgstr ""
+
 msgid "Project %{project_repo} could not be found"
 msgstr ""
 
@@ -43320,6 +43323,9 @@ msgstr ""
 msgid "Short name"
 msgstr ""
 
+msgid "Should these changes be private?"
+msgstr ""
+
 msgid "Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{boldStart}will%{boldEnd} lose access to your account."
 msgstr ""
 
diff --git a/spec/features/merge_request/creating_mr_for_projects_with_different_visibility_spec.rb b/spec/features/merge_request/creating_mr_for_projects_with_different_visibility_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3597c2ed1c78afab5e54453fdf841f046edcf670
--- /dev/null
+++ b/spec/features/merge_request/creating_mr_for_projects_with_different_visibility_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge Request > Selecting projects with different visibility', feature_category: :source_code_management do
+  include ProjectForksHelper
+
+  let_it_be(:public_project) { create(:project, :public, :small_repo) }
+  let_it_be(:internal_project) { create(:project, :internal, :small_repo) }
+  let_it_be(:private_project) { create(:project, :private, :small_repo) }
+  let(:private_fork_public_project) do
+    fork_project(public_project, nil, target_project: create(:project, :private, :small_repo))
+  end
+
+  let(:private_fork_internal_project) do
+    fork_project(internal_project, nil, target_project: create(:project, :private, :small_repo))
+  end
+
+  let(:internal_fork_public_project) do
+    fork_project(public_project, nil, target_project: create(:project, :internal, :small_repo))
+  end
+
+  let(:user) { source_project.creator }
+
+  before do
+    sign_in(user)
+  end
+
+  describe 'warnings for more permissive visibility in target project', :js do
+    using RSpec::Parameterized::TableSyntax
+
+    where(:source_project, :target_project, :warning_message) do
+      ref(:private_fork_internal_project) |
+        ref(:internal_project) |
+        _('This merge request is from a private project to an internal project.')
+
+      ref(:private_fork_public_project) |
+        ref(:public_project) |
+        _('This merge request is from a private project to a public project.')
+
+      ref(:internal_fork_public_project) |
+        ref(:public_project) |
+        _('This merge request is from an internal project to a public project.')
+    end
+
+    with_them do
+      it 'shows a warning message' do
+        visit project_new_merge_request_path(source_project,
+          merge_request: { source_branch: 'master', target_project_id: target_project.id })
+        expect(page).to have_content(warning_message)
+      end
+    end
+
+    describe 'warnings for more permissive repository access level in target project' do
+      let(:source_project) do
+        fork_project(internal_project, nil, target_project: create(:project, :internal, :small_repo))
+      end
+
+      let(:target_project) { internal_project }
+
+      let(:warning_message) do
+        "Project #{source_project.name_with_namespace} has more restricted access settings than " \
+          "#{target_project.name_with_namespace}. To avoid exposing private changes, make sure " \
+          "you're submitting changes to the correct project."
+      end
+
+      context 'when the source repository access level is private' do
+        before do
+          source_access_level = Featurable::PRIVATE
+          source_project.project_feature.update!(
+            repository_access_level: source_access_level,
+            merge_requests_access_level: source_access_level,
+            builds_access_level: source_access_level
+          )
+        end
+
+        it 'shows a warning' do
+          visit project_new_merge_request_path(source_project,
+            merge_request: { source_branch: 'master', target_project_id: target_project.id })
+          expect(page).to have_content(warning_message)
+        end
+
+        context 'when target project is private' do
+          let(:source_project) do
+            fork_project(private_project, nil, target_project: create(:project, :private, :small_repo))
+          end
+
+          let(:target_project) { private_project }
+
+          it 'does not show a warning' do
+            visit project_new_merge_request_path(source_project,
+              merge_request: { source_branch: 'master', target_project_id: target_project.id })
+
+            expect(page).not_to have_content(warning_message)
+          end
+        end
+      end
+    end
+  end
+end