diff --git a/pkg/items/item.go b/pkg/items/item.go
index f0fc81809947e1b6282c72ef514a2ecb730aa33f..7c34d2bb3563b338d6c3cb0baf97c4e49f58b535 100644
--- a/pkg/items/item.go
+++ b/pkg/items/item.go
@@ -69,6 +69,7 @@ var SystemFields = []string{
 	"updated_at",
 	"updated_by",
 	"revision_id",
+	"revision_description",
 	"data",
 	"translations",
 	"locale",
@@ -86,21 +87,22 @@ type Permissions struct {
 }
 
 type Item struct {
-	ID           string                            `json:"id" bson:"_id"` // ID - Идентификатор записи. Автоматически генерируется системой при сохранении первой ревизии.
-	SpaceID      string                            `json:"spaceId" bson:"-"`
-	EnvID        string                            `json:"envId" bson:"-"`
-	CollectionID string                            `json:"collectionId" bson:"-"`
-	State        State                             `json:"state" bson:"state"`
-	CreatedRevAt time.Time                         `json:"createdRevAt,omitempty" bson:"created_rev_at,omitempty"`
-	CreatedBy    string                            `json:"createdBy,omitempty" bson:"created_by,omitempty"`
-	CreatedAt    time.Time                         `json:"createdAt,omitempty" bson:"created_at,omitempty"`
-	UpdatedAt    time.Time                         `json:"updatedAt,omitempty" bson:"updated_at,omitempty"`
-	UpdatedBy    string                            `json:"updatedBy,omitempty" bson:"updated_by,omitempty"`
-	Data         map[string]interface{}            `json:"data" bson:"data"`
-	Locale       string                            `json:"locale" bson:"-"`
-	Translations map[string]map[string]interface{} `json:"translations" bson:"translations,omitempty"`
-	RevisionID   string                            `json:"revId,omitempty" bson:"revision_id"`
-	Permissions  *Permissions                      `json:"permissions,omitempty" bson:"-"`
+	ID                  string                            `json:"id" bson:"_id"` // ID - Идентификатор записи. Автоматически генерируется системой при сохранении первой ревизии.
+	SpaceID             string                            `json:"spaceId" bson:"-"`
+	EnvID               string                            `json:"envId" bson:"-"`
+	CollectionID        string                            `json:"collectionId" bson:"-"`
+	State               State                             `json:"state" bson:"state"`
+	CreatedRevAt        time.Time                         `json:"createdRevAt,omitempty" bson:"created_rev_at,omitempty"`
+	CreatedBy           string                            `json:"createdBy,omitempty" bson:"created_by,omitempty"`
+	CreatedAt           time.Time                         `json:"createdAt,omitempty" bson:"created_at,omitempty"`
+	UpdatedAt           time.Time                         `json:"updatedAt,omitempty" bson:"updated_at,omitempty"`
+	UpdatedBy           string                            `json:"updatedBy,omitempty" bson:"updated_by,omitempty"`
+	Data                map[string]interface{}            `json:"data" bson:"data"`
+	Locale              string                            `json:"locale" bson:"-"`
+	Translations        map[string]map[string]interface{} `json:"translations" bson:"translations,omitempty"`
+	RevisionID          string                            `json:"revId,omitempty" bson:"revision_id"`
+	RevisionDescription string                            `json:"revDescription,omitempty" bson:"revision_description"`
+	Permissions         *Permissions                      `json:"permissions,omitempty" bson:"-"`
 
 	// Флаги записи
 	Deleted  bool `json:"deleted" bson:"deleted,omitempty"`
@@ -135,23 +137,24 @@ func (i *Item) Clone() *Item {
 
 func (i *Item) ToMap() map[string]interface{} {
 	return map[string]interface{}{
-		"id":             i.ID,
-		"space_id":       i.SpaceID,
-		"env_id":         i.EnvID,
-		"collection_id":  i.CollectionID,
-		"state":          i.State,
-		"created_rev_at": i.CreatedRevAt,
-		"created_by":     i.CreatedBy,
-		"created_at":     i.CreatedAt,
-		"updated_at":     i.UpdatedAt,
-		"updated_by":     i.UpdatedBy,
-		"revision_id":    i.RevisionID,
-		"data":           i.Data,
-		"translations":   i.Translations,
-		"locale":         i.Locale,
-		"deleted":        i.Deleted,
-		"hidden":         i.Hidden,
-		"template":       i.Template,
+		"id":                   i.ID,
+		"space_id":             i.SpaceID,
+		"env_id":               i.EnvID,
+		"collection_id":        i.CollectionID,
+		"state":                i.State,
+		"created_rev_at":       i.CreatedRevAt,
+		"created_by":           i.CreatedBy,
+		"created_at":           i.CreatedAt,
+		"updated_at":           i.UpdatedAt,
+		"updated_by":           i.UpdatedBy,
+		"revision_id":          i.RevisionID,
+		"revision_description": i.RevisionDescription,
+		"data":                 i.Data,
+		"translations":         i.Translations,
+		"locale":               i.Locale,
+		"deleted":              i.Deleted,
+		"hidden":               i.Hidden,
+		"template":             i.Template,
 	}
 }
 
@@ -304,6 +307,8 @@ func (i *Item) SetSystemField(field string, value interface{}) error {
 		i.UpdatedAt, ok = value.(time.Time)
 	case "revision_id":
 		i.RevisionID, ok = value.(string)
+	case "revision_description":
+		i.RevisionDescription, ok = value.(string)
 	case "hidden":
 		i.Hidden, ok = value.(bool)
 	case "deleted":
@@ -344,6 +349,8 @@ func (i *Item) GetSystem(field string) (any, error) {
 		return i.UpdatedAt, nil
 	case "revision_id":
 		return i.RevisionID, nil
+	case "revision_description":
+		return i.RevisionDescription, nil
 	case "hidden":
 		return i.Hidden, nil
 	case "deleted":
@@ -394,7 +401,7 @@ func (i *Item) Get(field string) (any, error) {
 // GetSystemField возвращает описание поля для системных аттрибутов Item
 func GetSystemField(fld string) (*field.Field, error) {
 	switch fld {
-	case "id", "space_id", "env_id", "collection_id", "revision_id":
+	case "id", "space_id", "env_id", "collection_id", "revision_id", "revision_description":
 		return field.String(), nil
 	case "created_rev_at", "created_at", "updated_at", "published_at":
 		return field.Time(), nil
@@ -439,18 +446,19 @@ func ItemToProto(item *Item) *pb.Item {
 	}
 
 	protoItem := &pb.Item{
-		Id:           item.ID,
-		SpaceId:      item.SpaceID,
-		EnvId:        item.EnvID,
-		CollectionId: item.CollectionID,
-		State:        pb.Item_State(item.State),
-		CreatedBy:    item.CreatedBy,
-		UpdatedBy:    item.UpdatedBy,
-		RevisionId:   item.RevisionID,
-		Locale:       item.Locale,
-		Hidden:       item.Hidden,
-		Template:     item.Template,
-		Deleted:      item.Deleted,
+		Id:                  item.ID,
+		SpaceId:             item.SpaceID,
+		EnvId:               item.EnvID,
+		CollectionId:        item.CollectionID,
+		State:               pb.Item_State(item.State),
+		CreatedBy:           item.CreatedBy,
+		UpdatedBy:           item.UpdatedBy,
+		RevisionId:          item.RevisionID,
+		RevisionDescription: item.RevisionDescription,
+		Locale:              item.Locale,
+		Hidden:              item.Hidden,
+		Template:            item.Template,
+		Deleted:             item.Deleted,
 	}
 
 	if item.Data != nil {
@@ -487,18 +495,19 @@ func ItemFromProto(protoItem *pb.Item) *Item {
 	}
 
 	item := &Item{
-		ID:           protoItem.Id,
-		SpaceID:      protoItem.SpaceId,
-		EnvID:        protoItem.EnvId,
-		CollectionID: protoItem.CollectionId,
-		State:        State(protoItem.State),
-		CreatedBy:    protoItem.CreatedBy,
-		UpdatedBy:    protoItem.UpdatedBy,
-		RevisionID:   protoItem.RevisionId,
-		Locale:       protoItem.Locale,
-		Hidden:       protoItem.Hidden,
-		Template:     protoItem.Template,
-		Deleted:      protoItem.Deleted,
+		ID:                  protoItem.Id,
+		SpaceID:             protoItem.SpaceId,
+		EnvID:               protoItem.EnvId,
+		CollectionID:        protoItem.CollectionId,
+		State:               State(protoItem.State),
+		CreatedBy:           protoItem.CreatedBy,
+		UpdatedBy:           protoItem.UpdatedBy,
+		RevisionID:          protoItem.RevisionId,
+		RevisionDescription: protoItem.RevisionDescription,
+		Locale:              protoItem.Locale,
+		Hidden:              protoItem.Hidden,
+		Template:            protoItem.Template,
+		Deleted:             protoItem.Deleted,
 	}
 
 	if protoItem.Data != nil {
diff --git a/pkg/schema/walk/fn.go b/pkg/schema/walk/fn.go
index c3eaf35c569c18ba8ead7c7ff48c08d03f2a9d90..9b1d4f22316cf37cae1af824d98f611b7dc0bcf7 100644
--- a/pkg/schema/walk/fn.go
+++ b/pkg/schema/walk/fn.go
@@ -1,10 +1,15 @@
 package walk
 
+import "reflect"
+
 func GenericMerge(c *WalkContext) (err error) {
 	return
 }
 
 func KeepSrc(c *WalkContext) (err error) {
+	if reflect.DeepEqual(c.Src, c.Dst) {
+		return
+	}
 	c.Dst = c.Src
 	c.Changed = true
 	return
diff --git a/pkg/schema/walk/walk_test.go b/pkg/schema/walk/walk_test.go
index e20adb462735e83c92c8b04f5c159e336e49f2b0..3fd01bd577c3fe16abb1cae7b2e9785e0edc659c 100644
--- a/pkg/schema/walk/walk_test.go
+++ b/pkg/schema/walk/walk_test.go
@@ -46,6 +46,54 @@ func TestWalker_DataWalk(t *testing.T) {
 		wantErr     bool
 	}{
 		{"generic",
+			&WalkConfig{
+				Fields: map[string]FieldConfig{},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
+			map[string]interface{}{
+				"a":                 "dst_a",
+				"field_not_extists": "remove",
+				"obj1": map[string]interface{}{
+					"a": "dst_obj1_a",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+				},
+				"inline_str_1": "dst_inline_1",
+				"inline_str_2": "dst_inline_2",
+				"slice":        []interface{}{"dst_s1", "dst_s2", "dst_s3"},
+			},
+			map[string]interface{}{
+				"a": "dst_a",
+				"obj1": map[string]interface{}{
+					"a": "dst_obj1_a",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+				},
+				"inline_str_1": "dst_inline_1",
+				"inline_str_2": "dst_inline_2",
+				"slice":        []interface{}{"dst_s1", "dst_s2", "dst_s3"},
+			},
+			false, false,
+		},
+		{"keep src changed",
 			&WalkConfig{
 				Fields: map[string]FieldConfig{
 					"obj1.a":       {Fn: KeepSrc},
@@ -96,6 +144,68 @@ func TestWalker_DataWalk(t *testing.T) {
 				"inline_str_2": "src_inline_2",
 				"slice":        []interface{}{"dst_s1", "src_s2", "dst_s3"},
 			},
+			true, false,
+		},
+		{"keep src not changed",
+			&WalkConfig{
+				Fields: map[string]FieldConfig{
+					"obj1.a":       {Fn: KeepSrc},
+					"slice.1":      {Fn: KeepSrc},
+					"inline_str_1": {Fn: KeepSrc},
+					"inline_str_2": {Fn: KeepSrc},
+				},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
 			false, false,
 		},
 	}
@@ -103,11 +213,12 @@ func TestWalker_DataWalk(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			m := NewWalker(s, tt.config)
 			dst := tt.dst
-			res, _, err := m.DataWalk(context.Background(), dst, tt.src)
-			assert.Equal(t, tt.res, res)
+			res, chg, err := m.DataWalk(context.Background(), dst, tt.src)
 			if tt.wantErr {
 				require.Error(t, err)
 			} else {
+				assert.Equal(t, tt.res, res)
+				assert.Equal(t, tt.wantChanged, chg)
 				require.NoError(t, err)
 			}
 		})