diff --git a/app/models/repository.rb b/app/models/repository.rb
index 0164d6fed9324c0cbac7d0e7f5f0e9dfbf5bd99a..3ac30af7d3e7600216d36b6c3911a2a17af2b352 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1125,7 +1125,11 @@ class Repository
       copy_gitattributes(branch)
       after_change_head
     else
-      container.errors.add(:base, _("Could not change HEAD: branch '%{branch}' does not exist") % { branch: branch })
+      # For example, `Wiki` does not have `errors` because it is not an `ActiveModel`
+      if container.respond_to?(:errors)
+        container.errors.add(:base, _("Could not change HEAD: branch '%{branch}' does not exist") % { branch: branch })
+      end
+
       false
     end
   end
diff --git a/db/post_migrate/20210823193234_remove_allow_editing_commit_messages_from_project_settings.rb b/db/post_migrate/20210823193234_remove_allow_editing_commit_messages_from_project_settings.rb
deleted file mode 100644
index 7806f05a9af0ea4c3e6ad2c539ef33a586db6ad0..0000000000000000000000000000000000000000
--- a/db/post_migrate/20210823193234_remove_allow_editing_commit_messages_from_project_settings.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveAllowEditingCommitMessagesFromProjectSettings < ActiveRecord::Migration[6.1]
-  include Gitlab::Database::MigrationHelpers
-
-  def up
-    with_lock_retries do
-      remove_column :project_settings, :allow_editing_commit_messages
-    end
-  end
-
-  def down
-    with_lock_retries do
-      add_column :project_settings, :allow_editing_commit_messages, :boolean, default: false, null: false
-    end
-  end
-end
diff --git a/db/schema_migrations/20210823193234 b/db/schema_migrations/20210823193234
deleted file mode 100644
index d47f1ec567a1acb149241b115305a02be4a0c515..0000000000000000000000000000000000000000
--- a/db/schema_migrations/20210823193234
+++ /dev/null
@@ -1 +0,0 @@
-b85ef326056bb152d527e34b49caa3c40ee8685c3b14654992246c6adf082f8c
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 058a55d625167297f750f7a3492efd2a5fa2bea0..163ac643a3dd0543dffbb22cc3e50f24fe15336e 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -17343,6 +17343,7 @@ CREATE TABLE project_settings (
     squash_option smallint DEFAULT 3,
     has_confluence boolean DEFAULT false NOT NULL,
     has_vulnerabilities boolean DEFAULT false NOT NULL,
+    allow_editing_commit_messages boolean DEFAULT false NOT NULL,
     prevent_merge_without_jira_issue boolean DEFAULT false NOT NULL,
     cve_id_request_enabled boolean DEFAULT true NOT NULL,
     mr_default_target_self boolean DEFAULT false NOT NULL,
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 4b4d13179c3b05df494504b87add56d66c7c3ae4..d9857c0830fc7bc36a50bedea521d8bc2dbc17da 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -1595,7 +1595,9 @@ production:
   can refer to jobs in the same stage as the job you are configuring. This feature is
   enabled on GitLab.com and ready for production use. On self-managed [GitLab 14.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/30632)
   this feature is available by default.
-- In GitLab 14.0 and older, you can only refer to jobs in earlier stages.
+- In GitLab 14.0 and older, you can only refer to jobs in earlier stages. Stages must be
+  explicitly defined for all jobs that use the `needs:` keyword, or are referenced
+  in a job's `needs:` section.
 - In GitLab 13.9 and older, if `needs:` refers to a job that might not be added to
   a pipeline because of `only`, `except`, or `rules`, the pipeline might fail to create.
 - The maximum number of jobs that a single job can need in the `needs:` array is limited:
@@ -1609,8 +1611,6 @@ production:
 - `needs:` is similar to `dependencies:` in that it must use jobs from prior stages,
   meaning it's impossible to create circular dependencies. Depending on jobs in the
   current stage is not possible either, but [an issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/30632).
-- Stages must be explicitly defined for all jobs
-  that have the keyword `needs:` or are referred to by one.
 
 ##### Changing the `needs:` job limit **(FREE SELF)**
 
diff --git a/ee/app/services/geo/framework_repository_sync_service.rb b/ee/app/services/geo/framework_repository_sync_service.rb
index dceb683f0a73baa302dcb3e312d11f1ff22064fd..8b2e56c85290daea3493b901462027b54c075da2 100644
--- a/ee/app/services/geo/framework_repository_sync_service.rb
+++ b/ee/app/services/geo/framework_repository_sync_service.rb
@@ -37,7 +37,6 @@ module Geo
     def sync_repository
       start_registry_sync!
       fetch_repository
-      update_root_ref
       mark_sync_as_successful
     rescue Gitlab::Git::Repository::NoRepository => e
       log_info('Marking the repository for a forced re-download')
@@ -83,6 +82,8 @@ module Geo
         fetch_geo_mirror(repository)
         @new_repository = true
       end
+
+      update_root_ref
     end
 
     def redownload_repository
diff --git a/ee/app/services/geo/repository_base_sync_service.rb b/ee/app/services/geo/repository_base_sync_service.rb
index 733740db77a8e03b2734482c508258a6072689c6..be5f035f6f017b991833cf83a21f3691ca436e95 100644
--- a/ee/app/services/geo/repository_base_sync_service.rb
+++ b/ee/app/services/geo/repository_base_sync_service.rb
@@ -63,6 +63,8 @@ module Geo
         fetch_geo_mirror(repository)
         @new_repository = true
       end
+
+      update_root_ref
     end
 
     def redownload?
@@ -270,5 +272,13 @@ module Geo
       checksum = project.repository_state.public_send("#{type}_verification_checksum") # rubocop:disable GitlabSecurity/PublicSend
       checksum && checksum != Gitlab::Git::Repository::EMPTY_REPOSITORY_CHECKSUM
     end
+
+    def update_root_ref
+      authorization = ::Gitlab::Geo::RepoSyncRequest.new(
+        scope: repository.full_path
+      ).authorization
+
+      repository.update_root_ref(remote_url, authorization)
+    end
   end
 end
diff --git a/ee/app/services/geo/repository_sync_service.rb b/ee/app/services/geo/repository_sync_service.rb
index 93c411cc9da7d7afe636294da62df3720fea14d4..36e5023230fe2bb7701a903097fef9f7e7ebf175 100644
--- a/ee/app/services/geo/repository_sync_service.rb
+++ b/ee/app/services/geo/repository_sync_service.rb
@@ -9,7 +9,6 @@ module Geo
     def sync_repository
       start_registry_sync!
       fetch_repository
-      update_root_ref
       mark_sync_as_successful
     rescue Gitlab::Git::Repository::NoRepository => e
       log_info('Setting force_to_redownload flag')
@@ -49,14 +48,6 @@ module Geo
       project.ensure_repository
     end
 
-    def update_root_ref
-      authorization = ::Gitlab::Geo::RepoSyncRequest.new(
-        scope: repository.full_path
-      ).authorization
-
-      repository.update_root_ref(remote_url, authorization)
-    end
-
     def execute_housekeeping
       Geo::ProjectHousekeepingService.new(project, new_repository: new_repository?).execute
     end
diff --git a/ee/spec/services/geo/design_repository_sync_service_spec.rb b/ee/spec/services/geo/design_repository_sync_service_spec.rb
index 94b37c1055f903ba78c43b94c5b37527bc6d3950..4fe1f4957b580d3e8b35444a694847b6b6ad820b 100644
--- a/ee/spec/services/geo/design_repository_sync_service_spec.rb
+++ b/ee/spec/services/geo/design_repository_sync_service_spec.rb
@@ -35,12 +35,11 @@ RSpec.describe Geo::DesignRepositorySyncService do
       stub_exclusive_lease(lease_key, lease_uuid)
       stub_exclusive_lease("geo_project_housekeeping:#{project.id}")
 
-      allow_any_instance_of(Repository).to receive(:fetch_as_mirror)
-        .and_return(true)
+      allow(repository).to receive(:fetch_as_mirror).and_return(true)
 
-      allow_any_instance_of(Repository)
+      allow(repository)
         .to receive(:find_remote_root_ref)
-        .with(url_to_repo)
+        .with(url_to_repo, anything)
         .and_return('master')
 
       allow_any_instance_of(Geo::ProjectHousekeepingService).to receive(:execute)
diff --git a/ee/spec/services/geo/repository_sync_service_spec.rb b/ee/spec/services/geo/repository_sync_service_spec.rb
index f24929e0529c555d140fd66e2cbeeeaedda4e6a7..fdf49005294522578a399f9dea213bc9336772e5 100644
--- a/ee/spec/services/geo/repository_sync_service_spec.rb
+++ b/ee/spec/services/geo/repository_sync_service_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe Geo::RepositorySyncService, :geo do
       allow_any_instance_of(Repository).to receive(:fetch_as_mirror)
         .and_return(true)
 
-      allow_any_instance_of(Repository)
+      allow(repository)
         .to receive(:find_remote_root_ref)
         .with(url_to_repo, anything)
         .and_return('master')
diff --git a/ee/spec/services/geo/wiki_sync_service_spec.rb b/ee/spec/services/geo/wiki_sync_service_spec.rb
index 203d64969889a097ef11ddeb6ad1695cc1a5dd1a..f6d83c49efd594620a056e4e2cb503845a79a95e 100644
--- a/ee/spec/services/geo/wiki_sync_service_spec.rb
+++ b/ee/spec/services/geo/wiki_sync_service_spec.rb
@@ -45,6 +45,8 @@ RSpec.describe Geo::WikiSyncService, :geo do
     end
 
     it 'voids the failure message when it succeeds after an error' do
+      allow(repository).to receive(:update_root_ref)
+
       registry = create(:geo_project_registry, project: project, last_wiki_sync_failure: 'error')
 
       expect { subject.execute }.to change { registry.reload.last_wiki_sync_failure }.to(nil)
@@ -126,6 +128,8 @@ RSpec.describe Geo::WikiSyncService, :geo do
     end
 
     it 'marks primary_wiki_checksummed as true when wiki has been verified on primary' do
+      allow(repository).to receive(:update_root_ref)
+
       create(:repository_state, :wiki_verified, project: project)
       registry = create(:geo_project_registry, project: project, primary_wiki_checksummed: false)
 
@@ -133,6 +137,8 @@ RSpec.describe Geo::WikiSyncService, :geo do
     end
 
     it 'marks primary_wiki_checksummed as false when wiki has not been verified on primary' do
+      allow(repository).to receive(:update_root_ref)
+
       create(:repository_state, :wiki_failed, project: project)
       registry = create(:geo_project_registry, project: project, primary_wiki_checksummed: true)
 
@@ -166,6 +172,8 @@ RSpec.describe Geo::WikiSyncService, :geo do
         end
 
         it 'sets last_wiki_successful_sync_at' do
+          allow(repository).to receive(:update_root_ref)
+
           subject.execute
 
           expect(registry.last_wiki_successful_sync_at).not_to be_nil
@@ -190,7 +198,9 @@ RSpec.describe Geo::WikiSyncService, :geo do
         end
 
         it 'logs success with timings' do
+          allow(repository).to receive(:update_root_ref)
           allow(Gitlab::Geo::Logger).to receive(:info).and_call_original
+
           expect(Gitlab::Geo::Logger).to receive(:info).with(hash_including(:message, :update_delay_s, :download_time_s)).and_call_original
 
           subject.execute
@@ -232,6 +242,7 @@ RSpec.describe Geo::WikiSyncService, :geo do
             force_to_redownload_wiki: true
           )
 
+          allow(project.wiki.repository).to receive(:update_root_ref)
           expect(project.wiki.repository).to receive(:expire_exists_cache).exactly(3).times.and_call_original
           expect(subject).not_to receive(:fail_registry_sync!)
 
diff --git a/ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb b/ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb
index 7e9617ad9056443d6425000fa956d0943b7093a9..b83549e07402c336e0313cf17555d00383fe3a58 100644
--- a/ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb
+++ b/ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb
@@ -65,6 +65,7 @@ RSpec.shared_examples 'geo base sync fetch' do
 
     before do
       allow(subject).to receive(:fetch_geo_mirror).and_return(true)
+      allow(repository).to receive(:update_root_ref)
     end
 
     it 'cleans up temporary repository' do
@@ -79,6 +80,12 @@ RSpec.shared_examples 'geo base sync fetch' do
       fetch_repository
     end
 
+    it 'syncs the HEAD ref' do
+      expect(repository).to receive(:update_root_ref)
+
+      fetch_repository
+    end
+
     context 'repository does not exist' do
       before do
         allow_any_instance_of(Repository).to receive(:exists?) { false }