Steps below explain to keep the forked version up to date with the upstream branch of a forked repository. I know this was already documented many times, but I was struggling with it for some time, until I have found the workflow that suits me the best, so I documented it.

Create a fork in the UI, clone the forked repository and change directory:

git clone --recurse-submodules
cd forked-repository

Add the upstream remote, do this only if remote is not already present:

git remote add upstream

Get back to the main branch, if not already there:

git checkout main

Fetch latest changes and add them to the repository:

git pull --rebase upstream main

This command can however fail with the following error:

CONFLICT (add/add): Merge conflict in ...
error: could not apply 11fa9d20...
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 11fa9d20...

The above means that there are local unsynchronized changes, that could be introduced via GitHub GUI for instance. To get over them, first abort the rebase:

git rebase --abort

And then run the rebase again specifying strategy:

git pull --rebase -s recursive -X ours upstream main

This command replaces local conflicting files with the files from the upstream without asking, meaning it is potentially dangerous. What is left is to push the changes back into the origin (the fork):

git push --force-with-lease origin main

Repeat last three commands to keep the forked repository updated.

Tip: It is possible to skip writing --rebase with this setting:

git config --global pull.rebase true

For the completeness, here's how remotes should look like:

git remote --verbose
origin (fetch)
origin (push)
upstream (fetch)
upstream (push)

This is a 40th post of #100daystooffload.