diff --git a/doc/4.6-final.md b/doc/4.6-final.md
index 30404ce4c54634bf430d2d154c10c45b8b1eebc1..f67dae762b4867831c3e37bed223f4f8df695ade 100644
--- a/doc/4.6-final.md
+++ b/doc/4.6-final.md
@@ -1 +1,82 @@
-TODO
\ No newline at end of file
+# CiviCRM v4.6.x: Publish a final release
+
+## Pre-requisites
+
+ * Installed+configured [Google Cloud SDK](https://cloud.google.com/sdk/downloads). (Run `gcloud init`, `gcloud auth activate-service-account --key-file ...`, or similar.)
+ * Write access to all main CiviCRM GitHub repos (`civicrm-{core,packages,backdrop,drupal,joomla,wordpress}`)
+ * Write access to Google Cloud Storage (`civicrm` and `civicrm-build` buckets)
+ * Write access to SourceForge account (`civicrm`)
+ * Import the CiviCRM GPG keypair (`7A1E75CB`)
+ * Local copy of [buildkit](https://github.com/civicrm/civicrm-buildkit/)
+ * Local clones of all main CiviCRM git repos (e.g. `mkdir src; cd src; gitify all --skip-gencode` or `cividist create dist`)
+
+The user `releaser` on `latest.civicrm.org` has a suitable configuration in `~/src/4.6`.
+
+## Identify the final RC
+
+Determine the identity of the final release candidate:
+
+```
+gsutil ls gs://civicrm-build/4.6/*json
+```
+
+For example, we might pick `gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json`.
+
+## Publish
+
+You can do the full process in one command:
+
+```
+cd /path/to/civicrm
+releaser gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json --get --sign --tag --publish
+```
+
+or do the steps individually:
+
+```
+cd /path/to/civicrm
+
+## Get the RC tarballs
+releaser gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json --get
+
+## Generate signatures for tarballs
+releaser gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json --sign
+
+## Generate tags (dry run)
+releaser gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json --tag -n
+
+## Publish tarballs (dry run)
+releaser gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json --publish -n
+
+## Tag (really)
+releaser gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json --tag -f
+
+## Publish (really)
+releaser gs://civicrm-build/4.6/civicrm-4.6.28-201705030600.json --publish
+```
+
+Internally, these commands will:
+ * Copy and rename the build artifacts for `civicrm-4.6.28-*201705030600*`
+ * Generate and sign the MD5SUMS
+ * Push `git` tags in each repo
+   * Fetch each `git` repo
+   * Determine the `git` commits used in this build
+   * Create tags for each repo
+   * Push tags for each repo
+ * Publish the tarballs through the primary, long-term distribution channels
+   * Copy the corresponding tarballs to Google Cloud
+   * Copy the corresponding tarballs to Sourceforge
+
+## Set default on `civicrm.org` (WIP)
+
+... updating versions.json...
+
+## Bump version
+
+```
+cd ~/src/4.6
+git checkout 4.6
+git pull --ff-only origin 4.6
+./tools/bin/scripts/set-version.php 4.6.Y --commit
+git push origin 4.6
+```
diff --git a/doc/4.7-final.md b/doc/4.7-final.md
index 35c19a07602adc13df53d2857b24890a5d88efe8..d10858a9f1d956c91567f2e964f2f9349303b3a1 100644
--- a/doc/4.7-final.md
+++ b/doc/4.7-final.md
@@ -10,7 +10,7 @@
  * Local copy of [buildkit](https://github.com/civicrm/civicrm-buildkit/)
  * Local clones of all main CiviCRM git repos (e.g. `mkdir src; cd src; gitify all --skip-gencode` or `cividist create dist`)
 
-The user `releaser` on `latest.civicrm.org` has a suitable configuration in `~/src`.
+The user `releaser` on `latest.civicrm.org` has a suitable configuration in `~/src/4.7`.
 
 ## Identify the final RC
 
diff --git a/doc/4.7-rc.md b/doc/4.7-rc.md
index 8566eeccd1e4e3b054adfbd485d1a01e26cf4c8d..58ad13a50eecc9cbb670813a9d8842fdf503e489 100644
--- a/doc/4.7-rc.md
+++ b/doc/4.7-rc.md
@@ -78,6 +78,7 @@ The original branch, "master", should continue development with the next version
 ```bash
 cd ~/buildkit/build/dist/src
 git checkout master
-git pull origin master
+git pull --ff-only origin master
 ./tools/bin/scripts/set-version.php 4.7.Y --commit
+git push origin master
 ```