Trying to figure out how to write a function that can open every scene in a project and make a change, if needed. First, I wanted to find out how to open a scene and save it without any modifications if I didn’t modify the scene. I ended up with the following code:

@tool
class_name Migrate
extends Button
 
func _ready() -> void:
	pressed.connect(_on_pressed)
 
func _on_pressed() -> void:
	migrate_scenes("res://")
 
func migrate_scenes(path: String) -> void:
	var files = DirAccess.get_files_at(path)
	var folders = DirAccess.get_directories_at(path)
 
	for file in files:
		if not file.ends_with(".tscn"):
			continue
 
		var result = migrate_scene(path + file)
		if result != OK:
			print("Failed to migrate scene \"", path + file, "\"")
			return
 
	for folder in folders:
		migrate_scenes(path + folder + "/")
 
func migrate_scene(path: String) -> Error:
	var scene: PackedScene = load(path)
	var root := scene.instantiate(PackedScene.GEN_EDIT_STATE_INSTANCE)
 
	var result := scene.pack(root)
	root.free()
	if result != OK:
		print("Error while packing \"", path, "\"")
		return result
 
	result = ResourceSaver.save(scene, path)
	if result != OK:
		print("Error while saving \"", path, "\"")
		return result
 
	return OK

Unfortunately, this appears to result in Godot modifying scenes for some unknown reason. In particular, it seems that reference IDs change. For example:

$ git diff godot/prefabs/viewport_decal/
diff --git a/godot/prefabs/viewport_decal/viewport_decal.tscn b/godot/prefabs/viewport_decal/viewport_decal.tscn
index 30c39760..9381ec63 100644
--- a/godot/prefabs/viewport_decal/viewport_decal.tscn
+++ b/godot/prefabs/viewport_decal/viewport_decal.tscn
@@ -2,13 +2,13 @@

 [ext_resource type="Script" path="res://prefabs/viewport_decal/viewport_decal.gd" id="1_krot6"]

-[sub_resource type="ViewportTexture" id="ViewportTexture_p6k6r"]
+[sub_resource type="ViewportTexture" id="ViewportTexture_bcsvw"]
 viewport_path = NodePath("Viewport")

 [node name="Decal" type="Decal"]
 transform = Transform3D(-4.37114e-08, -4.37114e-08, -1, -1, 1.91069e-15, 4.37114e-08, 0, 1, -4.37114e-08, -4.94398, 1.47306, -2.56415)
 size = Vector3(2, 1, 1)
-texture_albedo = SubResource("ViewportTexture_p6k6r")
+texture_albedo = SubResource("ViewportTexture_bcsvw")
 script = ExtResource("1_krot6")

 [node name="Viewport" type="SubViewport" parent="."]

I thought this might be due to tool scripts, but it appears that this scene does not have any tool scripts in it.