diff --git a/app/models/work_item.rb b/app/models/work_item.rb
index cd2de3fc335ab9ecb0d7be73de1477401ee8de4a..c4c991e5361cf9bbb46958a71e09da96d6e29b19 100644
--- a/app/models/work_item.rb
+++ b/app/models/work_item.rb
@@ -116,6 +116,17 @@ def related_link_class
     end
   end
 
+  def create_dates_source_from_current_dates
+    create_dates_source(
+      due_date: due_date,
+      start_date: start_date,
+      start_date_is_fixed: due_date.present? || start_date.present?,
+      due_date_is_fixed: due_date.present? || start_date.present?,
+      start_date_fixed: start_date,
+      due_date_fixed: due_date
+    )
+  end
+
   def noteable_target_type_name
     'issue'
   end
diff --git a/ee/app/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service.rb b/ee/app/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service.rb
index 3697bbfceba7fb5b409e32d2cc9dcb1b5d06f5cd..3c23c14a8df20c37c74b4b86523ad6dc4dfbfcde 100644
--- a/ee/app/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service.rb
+++ b/ee/app/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service.rb
@@ -44,7 +44,7 @@ def execute
         def ensure_dates_sources_exist(work_items)
           work_items
             .excluding(work_items.joins(:dates_source)) # exclude work items that already have a dates source
-            .each(&:create_dates_source)
+            .each(&:create_dates_source_from_current_dates)
         end
 
         def join_with_update(query)
diff --git a/ee/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/ee/spec/requests/api/graphql/mutations/work_items/update_spec.rb
index fc92081967a0ad098c57f4ee5de0cc4cdb3a5ac4..5959b2838d166f418430bac6bbd847b6830b7f30 100644
--- a/ee/spec/requests/api/graphql/mutations/work_items/update_spec.rb
+++ b/ee/spec/requests/api/graphql/mutations/work_items/update_spec.rb
@@ -1031,12 +1031,37 @@ def work_item_status
 
     context 'when updating parent' do
       let_it_be(:work_item_epic, reload: true) { create(:work_item, :epic_with_legacy_epic, namespace: group) }
-      let_it_be(:work_item_issue, reload: true) { create(:work_item, :issue, project: project) }
+      let_it_be(:work_item_issue, reload: true) do
+        create(:work_item, :issue, project: project, due_date: 2.days.from_now, start_date: 2.days.ago)
+      end
 
       let_it_be(:new_parent) { create(:work_item, :epic_with_legacy_epic, namespace: group) }
 
       let(:input) { { 'hierarchyWidget' => { 'parentId' => new_parent.to_global_id.to_s } } }
 
+      context 'when issue has due and start date set but no dates_source record' do
+        let(:input) { { 'hierarchyWidget' => { 'parentId' => work_item_epic.to_global_id.to_s } } }
+
+        before do
+          allow(Gitlab::QueryLimiting::Transaction).to receive(:threshold).and_return(150)
+        end
+
+        it 'does not clear due and start date values from issue', :sidekiq_inline, :aggregate_failures do
+          set_due_date = work_item_issue.due_date
+          set_start_date = work_item_issue.start_date
+
+          expect(work_item_issue.dates_source).to be_nil
+          expect(set_due_date).to be_present
+          expect(set_start_date).to be_present
+
+          expect do
+            post_graphql_mutation(mutation_for(work_item_issue), current_user: reporter)
+          end.to change { work_item_issue.reload.work_item_parent }.from(nil).to(work_item_epic)
+            .and not_change { work_item_issue.reload.due_date }.from(set_due_date)
+            .and not_change { work_item_issue.reload.start_date }.from(set_start_date)
+        end
+      end
+
       it 'updates work item parent and synced epic parent when moving child is epic' do
         expect do
           post_graphql_mutation(mutation_for(work_item_epic), current_user: reporter)
diff --git a/ee/spec/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service_spec.rb b/ee/spec/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service_spec.rb
index 330a7bca4ce67d40eaa0e0561a382a1f83ab66cd..c69c2ba3ce4ea8dc6e3d0c89eba03fabd7ac4179 100644
--- a/ee/spec/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service_spec.rb
+++ b/ee/spec/services/work_items/widgets/rolledup_dates_service/hierarchies_update_service_spec.rb
@@ -41,13 +41,9 @@
     let_it_be_with_reload(:epic_1) { create(:epic, group: group, work_item: work_item_1) }
     let_it_be_with_reload(:epic_2) { create(:epic, group: group, work_item: work_item_2) }
 
-    subject(:service) do
-      described_class.new(WorkItem.id_in([
-        work_item_1.id,
-        work_item_2.id,
-        work_item_fixed_dates.id
-      ]))
-    end
+    let(:work_items) { WorkItem.id_in([work_item_1.id, work_item_2.id, work_item_fixed_dates.id]) }
+
+    subject(:service) { described_class.new(work_items) }
 
     shared_examples 'syncs work item dates sources to epics' do
       specify do
@@ -234,4 +230,32 @@
           .and not_change { work_item_fixed_dates.dates_source&.due_date }
       end
     end
+
+    context 'when no dates_sources records exist' do
+      let_it_be(:project) { create(:project, group: group) }
+      let_it_be(:start_date) { Time.zone.today }
+      let_it_be(:due_date) { Time.zone.tomorrow }
+
+      let_it_be_with_reload(:work_item_without_dates_source) do
+        create(:work_item, :issue, project: project, start_date: start_date, due_date: due_date).tap do |child|
+          create(:parent_link, work_item: child, work_item_parent: work_item_1)
+        end
+      end
+
+      let(:work_items) do
+        WorkItem.id_in([work_item_1.id, work_item_2.id, work_item_fixed_dates.id, work_item_without_dates_source.id])
+      end
+
+      it 'ensures to create the records and sets correct default values' do
+        expect(work_item_without_dates_source.dates_source).to be_nil
+
+        # We have multiple child work items that do not have a dates_source
+        expect { service.execute }.to change { WorkItems::DatesSource.count }.by(3)
+
+        expect(work_item_without_dates_source.reload.dates_source).to have_attributes(
+          start_date: start_date, due_date: due_date, start_date_fixed: start_date, due_date_fixed: due_date,
+          start_date_is_fixed: true, due_date_is_fixed: true
+        )
+      end
+    end
   end
diff --git a/spec/models/work_item_spec.rb b/spec/models/work_item_spec.rb
index 213ba7a19178f19d75c640f7cb096bdf17a6ede9..e3117b9bebc7cbf0235f736297497ec58c1484f2 100644
--- a/spec/models/work_item_spec.rb
+++ b/spec/models/work_item_spec.rb
@@ -92,6 +92,91 @@
     end
   end
 
+  describe '#create_dates_source_from_current_dates' do
+    let_it_be(:start_date) { nil }
+    let_it_be(:due_date) { nil }
+    let(:dates_source) { work_item.dates_source }
+
+    let_it_be_with_reload(:work_item) do
+      create(:work_item, project: reusable_project, start_date: start_date, due_date: due_date)
+    end
+
+    before do
+      work_item.update!(start_date: start_date, due_date: due_date)
+    end
+
+    subject(:create_dates_source_from_current_dates) { work_item.create_dates_source_from_current_dates }
+
+    context 'when both due_date and start_date are present' do
+      let_it_be(:due_date) { Time.zone.tomorrow }
+      let_it_be(:start_date) { Time.zone.today }
+
+      it 'creates dates_source with correct attributes' do
+        expect { create_dates_source_from_current_dates }.to change { WorkItems::DatesSource.count }.by(1)
+
+        expect(dates_source.reload).to have_attributes(
+          due_date: due_date,
+          start_date: start_date,
+          start_date_is_fixed: true,
+          due_date_is_fixed: true,
+          start_date_fixed: start_date,
+          due_date_fixed: due_date
+        )
+      end
+    end
+
+    context 'when only due_date is present' do
+      let_it_be(:due_date) { Time.zone.tomorrow }
+      let_it_be(:start_date) { nil }
+
+      it 'creates dates_source with correct attributes' do
+        create_dates_source_from_current_dates
+
+        expect(dates_source).to have_attributes(
+          due_date: work_item.due_date,
+          start_date: nil,
+          start_date_is_fixed: true,
+          due_date_is_fixed: true,
+          start_date_fixed: nil,
+          due_date_fixed: work_item.due_date
+        )
+      end
+    end
+
+    context 'when only start_date is present' do
+      let_it_be(:due_date) { nil }
+      let_it_be(:start_date) { Time.zone.today }
+
+      it 'creates dates_source with correct attributes' do
+        create_dates_source_from_current_dates
+
+        expect(dates_source).to have_attributes(
+          due_date: nil,
+          start_date: work_item.start_date,
+          start_date_is_fixed: true,
+          due_date_is_fixed: true,
+          start_date_fixed: work_item.start_date,
+          due_date_fixed: nil
+        )
+      end
+    end
+
+    context 'when neither due_date nor start_date is present' do
+      it 'creates dates_source with correct attributes' do
+        dates_source = work_item.create_dates_source_from_current_dates
+
+        expect(dates_source).to have_attributes(
+          due_date: nil,
+          start_date: nil,
+          start_date_is_fixed: false,
+          due_date_is_fixed: false,
+          start_date_fixed: nil,
+          due_date_fixed: nil
+        )
+      end
+    end
+  end
+
   describe '#noteable_target_type_name' do
     it 'returns `issue` as the target name' do
       work_item = build(:work_item)