diff --git a/rwm.py b/rwm.py
index 8433e93c220bce38cf40fc6ea450c0908b6cc4a3..c6296672b1139e6212393f1872a6c02858f85247 100755
--- a/rwm.py
+++ b/rwm.py
@@ -346,6 +346,19 @@ class StorageManager:
 
         return 0
 
+    def storage_restore_state(self, source_bucket_name, target_bucket_name, state_object_key):
+        """create new bucket, copy data by selected state_file"""
+
+        target_bucket = self.storage_create(target_bucket_name, "dummy")
+        resp = self.s3.Bucket(source_bucket_name).Object(state_object_key).get()
+        state = json.loads(gzip.decompress(resp['Body'].read()))
+
+        for obj in state["versions"]:
+            if obj["IsLatest"]:
+                target_bucket.Object(obj["Key"]).copy({"Bucket": source_bucket_name, "Key": obj["Key"], "VersionId": obj["VersionId"]})
+
+        return 0
+
 
 class RWM:
     """rwm impl"""
@@ -508,6 +521,11 @@ class RWM:
 
         return self.storage_manager.storage_drop_versions(bucket_name)
 
+    def storage_restore_state(self, source_bucket, target_bucket, state_object_key):
+        """storage restore state"""
+
+        return self.storage_manager.storage_restore_state(source_bucket, target_bucket, state_object_key)
+
 
 def configure_logging(debug):
     """configure logger"""
@@ -564,6 +582,11 @@ def parse_arguments(argv):
     )
     storage_drop_versions_cmd_parser.add_argument("bucket_name", help="bucket name")
 
+    storage_restore_state_cmd_parser = subparsers.add_parser("storage_restore_state", help="restore bucketX stateX1 to bucketY")
+    storage_restore_state_cmd_parser.add_argument("source_bucket", help="source_bucket")
+    storage_restore_state_cmd_parser.add_argument("target_bucket", help="target_bucket; should not exist")
+    storage_restore_state_cmd_parser.add_argument("state", help="state object key in source bucket")
+
     return parser.parse_args(argv)
 
 
@@ -607,6 +630,8 @@ def main(argv=None):  # pylint: disable=too-many-branches
         ret = rwmi.storage_list(args.full, args.filter)
     if args.command == "storage_drop_versions":
         ret = rwmi.storage_drop_versions(args.bucket_name)
+    if args.command == "storage_restore_state":
+        ret = rwmi.storage_restore_state(args.source_bucket, args.target_bucket, args.state)
 
     logger.debug("rwm finished with %s (ret %d)", "success" if ret == 0 else "errors", ret)
     return ret
diff --git a/tests/test_default.py b/tests/test_default.py
index 2059e6f24c7a9018be8b6328bd74323dfba7ee25..c9fece7b97cacc16d325a93305ef7f71465cd49c 100644
--- a/tests/test_default.py
+++ b/tests/test_default.py
@@ -61,3 +61,5 @@ def test_main(tmpworkdir: str):  # pylint: disable=unused-argument
         assert rwm_main(["storage_list"]) == 0
     with patch.object(rwm.RWM, "storage_drop_versions", mock_ok):
         assert rwm_main(["storage_drop_versions", "bucket"]) == 0
+    with patch.object(rwm.RWM, "storage_restore_state", mock_ok):
+        assert rwm_main(["storage_restore_state", "bucket", "bucket", "state"]) == 0
diff --git a/tests/test_rwm.py b/tests/test_rwm.py
index d521e9f9b490e0ecd4f0f8be7c4bac8273bb7bd3..34002d985c527dd58b748ad2a89f52dea685d12f 100644
--- a/tests/test_rwm.py
+++ b/tests/test_rwm.py
@@ -261,3 +261,57 @@ def test_storage_drop_versions(tmpworkdir: str):  # pylint: disable=unused-argum
     mock = Mock(return_value=0)
     with patch.object(rwm.StorageManager, "storage_drop_versions", mock):
         assert trwm.storage_drop_versions("dummy") == 0
+
+
+def test_storage_restore_state_restic(tmpworkdir: str, radosuser_admin: rwm.StorageManager):  # pylint: disable=unused-argument
+    """test restore bucket from previous saved state"""
+
+    trwm = rwm.RWM({
+        "rwm_s3_endpoint_url": radosuser_admin.url,
+        "rwm_s3_access_key": radosuser_admin.access_key,
+        "rwm_s3_secret_key": radosuser_admin.secret_key,
+        "rwm_restic_bucket": "restictest",
+        "rwm_restic_password": "dummydummydummydummy",
+        "rwm_backups": {
+            "testcfg": {
+                "filesdirs": ["testdatadir/"],
+            }
+        }
+    })
+
+    # create and initialize storage
+    assert trwm.storage_create(trwm.config["rwm_restic_bucket"], "dummy") == 0
+    assert trwm.restic_cmd(["init"]).returncode == 0
+
+    # do backups
+    Path("testdatadir").mkdir()
+    Path("testdatadir/testdata1.txt").write_text("dummydata1", encoding="utf-8")
+    assert trwm.backup("testcfg") == 0
+    Path("testdatadir/testdata1.txt").unlink()
+    Path("testdatadir/testdata2.txt").write_text("dummydata2", encoding="utf-8")
+    assert trwm.backup("testcfg") == 0
+
+    # check two snapshots exists with expected content
+    snapshots = _restic_list_snapshots(trwm)
+    snapshot_files = _restic_list_snapshot_files(trwm, snapshots[1]["id"])
+    assert len(snapshots) == 2
+    assert len(snapshot_files) == 1
+    assert "/testdatadir/testdata2.txt" == snapshot_files[0]
+    states = sorted([x.key for x in trwm.storage_manager.s3.Bucket(trwm.config["rwm_restic_bucket"]).objects.filter(Prefix="rwm")])
+    assert len(states) == 2
+
+    # create restore bucket
+    restore_bucket_name = f'{trwm.config["rwm_restic_bucket"]}-restore'
+    trwm.storage_restore_state(trwm.config["rwm_restic_bucket"], restore_bucket_name, states[0])
+
+    # check restore bucket contents
+    trwm_restore = rwm.RWM({
+        **trwm.config,
+        "rwm_restic_bucket": restore_bucket_name
+    })
+    snapshots = _restic_list_snapshots(trwm_restore)
+    snapshot_files = _restic_list_snapshot_files(trwm_restore, snapshots[0]["id"])
+    assert len(snapshots) == 1
+    assert len(snapshot_files) == 1
+    assert "/testdatadir/testdata1.txt" == snapshot_files[0]
+    assert trwm_restore.restic_cmd(["check"]).returncode == 0