diff --git a/pydantic/main.py b/pydantic/main.py
--- a/pydantic/main.py
+++ b/pydantic/main.py
@@ -627,7 +627,12 @@ def copy(
         cls = self.__class__
         m = cls.__new__(cls)
         object_setattr(m, '__dict__', v)
-        object_setattr(m, '__fields_set__', self.__fields_set__.copy())
+        # new `__fields_set__` can have unset optional fields with a set value in `update` kwarg
+        if update:
+            fields_set = self.__fields_set__ | update.keys()
+        else:
+            fields_set = set(self.__fields_set__)
+        object_setattr(m, '__fields_set__', fields_set)
         for name in self.__private_attributes__:
             value = getattr(self, name, Undefined)
             if value is not Undefined:

diff --git a/tests/test_construction.py b/tests/test_construction.py
--- a/tests/test_construction.py
+++ b/tests/test_construction.py
@@ -1,5 +1,5 @@
 import pickle
-from typing import Any, List
+from typing import Any, List, Optional
 
 import pytest
 
@@ -191,6 +191,14 @@ def test_copy_update():
     assert m != m2
 
 
+def test_copy_update_unset():
+    class Foo(BaseModel):
+        foo: Optional[str]
+        bar: Optional[str]
+
+    assert Foo(foo='hello').copy(update={'bar': 'world'}).json(exclude_unset=True) == '{"foo": "hello", "bar": "world"}'
+
+
 def test_copy_set_fields():
     m = ModelTwo(a=24, d=Model(a='12'))
     m2 = m.copy()

BaseModel.copy(update=…) does not update __fields_set__
### Checks

* [x] I added a descriptive title to this issue
* [x] I have searched (google, github) for similar issues and couldn't find anything
* [x] I have read and followed [the docs](https://pydantic-docs.helpmanual.io/) and still think this is a bug

# Bug

Output of `python -c "import pydantic.utils; print(pydantic.utils.version_info())"`:
```
             pydantic version: 1.7.2
            pydantic compiled: False
                 install path: /usr/local/lib/python3.6/dist-packages/pydantic
               python version: 3.6.9 (default, Oct  8 2020, 12:12:24)  [GCC 8.4.0]
                     platform: Linux-4.15.0-112-generic-x86_64-with-Ubuntu-18.04-bionic
     optional deps. installed: ['typing-extensions', 'email-validator']
```

```py
from typing import Optional
import pydantic

class Foo(pydantic.BaseModel):
    foo: Optional[str]
    bar: Optional[str]

print(Foo(foo='hello')
      .copy(update={'bar': 'world'})
      .json(exclude_unset=True))
# Observed: {"foo": "hello"}
# Expected: {"foo": "hello", "bar": "world"}
```

tests/test_construction.py::test_copy_update_unset
tests/test_construction.py::test_simple_construct tests/test_construction.py::test_construct_misuse tests/test_construction.py::test_construct_fields_set tests/test_construction.py::test_large_any_str tests/test_construction.py::test_simple_copy tests/test_construction.py::test_deep_copy tests/test_construction.py::test_copy_exclude tests/test_construction.py::test_copy_include tests/test_construction.py::test_copy_include_exclude tests/test_construction.py::test_copy_advanced_exclude tests/test_construction.py::test_copy_advanced_include tests/test_construction.py::test_copy_advanced_include_exclude tests/test_construction.py::test_copy_update tests/test_construction.py::test_copy_set_fields tests/test_construction.py::test_simple_pickle tests/test_construction.py::test_recursive_pickle tests/test_construction.py::test_immutable_copy tests/test_construction.py::test_pickle_fields_set tests/test_construction.py::test_copy_update_exclude tests/test_construction.py::test_shallow_copy_modify tests/test_construction.py::test_construct_default_factory