diff --git a/CHANGELOG.md b/CHANGELOG.md
index 51aa8cf0a3c8c2409b032c2f6f0ed7be299d9631..0b9f7a0c0c0da499fb60547ee058156c4959999b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
   th above `empty_diff` function). Formerly this would have caused a merge
   conflict if the referenced record(s) were identical, but stored in different
   Python objects.
+* `apiutils.merge_entities` now has an optional `force` argument (defaults to
+  `False`, i.e., the old behavior) which determines whether in case of merge
+  conflicts errors will be raised or the properties and attributes of entity A
+  will be overwritten by entity B.
 
 ### Deprecated ###
 
diff --git a/src/caosdb/apiutils.py b/src/caosdb/apiutils.py
index 9d2f3c4cc343305eaff986031dfe3adc8f45dbc2..0651e4930072242524dc955c6ae69ca70b5f877a 100644
--- a/src/caosdb/apiutils.py
+++ b/src/caosdb/apiutils.py
@@ -361,7 +361,7 @@ def empty_diff(old_entity: Entity, new_entity: Entity, compare_referenced_record
     return True
 
 
-def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_empty_diffs=True):
+def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_empty_diffs=True, force=False):
     """
     Merge entity_b into entity_a such that they have the same parents and properties.
 
@@ -385,6 +385,10 @@ def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_emp
        record(s) that may be different Python objects but have empty diffs. If
        set to `False` a merge conflict will be raised in this case
        instead. Default is True.
+    force : bool, optional
+       If True, in case `entity_a` and `entity_b` have the same properties, the
+       values of `entity_a` are replaced by those of `entity_b` in the merge.
+       If `False`, a RuntimeError is raised instead. Default is False.
 
     Returns
     -------
@@ -421,6 +425,9 @@ def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_emp
                     if (diff_r1["properties"][key][attribute] is None):
                         setattr(entity_a.get_property(key), attribute,
                                 diff_r2["properties"][key][attribute])
+                    elif force:
+                        setattr(entity_a.get_property(key), attribute,
+                                diff_r2["properties"][key][attribute])
                     else:
                         raise RuntimeError(
                             f"Merge conflict:\nEntity a ({entity_a.id}, {entity_a.name}) "
@@ -448,6 +455,9 @@ def merge_entities(entity_a: Entity, entity_b: Entity, merge_references_with_emp
         if sa_a != sa_b:
             if sa_a is None:
                 setattr(entity_a, special_attribute, sa_b)
+            elif force:
+                # force overwrite
+                setattr(entity_a, special_attribute, sa_b)
             else:
                 raise RuntimeError("Merge conflict.")
     return entity_a
diff --git a/unittests/test_apiutils.py b/unittests/test_apiutils.py
index 89be9b86ae840e39271cc1b2aca7f0e0a82100cc..7b22d9956931fff4bded7f4eab813e9b91181997 100644
--- a/unittests/test_apiutils.py
+++ b/unittests/test_apiutils.py
@@ -1,11 +1,11 @@
-# -*- encoding: utf-8 -*-
 #
 # This file is a part of the CaosDB Project.
 #
-# Copyright (C) 2018 Research Group Biomedical Physics,
-# Max-Planck-Institute for Dynamics and Self-Organization Göttingen
 # Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
+# Copyright (C) 2022 Florian Spreckelsen <f.spreckelsen@indiscale.com>
 # Copyright (C) 2020-2022 IndiScale GmbH <info@indiscale.com>
+# Copyright (C) 2018 Research Group Biomedical Physics,
+# Max-Planck-Institute for Dynamics and Self-Organization Göttingen
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU Affero General Public License as
@@ -20,7 +20,6 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program. If not, see <https://www.gnu.org/licenses/>.
 #
-# ** end header
 #
 # Test apiutils
 # A. Schlemmer, 02/2018
@@ -466,3 +465,90 @@ def test_empty_diff():
         "RefType"), value=[ref_rec_b, ref_rec_b])
     assert not empty_diff(rec_a, rec_b)
     assert empty_diff(rec_a, rec_b, compare_referenced_records=True)
+
+
+def test_force_merge():
+    """Test whether a forced merge overwrites existing properties correctly."""
+
+    # name overwrite
+    recA = db.Record(name="A")
+    recB = db.Record(name="B")
+
+    with pytest.raises(RuntimeError) as re:
+        merge_entities(recA, recB)
+    assert "Merge conflict" in str(re.value)
+
+    merge_entities(recA, recB, force=True)
+    assert "B" == recA.name
+    # unchanged
+    assert "B" == recB.name
+
+    # description overwrite
+    recA = db.Record()
+    recA.description = "something"
+    recB = db.Record()
+    recB.description = "something else"
+
+    with pytest.raises(RuntimeError) as re:
+        merge_entities(recA, recB)
+    assert "Merge conflict" in str(re.value)
+
+    merge_entities(recA, recB, force=True)
+    assert recA.description == "something else"
+    # unchanged
+    assert recB.description == "something else"
+
+    # property overwrite
+    recA = db.Record()
+    recA.add_property(name="propA", value="something")
+    recB = db.Record()
+    recB.add_property(name="propA", value="something else")
+
+    with pytest.raises(RuntimeError) as re:
+        merge_entities(recA, recB)
+    assert "Merge conflict" in str(re.value)
+
+    merge_entities(recA, recB, force=True)
+    assert recA.get_property("propA").value == "something else"
+    # unchanged
+    assert recB.get_property("propA").value == "something else"
+
+    # don't remove a property that's not in recB
+    recA = db.Record()
+    recA.add_property(name="propA", value="something")
+    recA.add_property(name="propB", value=5.0)
+    recB = db.Record()
+    recB.add_property(name="propA", value="something else")
+
+    merge_entities(recA, recB, force=True)
+    assert recA.get_property("propA").value == "something else"
+    assert recA.get_property("propB").value == 5.0
+
+    # also overwrite datatypes ...
+    rtA = db.RecordType()
+    rtA.add_property(name="propA", datatype=db.INTEGER)
+    rtB = db.RecordType()
+    rtB.add_property(name="propA", datatype=db.TEXT)
+
+    with pytest.raises(RuntimeError) as re:
+        merge_entities(rtA, rtB)
+    assert "Merge conflict" in str(re.value)
+
+    merge_entities(rtA, rtB, force=True)
+    assert rtA.get_property("propA").datatype == db.TEXT
+    # unchanged
+    assert rtB.get_property("propA").datatype == db.TEXT
+
+    # ... and units
+    recA = db.Record()
+    recA.add_property(name="propA", value=5, unit="m")
+    recB = db.Record()
+    recB.add_property(name="propA", value=5, unit="cm")
+
+    with pytest.raises(RuntimeError) as re:
+        merge_entities(recA, recB)
+    assert "Merge conflict" in str(re.value)
+    merge_entities(recA, recB, force=True)
+    assert recA.get_property("propA").unit == "cm"
+    # unchanged
+    assert recB.get_property("propA").unit == "cm"