This article is for anyone still on Angular versions 2.x, 4.x, or 5.x.
Since May of 2018 and the release of version 6.0, it's been easy to stay up to date with Angular. That was the release where the CLI, framework, and material packages were all synchronized on their major versions. The 6.0 release introduced a version of ng update that would automatically migrate your applications, keeping them up to date by using Schematics.
If you are on version 6 or later, you get all of these benefits, but what if your application is on version 5, 4, or 2? You could manually move from 2->4 by updating your package.json, then move from 4->5 the same way. You could finally use the 6.0 CLI version of ng update to move to 6.0, but this isn't my recommendation.

Start from scratch

My core recommendation is to start from scratch. Not restarting your code (components, modules, etc), but only the build system and other files that the Angular CLI creates. This includes things like polyfills.ts, tsconfig.json files, your angular.json (formerly angular-cli.json) and other build configuration.

Step 1: Start a new CLI project

Since we're starting from scratch, let's start with the latest version of Angular. You can either install it globally, or just run:
npx @angular/cli new my-new-app

This will create a blank project, following all of the latest and greatest best practices.

Step 2: Migrate your application code

You should basically be able to copy and paste all of your TypeScript code from your src/app folder into the new src/app folder.
This should virtually work out of the box, but you should double-check things at this point. open VS Code and look for errors and make sure the major functionality of your app works.
If you have any dependencies, you'll have to add them back into your package.json.

Step 3: Fix any Angular changes

Versions 4, 5, 6, 7, 8, and 9 don't include a ton of breaking changes, but there's a chance that something isn't compatible.
Take a look at update.angular.io and see the list of changes that have happened within Angular. This should give you some high-level guidance for fixing anything that might have changed.

Step 4: Migrate your assets and other files

Now that the application works, make it complete by migrating assets, favicons, and anything else that you might have to update pointers for in your angular.json file.

Step 5: Double-check everything

At this point, you should be all set. There might be some final cleanup necessary. Things like dependencies should be updated. Make sure your linting and end to end tests work.

Step 6: Fix your git history

This is a little bit complex, but I recommend blowing away the my-new-app git configuration located in .git and then copy the .git folder from the old project.
When you run git status, you should be able to run git add . to stage a large single diff, moving your application from your old version to the new version of Angular. Then you can git commit and finalize and push the changes back to your repository.