add ignored fields to apply
diff --git a/internal/fixture/state.go b/internal/fixture/state.go
index a055095..05caa9c 100644
--- a/internal/fixture/state.go
+++ b/internal/fixture/state.go
@@ -137,7 +137,7 @@
 	return s.UpdateObject(tv, version, ignored, manager)
 }
 
-func (s *State) ApplyObject(tv *typed.TypedValue, version fieldpath.APIVersion, manager string, force bool) error {
+func (s *State) ApplyObject(tv *typed.TypedValue, version fieldpath.APIVersion, ignored *fieldpath.Set, manager string, force bool) error {
 	err := s.checkInit(version)
 	if err != nil {
 		return err
@@ -146,7 +146,7 @@
 	if err != nil {
 		return err
 	}
-	new, managers, err := s.Updater.Apply(s.Live, tv, version, s.Managers, manager, force)
+	new, managers, err := s.Updater.Apply(s.Live, tv, version, s.Managers, ignored, manager, force)
 	if err != nil {
 		return err
 	}
@@ -158,12 +158,12 @@
 }
 
 // Apply the passed in object to the current state
-func (s *State) Apply(obj typed.YAMLObject, version fieldpath.APIVersion, manager string, force bool) error {
+func (s *State) Apply(obj typed.YAMLObject, version fieldpath.APIVersion, ignored *fieldpath.Set, manager string, force bool) error {
 	tv, err := s.Parser.Type(string(version)).FromYAML(FixTabsOrDie(obj))
 	if err != nil {
 		return err
 	}
-	return s.ApplyObject(tv, version, manager, force)
+	return s.ApplyObject(tv, version, ignored, manager, force)
 }
 
 // CompareLive takes a YAML string and returns the comparison with the
@@ -231,10 +231,11 @@
 // conflict, the user can specify the expected conflicts. If conflicts
 // don't match, an error will occur.
 type Apply struct {
-	Manager    string
-	APIVersion fieldpath.APIVersion
-	Object     typed.YAMLObject
-	Conflicts  merge.Conflicts
+	Manager       string
+	APIVersion    fieldpath.APIVersion
+	Object        typed.YAMLObject
+	Conflicts     merge.Conflicts
+	IgnoredFields *fieldpath.Set
 }
 
 var _ Operation = &Apply{}
@@ -253,24 +254,26 @@
 		return nil, err
 	}
 	return ApplyObject{
-		Manager:    a.Manager,
-		APIVersion: a.APIVersion,
-		Object:     tv,
-		Conflicts:  a.Conflicts,
+		Manager:       a.Manager,
+		APIVersion:    a.APIVersion,
+		Object:        tv,
+		Conflicts:     a.Conflicts,
+		IgnoredFields: a.IgnoredFields,
 	}, nil
 }
 
 type ApplyObject struct {
-	Manager    string
-	APIVersion fieldpath.APIVersion
-	Object     *typed.TypedValue
-	Conflicts  merge.Conflicts
+	Manager       string
+	APIVersion    fieldpath.APIVersion
+	Object        *typed.TypedValue
+	Conflicts     merge.Conflicts
+	IgnoredFields *fieldpath.Set
 }
 
 var _ Operation = &ApplyObject{}
 
 func (a ApplyObject) run(state *State) error {
-	err := state.ApplyObject(a.Object, a.APIVersion, a.Manager, false)
+	err := state.ApplyObject(a.Object, a.APIVersion, a.IgnoredFields, a.Manager, false)
 	if err != nil {
 		if _, ok := err.(merge.Conflicts); !ok || a.Conflicts == nil {
 			return err
@@ -300,15 +303,16 @@
 // ForceApply is a type of operation. It is a forced-apply run by a
 // manager with a given object. Any error will be returned.
 type ForceApply struct {
-	Manager    string
-	APIVersion fieldpath.APIVersion
-	Object     typed.YAMLObject
+	Manager       string
+	APIVersion    fieldpath.APIVersion
+	Object        typed.YAMLObject
+	IgnoredFields *fieldpath.Set
 }
 
 var _ Operation = &ForceApply{}
 
 func (f ForceApply) run(state *State) error {
-	return state.Apply(f.Object, f.APIVersion, f.Manager, true)
+	return state.Apply(f.Object, f.APIVersion, f.IgnoredFields, f.Manager, true)
 }
 
 func (f ForceApply) preprocess(parser Parser) (Operation, error) {
@@ -317,24 +321,26 @@
 		return nil, err
 	}
 	return ForceApplyObject{
-		Manager:    f.Manager,
-		APIVersion: f.APIVersion,
-		Object:     tv,
+		Manager:       f.Manager,
+		APIVersion:    f.APIVersion,
+		Object:        tv,
+		IgnoredFields: f.IgnoredFields,
 	}, nil
 }
 
 // ForceApplyObject is a type of operation. It is a forced-apply run by
 // a manager with a given object. Any error will be returned.
 type ForceApplyObject struct {
-	Manager    string
-	APIVersion fieldpath.APIVersion
-	Object     *typed.TypedValue
+	Manager       string
+	APIVersion    fieldpath.APIVersion
+	Object        *typed.TypedValue
+	IgnoredFields *fieldpath.Set
 }
 
 var _ Operation = &ForceApplyObject{}
 
 func (f ForceApplyObject) run(state *State) error {
-	return state.ApplyObject(f.Object, f.APIVersion, f.Manager, true)
+	return state.ApplyObject(f.Object, f.APIVersion, f.IgnoredFields, f.Manager, true)
 }
 
 func (f ForceApplyObject) preprocess(parser Parser) (Operation, error) {
@@ -567,6 +573,9 @@
 		}
 		return fmt.Errorf("manager not found: %s", op.Manager)
 	}
+	if op.Fields == nil {
+		op.Fields = fieldpath.NewSet()
+	}
 	if diff := manager.Set().Difference(op.Fields); !diff.Empty() {
 		return fmt.Errorf("unexpected managedFields for %s: \n%v", op.Manager, diff)
 	}
diff --git a/merge/ignore_test.go b/merge/ignore_test.go
index 1a93cf1..63401ac 100644
--- a/merge/ignore_test.go
+++ b/merge/ignore_test.go
@@ -9,7 +9,7 @@
 
 func TestIgnoredFields(t *testing.T) {
 	tests := map[string]TestCase{
-		"do_not_own_ignored": {
+		"update_does_not_own_ignored": {
 			APIVersion: "v1",
 			Ops: []Operation{
 				Update{
@@ -38,7 +38,7 @@
 				},
 			},
 		},
-		"do_not_steal_ignored": {
+		"update_does_not_steal_ignored": {
 			APIVersion: "v1",
 			Ops: []Operation{
 				Update{
@@ -85,7 +85,7 @@
 				},
 			},
 		},
-		"do_not_own_deep_ignored": {
+		"update_does_not_own_deep_ignored": {
 			APIVersion: "v1",
 			Ops: []Operation{
 				Update{
@@ -108,6 +108,114 @@
 				},
 			},
 		},
+		"apply_does_not_own_ignored": {
+			APIVersion: "v1",
+			Ops: []Operation{
+				Apply{
+					Manager:    "default",
+					APIVersion: "v1",
+					Object: `
+						numeric: 1
+						string: "some string"
+					`,
+					IgnoredFields: fieldpath.NewSet(
+						fieldpath.MakePathOrDie("string"),
+					),
+				},
+				ExpectState{
+					APIVersion: "v1",
+					Object: `
+						numeric: 1
+						string: "some string"
+					`,
+				},
+				ExpectManagedFields{
+					Manager: "default",
+					Fields: fieldpath.NewSet(
+						fieldpath.MakePathOrDie("numeric"),
+					),
+				},
+			},
+		},
+		"apply_does_not_steal_ignored": {
+			APIVersion: "v1",
+			Ops: []Operation{
+				Apply{
+					Manager:    "default",
+					APIVersion: "v1",
+					Object: `
+						numeric: 1
+						string: "some string"
+					`,
+				},
+				ExpectState{
+					APIVersion: "v1",
+					Object: `
+						numeric: 1
+						string: "some string"
+					`,
+				},
+				ExpectManagedFields{
+					Manager: "default",
+					Fields: fieldpath.NewSet(
+						fieldpath.MakePathOrDie("numeric"),
+						fieldpath.MakePathOrDie("string"),
+					),
+				},
+				Apply{
+					Manager:    "default2",
+					APIVersion: "v1",
+					Object: `
+						numeric: 1
+						string: "no string"
+					`,
+					IgnoredFields: fieldpath.NewSet(fieldpath.MakePathOrDie("string")),
+				},
+				ExpectState{
+					APIVersion: "v1",
+					Object: `
+						numeric: 1
+						string: "some string"
+					`,
+				},
+				ExpectManagedFields{
+					Manager: "default",
+					Fields: fieldpath.NewSet(
+						fieldpath.MakePathOrDie("numeric"),
+						fieldpath.MakePathOrDie("string"),
+					),
+				},
+				ExpectManagedFields{
+					Manager: "default2",
+					Fields: fieldpath.NewSet(
+						fieldpath.MakePathOrDie("numeric"),
+					),
+				},
+			},
+		},
+		"apply_does_not_own_deep_ignored": {
+			APIVersion: "v1",
+			Ops: []Operation{
+				Apply{
+					Manager:    "default",
+					APIVersion: "v1",
+					Object:     `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`,
+					IgnoredFields: fieldpath.NewSet(
+						fieldpath.MakePathOrDie("obj"),
+					),
+				},
+				ExpectState{
+					APIVersion: "v1",
+					Object:     `{"numeric": 1, "obj": {"string": "foo", "numeric": 2}}`,
+				},
+				ExpectManagedFields{
+					Manager: "default",
+					Fields: fieldpath.NewSet(
+						fieldpath.MakePathOrDie("numeric"),
+					),
+				},
+			},
+		},
 	}
 
 	for name, test := range tests {
diff --git a/merge/obsolete_versions_test.go b/merge/obsolete_versions_test.go
index 9498a9c..4ac2413 100644
--- a/merge/obsolete_versions_test.go
+++ b/merge/obsolete_versions_test.go
@@ -113,13 +113,13 @@
 		Parser:  SameVersionParser{T: parser.Type("sets")},
 	}
 
-	if err := state.Apply(typed.YAMLObject(`{"list": ["a", "b", "c", "d"]}`), fieldpath.APIVersion("v1"), "apply", false); err != nil {
+	if err := state.Apply(typed.YAMLObject(`{"list": ["a", "b", "c", "d"]}`), fieldpath.APIVersion("v1"), nil, "apply", false); err != nil {
 		t.Fatalf("Failed to apply: %v", err)
 	}
 	// Remove v1, add v2 instead.
 	converter.AcceptedVersions = []fieldpath.APIVersion{"v2"}
 
-	if err := state.Apply(typed.YAMLObject(`{"list": ["a"]}`), fieldpath.APIVersion("v2"), "apply", false); err != nil {
+	if err := state.Apply(typed.YAMLObject(`{"list": ["a"]}`), fieldpath.APIVersion("v2"), nil, "apply", false); err != nil {
 		t.Fatalf("Failed to apply: %v", err)
 	}
 
diff --git a/merge/update.go b/merge/update.go
index e4815e5..4bd65a7 100644
--- a/merge/update.go
+++ b/merge/update.go
@@ -80,6 +80,7 @@
 			if err != nil {
 				return nil, nil, fmt.Errorf("failed to compare objects: %v", err)
 			}
+			compare.Remove(ignored)
 			versions[managerSet.APIVersion()] = compare
 		}
 
@@ -150,7 +151,7 @@
 // well as the configuration that is applied. This will merge the object
 // and return it. If the object hasn't changed, nil is returned (the
 // managers can still have changed though).
-func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, manager string, force bool) (*typed.TypedValue, fieldpath.ManagedFields, error) {
+func (s *Updater) Apply(liveObject, configObject *typed.TypedValue, version fieldpath.APIVersion, managers fieldpath.ManagedFields, ignored *fieldpath.Set, manager string, force bool) (*typed.TypedValue, fieldpath.ManagedFields, error) {
 	managers = shallowCopyManagers(managers)
 	var err error
 	if s.enableUnions {
@@ -171,6 +172,9 @@
 	}
 	lastSet := managers[manager]
 	set, err := configObject.ToFieldSet()
+	if ignored != nil {
+		set = set.RecursiveDifference(ignored)
+	}
 	if err != nil {
 		return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to get field set: %v", err)
 	}
@@ -179,7 +183,7 @@
 	if err != nil {
 		return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to prune fields: %v", err)
 	}
-	managers, compare, err := s.update(liveObject, newObject, version, managers, nil, manager, force)
+	managers, compare, err := s.update(liveObject, newObject, version, managers, ignored, manager, force)
 	if err != nil {
 		return nil, fieldpath.ManagedFields{}, err
 	}