diff --git a/changes/feature29532 b/changes/feature29532
new file mode 100644
index 0000000000000000000000000000000000000000..4d95e6bca810637884621241c4ab33c61213bd19
--- /dev/null
+++ b/changes/feature29532
@@ -0,0 +1,4 @@
+  o Minor features (developer tooling):
+    - Modify git pre-push hook script to disallow pushing branches other than
+      master, release-* and maint-* to origin remote. Implements feature
+      29532.
diff --git a/scripts/maint/pre-push.git-hook b/scripts/maint/pre-push.git-hook
index 26296023fb3047647d6810293342ef8835d1b2f7..e7a72efa08dcb9c293d2af089d2c2ca0e918bfe5 100755
--- a/scripts/maint/pre-push.git-hook
+++ b/scripts/maint/pre-push.git-hook
@@ -1,24 +1,31 @@
 #!/bin/bash
 
+# git pre-push hook script to:
+# 1) prevent "fixup!" and "squash!" commit from ending up in master, release-*
+#    or maint-*
+# 2) Disallow pushing branches other than master, release-*
+#    and maint-* to origin (e.g. gitweb.torproject.org).
+#
 # To install this script, copy it into .git/hooks/pre-push path in your
 # local copy of git repository. Make sure it has permission to execute.
 #
-# This is git pre-push hook script to prevent "fixup!" and "squash!" commits
-# from ending up in upstream branches (master, release-* or maint-*).
-#
 # The following sample script was used as starting point:
 # https://github.com/git/git/blob/master/templates/hooks--pre-push.sample
 
+echo "Running pre-push hook"
+
 z40=0000000000000000000000000000000000000000
 
-CUR_BRANCH=$(git rev-parse --abbrev-ref HEAD)
-if [ "$CUR_BRANCH" != "master" ] && [[ $CUR_BRANCH != release-* ]] &&
-        [[ $CUR_BRANCH != maint-* ]]
-then
-        exit 0
-fi
+remote="$1"
 
-echo "Running pre-push hook"
+ref_is_upstream_branch() {
+        if [ "$1" == "refs/heads/master" ] ||
+                [[ "$1" == refs/heads/release-* ]] ||
+                [[ "$1" == refs/heads/maint-* ]]
+        then
+                return 1
+        fi
+}
 
 # shellcheck disable=SC2034
 while read -r local_ref local_sha remote_ref remote_sha
@@ -37,6 +44,20 @@ do
 			range="$remote_sha..$local_sha"
 		fi
 
+                if (ref_is_upstream_branch "$local_ref" == 0 ||
+                        ref_is_upstream_branch "$remote_ref"  == 0) &&
+                        [ "$local_ref" != "$remote_ref" ]
+                then
+                        if [ "$remote" == "origin" ]
+                        then
+                                echo >&2 "Not pushing: $local_ref to $remote_ref"
+			        echo >&2 "If you really want to push this, use --no-verify."
+                                exit 1
+                        else
+                                continue
+                        fi
+                fi
+
                 # Check for fixup! commit
                 commit=$(git rev-list -n 1 --grep '^fixup!' "$range")
 		if [ -n "$commit" ]