diff --git a/reviewboard/hostingsvcs/assembla.py b/reviewboard/hostingsvcs/assembla.py
index 35e86a6469d029031d62999b205c30c8a738db72..41aaf68102af7eb36957fcc9f090d523b7054a54 100644
--- a/reviewboard/hostingsvcs/assembla.py
+++ b/reviewboard/hostingsvcs/assembla.py
@@ -2,13 +2,13 @@
 from django.utils.translation import gettext_lazy as _
 
 from reviewboard.admin.server import get_hostname
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 
 
-class AssemblaForm(HostingServiceForm):
+class AssemblaForm(BaseHostingServiceRepositoryForm):
     assembla_project_id = forms.CharField(
         label=_('Project ID'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/beanstalk.py b/reviewboard/hostingsvcs/beanstalk.py
index 3b5cc81484d51d7fd5d97c334bb588ea4c4f233b..fe813396c5def66d7b88ca2327f4c75b6d17b616 100644
--- a/reviewboard/hostingsvcs/beanstalk.py
+++ b/reviewboard/hostingsvcs/beanstalk.py
@@ -12,9 +12,11 @@
 from django.views.decorators.http import require_POST
 
 from reviewboard.admin.server import get_server_url
+from reviewboard.hostingsvcs.base.forms import (
+    BaseHostingServiceAuthForm,
+    BaseHostingServiceRepositoryForm,
+)
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
-                                           HostingServiceForm)
 from reviewboard.hostingsvcs.hook_utils import (close_all_review_requests,
                                                 get_review_request_id)
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
@@ -27,7 +29,7 @@
 logger = logging.getLogger(__name__)
 
 
-class BeanstalkAuthForm(HostingServiceAuthForm):
+class BeanstalkAuthForm(BaseHostingServiceAuthForm):
     """Authentication form for the Beanstalk hosting service.
 
     This replaces some of the help text to make setup a bit easier.
@@ -52,7 +54,7 @@
         }
 
 
-class BeanstalkForm(HostingServiceForm):
+class BeanstalkForm(BaseHostingServiceRepositoryForm):
     beanstalk_account_domain = forms.CharField(
         label=_('Beanstalk account domain'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/bitbucket.py b/reviewboard/hostingsvcs/bitbucket.py
index ec74a278610cc8eaf66f70d70d2a7cc3e03ac9fb..cb0a984b5000bad74b5d8d220f3a8d702eb2976a 100644
--- a/reviewboard/hostingsvcs/bitbucket.py
+++ b/reviewboard/hostingsvcs/bitbucket.py
@@ -15,6 +15,10 @@
 from django.views.decorators.http import require_POST
 
 from reviewboard.admin.server import build_server_url, get_server_url
+from reviewboard.hostingsvcs.base.forms import (
+    BaseHostingServiceAuthForm,
+    BaseHostingServiceRepositoryForm,
+)
 from reviewboard.hostingsvcs.base.client import HostingServiceClient
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
@@ -22,8 +26,6 @@
                                             HostingServiceError,
                                             InvalidPlanError,
                                             RepositoryError)
-from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
-                                           HostingServiceForm)
 from reviewboard.hostingsvcs.hook_utils import (close_all_review_requests,
                                                 get_repository_for_hook,
                                                 get_review_request_id)
@@ -38,7 +40,7 @@
 logger = logging.getLogger(__name__)
 
 
-class BitbucketAuthForm(HostingServiceAuthForm):
+class BitbucketAuthForm(BaseHostingServiceAuthForm):
     """Authentication form for linking a Bitbucket account."""
 
     def clean_hosting_account_username(self):
@@ -84,7 +86,7 @@
         }
 
 
-class BitbucketPersonalForm(HostingServiceForm):
+class BitbucketPersonalForm(BaseHostingServiceRepositoryForm):
     bitbucket_repo_name = forms.CharField(
         label=_('Repository name'),
         max_length=64,
@@ -95,7 +97,7 @@
                     '&lt;username&gt;/&lt;repo_name&gt;/'))
 
 
-class BitbucketOtherUserForm(HostingServiceForm):
+class BitbucketOtherUserForm(BaseHostingServiceRepositoryForm):
     bitbucket_other_user_username = forms.CharField(
         label=_('Username'),
         max_length=64,
@@ -117,7 +119,7 @@
                     '&lt;repo_name&gt;/'))
 
 
-class BitbucketTeamForm(HostingServiceForm):
+class BitbucketTeamForm(BaseHostingServiceRepositoryForm):
     bitbucket_team_name = forms.CharField(
         label=_('Team name'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/bugzilla.py b/reviewboard/hostingsvcs/bugzilla.py
index 938a78fb003ad23ba2ddc5886778942fe9dd2a2b..33d59c57d434f84099c82d7db86538917d352b79 100644
--- a/reviewboard/hostingsvcs/bugzilla.py
+++ b/reviewboard/hostingsvcs/bugzilla.py
@@ -3,16 +3,16 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.bugtracker import BugTracker
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
 
 
 logger = logging.getLogger(__name__)
 
 
-class BugzillaForm(HostingServiceForm):
+class BugzillaForm(BaseHostingServiceRepositoryForm):
     bugzilla_url = forms.CharField(
         label=_('Bugzilla URL'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/codebasehq.py b/reviewboard/hostingsvcs/codebasehq.py
index c4f8a8240062835231ad6c1cecddd691a99307a4..4e38085a3e0f632b839aa2d7b154b9dbbe578003 100644
--- a/reviewboard/hostingsvcs/codebasehq.py
+++ b/reviewboard/hostingsvcs/codebasehq.py
@@ -6,12 +6,14 @@
 from django.utils.translation import gettext_lazy as _, gettext
 
 from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.forms import (
+    BaseHostingServiceAuthForm,
+    BaseHostingServiceRepositoryForm,
+)
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceAPIError,
                                             RepositoryError)
-from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
-                                           HostingServiceForm)
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 from reviewboard.scmtools.errors import FileNotFoundError
@@ -20,7 +22,7 @@
 logger = logging.getLogger(__name__)
 
 
-class CodebaseHQAuthForm(HostingServiceAuthForm):
+class CodebaseHQAuthForm(BaseHostingServiceAuthForm):
     api_key = forms.CharField(
         label=_('API key'),
         max_length=128,
@@ -60,7 +62,7 @@
         }
 
 
-class CodebaseHQForm(HostingServiceForm):
+class CodebaseHQForm(BaseHostingServiceRepositoryForm):
     codebasehq_project_name = forms.CharField(
         label=_('Project name'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/fedorahosted.py b/reviewboard/hostingsvcs/fedorahosted.py
index ea6cf01951317f9f628799073b134a37c75c6d5e..bcd20d5ce370d94e975c992f2dff755cd8f8b645 100644
--- a/reviewboard/hostingsvcs/fedorahosted.py
+++ b/reviewboard/hostingsvcs/fedorahosted.py
@@ -1,11 +1,11 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
-from reviewboard.hostingsvcs.forms import HostingServiceForm
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 
 
-class FedoraHostedForm(HostingServiceForm):
+class FedoraHostedForm(BaseHostingServiceRepositoryForm):
     fedorahosted_repo_name = forms.CharField(
         label=_('Repository name'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/fogbugz.py b/reviewboard/hostingsvcs/fogbugz.py
index 9b54904cb6cdf4326cf318c0fd61b1889a36f283..3d58315e42cd8482f5b9d61c21d70f974dcd940f 100644
--- a/reviewboard/hostingsvcs/fogbugz.py
+++ b/reviewboard/hostingsvcs/fogbugz.py
@@ -1,11 +1,11 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
-class FogBugzForm(HostingServiceForm):
+class FogBugzForm(BaseHostingServiceRepositoryForm):
     fogbugz_account_domain = forms.CharField(
         label=_('Account domain'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/forms.py b/reviewboard/hostingsvcs/forms.py
index d42362253ad6a58854b808501a3a875774c67879..d5c6f972315648e8703d6c7e1ac18683c0779648 100644
--- a/reviewboard/hostingsvcs/forms.py
+++ b/reviewboard/hostingsvcs/forms.py
@@ -4,9 +4,51 @@
 the classes in :py:mod:`reviewboard.hostingsvcs.base.forms`.
 """
 
-from reviewboard.hostingsvcs.base.forms import (
-    BaseHostingServiceAuthForm as HostingServiceAuthForm,
-    BaseHostingServiceRepositoryForm as HostingServiceForm)
+from __future__ import annotations
+
+from typing_extensions import deprecated
+
+from reviewboard.deprecation import RemovedInReviewBoard100Warning
+from reviewboard.hostingsvcs.base import forms
+
+
+# This can't use housekeeping.ClassMovedMixin because that interferes with the
+# form metaclass.
+@deprecated(
+    '`reviewboard.hostingsvcs.forms.HostingServiceAuthForm` has moved '
+    'to `reviewboard.hostingsvcs.base.forms.BaseHostingServiceAuthForm`. '
+    'The old class name is deprecated and will be removed in Review Board '
+    '10.0',
+    category=RemovedInReviewBoard100Warning)
+class HostingServiceAuthForm(forms.BaseHostingServiceAuthForm):
+    """Base form for handling authentication information for a hosting account.
+
+    Deprecated:
+        8.0:
+        This has been moved to :py:class:`reviewboard.hostingsvcs.base.forms.
+        BaseHostingServiceAuthForm`. The legacy import will be removed in
+        Review Board 10.
+    """
+
+
+# This can't use housekeeping.ClassMovedMixin because that interferes with the
+# form metaclass.
+@deprecated(
+    '`reviewboard.hostingsvcs.forms.HostingServiceForm` has moved '
+    'to `reviewboard.hostingsvcs.base.forms.'
+    'BaseHostingServiceRepositoryForm`. The old class name is deprecated and '
+    'will be removed in Review Board '
+    '10.0',
+    category=RemovedInReviewBoard100Warning)
+class HostingServiceForm(forms.BaseHostingServiceRepositoryForm):
+    """Base form for collecting information for a hosting service repository.
+
+    Deprecated:
+        8.0:
+        This has been moved to :py:class:`reviewboard.hostingsvcs.base.forms.
+        BaseHostingServiceRepositoryForm`. The legacy import will be removed in
+        Review Board 10.
+    """
 
 
 __all__ = [
diff --git a/reviewboard/hostingsvcs/gerrit.py b/reviewboard/hostingsvcs/gerrit.py
index 47f9f5e87c059efd0473d6794d7221d26725c688..cd10a524b0a8fa48f8234aee2b641d1474be9b60 100644
--- a/reviewboard/hostingsvcs/gerrit.py
+++ b/reviewboard/hostingsvcs/gerrit.py
@@ -11,14 +11,16 @@
 from djblets.util.decorators import cached_property
 
 from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.forms import (
+    BaseHostingServiceAuthForm,
+    BaseHostingServiceRepositoryForm,
+)
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.base.http import HostingServiceHTTPResponse
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceError,
                                             RepositoryError,
                                             HostingServiceAPIError)
-from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
-                                           HostingServiceForm)
 from reviewboard.scmtools.core import Branch, Commit
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
@@ -30,7 +32,7 @@
 _PLUGIN_URL = 'https://github.com/reviewboard/gerrit-reviewboard-plugin/'
 
 
-class GerritAuthForm(HostingServiceAuthForm):
+class GerritAuthForm(BaseHostingServiceAuthForm):
     """The Gerrit authentication form.
 
     Gerrit requires an HTTP password to access the web API, so this form saves
@@ -42,9 +44,7 @@
 
         Args:
             **kwargs (dict):
-                Keyword arguments to pass to
-                :py:meth`:HostingServiceAuthForm.save()
-                <reviewboard.hostingsvcs.forms.HostingServiceAuthForm.save>`.
+                Keyword arguments to pass through to the parent class.
 
         Returns:
             reviewboard.hostingsvcs.models.HostingServiceAccount:
@@ -80,7 +80,7 @@
         }
 
 
-class GerritForm(HostingServiceForm):
+class GerritForm(BaseHostingServiceRepositoryForm):
     """The Gerrit hosting service form."""
 
     gerrit_url = forms.URLField(
diff --git a/reviewboard/hostingsvcs/github.py b/reviewboard/hostingsvcs/github.py
index 93a574397d05612e155c899ebe4e9a9661fec4d1..0c7a9404e5b0a2640c6d5f3a40b8cc893d2c75d6 100644
--- a/reviewboard/hostingsvcs/github.py
+++ b/reviewboard/hostingsvcs/github.py
@@ -28,8 +28,10 @@
                                             HostingServiceError,
                                             InvalidPlanError,
                                             RepositoryError)
-from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
-                                           HostingServiceForm)
+from reviewboard.hostingsvcs.base.forms import (
+    BaseHostingServiceAuthForm,
+    BaseHostingServiceRepositoryForm,
+)
 from reviewboard.hostingsvcs.hook_utils import (close_all_review_requests,
                                                 get_git_branch_name,
                                                 get_repository_for_hook,
@@ -56,7 +58,7 @@
 _REQUIRED_SCOPES = ['admin:repo_hook', 'repo', 'user']
 
 
-class GitHubAuthForm(HostingServiceAuthForm):
+class GitHubAuthForm(BaseHostingServiceAuthForm):
     """Form for authenticating to GitHub."""
 
     class Meta:
@@ -86,7 +88,7 @@
         }
 
 
-class GitHubPublicForm(HostingServiceForm):
+class GitHubPublicForm(BaseHostingServiceRepositoryForm):
     """Sub-form for public repositories owned by a user."""
 
     github_public_repo_name = forms.CharField(
@@ -100,7 +102,7 @@
                     '&lt;repo_name&gt;/</code>'))
 
 
-class GitHubPrivateForm(HostingServiceForm):
+class GitHubPrivateForm(BaseHostingServiceRepositoryForm):
     """Sub-form for private repositories owned by a user."""
 
     github_private_repo_name = forms.CharField(
@@ -114,7 +116,7 @@
                     '&lt;repo_name&gt;/</code>'))
 
 
-class GitHubPublicOrgForm(HostingServiceForm):
+class GitHubPublicOrgForm(BaseHostingServiceRepositoryForm):
     """Sub-form for public repositories owned by an organization."""
 
     github_public_org_name = forms.CharField(
@@ -138,7 +140,7 @@
                     '&lt;repo_name&gt;/</code>'))
 
 
-class GitHubPrivateOrgForm(HostingServiceForm):
+class GitHubPrivateOrgForm(BaseHostingServiceRepositoryForm):
     """Sub-form for private repositories owned by an organization."""
 
     github_private_org_name = forms.CharField(
diff --git a/reviewboard/hostingsvcs/gitlab.py b/reviewboard/hostingsvcs/gitlab.py
index dd4261b50ece115b64d2766f18f503213391eb23..31dffbfbc0055cad9db8cb8c85cce4ffe27135e6 100644
--- a/reviewboard/hostingsvcs/gitlab.py
+++ b/reviewboard/hostingsvcs/gitlab.py
@@ -12,13 +12,15 @@
 from djblets.cache.backend import cache_memoize
 
 from reviewboard.admin.support import get_kb_url
+from reviewboard.hostingsvcs.base.forms import (
+    BaseHostingServiceAuthForm,
+    BaseHostingServiceRepositoryForm,
+)
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceError,
                                             InvalidPlanError,
                                             RepositoryError)
-from reviewboard.hostingsvcs.forms import (HostingServiceAuthForm,
-                                           HostingServiceForm)
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 from reviewboard.scmtools.errors import FileNotFoundError
@@ -126,7 +128,7 @@
             })
 
 
-class GitLabAuthForm(HostingServiceAuthForm):
+class GitLabAuthForm(BaseHostingServiceAuthForm):
     """An authentication form for the GitLab hosting service.
 
     This form allows user to select between gitlab.com and self-hosted
@@ -212,7 +214,7 @@
         return credentials
 
 
-class GitLabPersonalForm(HostingServiceForm):
+class GitLabPersonalForm(BaseHostingServiceRepositoryForm):
     gitlab_personal_repo_name = forms.CharField(
         label=_('Repository name'),
         max_length=64,
@@ -220,7 +222,7 @@
         widget=forms.TextInput(attrs={'size': '60'}))
 
 
-class GitLabGroupForm(HostingServiceForm):
+class GitLabGroupForm(BaseHostingServiceRepositoryForm):
     gitlab_group_name = forms.CharField(
         label=_('GitLab group name'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/gitorious.py b/reviewboard/hostingsvcs/gitorious.py
index 68fb7c2ef0dd9f9cd32f9c2f748aea8bfce4b4d9..c90d94291587adcebf85b41abc6766fa0ef28f5e 100644
--- a/reviewboard/hostingsvcs/gitorious.py
+++ b/reviewboard/hostingsvcs/gitorious.py
@@ -1,11 +1,11 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
-class GitoriousForm(HostingServiceForm):
+class GitoriousForm(BaseHostingServiceRepositoryForm):
     gitorious_project_name = forms.CharField(
         label=_('Project name'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/googlecode.py b/reviewboard/hostingsvcs/googlecode.py
index 74921067c6b4524f1d0b72185517ebb50dd51566..eefa06b663b9be84e5adba7c422f267759f4940e 100644
--- a/reviewboard/hostingsvcs/googlecode.py
+++ b/reviewboard/hostingsvcs/googlecode.py
@@ -1,11 +1,11 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
-class GoogleCodeForm(HostingServiceForm):
+class GoogleCodeForm(BaseHostingServiceRepositoryForm):
     googlecode_project_name = forms.CharField(
         label=_('Project name'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/jira.py b/reviewboard/hostingsvcs/jira.py
index fb3c369db2a29e15798e65107dce87d4ed9dca55..2ff5cd84cff9718318a2f3c103489e2631ba7fb4 100644
--- a/reviewboard/hostingsvcs/jira.py
+++ b/reviewboard/hostingsvcs/jira.py
@@ -10,15 +10,15 @@
     has_jira = False
 
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.bugtracker import BugTracker
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
 logger = logging.getLogger(__name__)
 
 
-class JIRAForm(HostingServiceForm):
+class JIRAForm(BaseHostingServiceRepositoryForm):
     jira_url = forms.CharField(
         label=_('JIRA URL'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/kiln.py b/reviewboard/hostingsvcs/kiln.py
index 734da0eef02c6bab6a5aa65c1870024568df6716..0e09f4116e6dca7c8b08d9349488dc3e3a3f9cb8 100644
--- a/reviewboard/hostingsvcs/kiln.py
+++ b/reviewboard/hostingsvcs/kiln.py
@@ -6,15 +6,15 @@
 from django.utils.translation import gettext, gettext_lazy as _
 
 from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceError,
                                             RepositoryError)
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 from reviewboard.scmtools.errors import FileNotFoundError
 
 
-class KilnForm(HostingServiceForm):
+class KilnForm(BaseHostingServiceRepositoryForm):
     kiln_account_domain = forms.CharField(
         label=_('Account domain'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/rbgateway.py b/reviewboard/hostingsvcs/rbgateway.py
index cbd1656ed8279d0f54d15d724e1d20a2a2357560..ce5fa630cf6bd79e503da784bcd4820ab63fa11a 100644
--- a/reviewboard/hostingsvcs/rbgateway.py
+++ b/reviewboard/hostingsvcs/rbgateway.py
@@ -14,11 +14,11 @@
 
 from reviewboard.admin.server import build_server_url, get_server_url
 from reviewboard.hostingsvcs.base.client import HostingServiceClient
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             HostingServiceAPIError,
                                             HostingServiceError)
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 from reviewboard.hostingsvcs.hook_utils import (close_all_review_requests,
                                                 get_repository_for_hook,
                                                 get_review_request_id)
@@ -120,7 +120,7 @@
     return HttpResponse()
 
 
-class ReviewBoardGatewayForm(HostingServiceForm):
+class ReviewBoardGatewayForm(BaseHostingServiceRepositoryForm):
     """Hosting service form for Review Board Gateway.
 
     Provide an additional field on top of the base hosting service form to
diff --git a/reviewboard/hostingsvcs/redmine.py b/reviewboard/hostingsvcs/redmine.py
index dcce1a26d400ecb49bae7c75ce28f0d6eca5c34d..4adcd5fc40ce15a87d07bc2ba8ac50cd1db85232 100644
--- a/reviewboard/hostingsvcs/redmine.py
+++ b/reviewboard/hostingsvcs/redmine.py
@@ -2,11 +2,11 @@
 from django.utils.translation import gettext_lazy as _
 
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
-class RedmineForm(HostingServiceForm):
+class RedmineForm(BaseHostingServiceRepositoryForm):
     redmine_url = forms.CharField(
         label=_('Redmine URL'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/sourceforge.py b/reviewboard/hostingsvcs/sourceforge.py
index 1aa60f9adef292517cb2bee9fc860a3efec2042d..8f01a8c77d941ce6eca1d9e9b05168094af03085 100644
--- a/reviewboard/hostingsvcs/sourceforge.py
+++ b/reviewboard/hostingsvcs/sourceforge.py
@@ -1,11 +1,11 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
-class SourceForgeForm(HostingServiceForm):
+class SourceForgeForm(BaseHostingServiceRepositoryForm):
     sourceforge_project_name = forms.CharField(
         label=_('Project name'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/splat.py b/reviewboard/hostingsvcs/splat.py
index 05836109e84852de567729a8f72756a474b0621f..bd8f90896583b5684bfcb3d65266b473d1c13374 100644
--- a/reviewboard/hostingsvcs/splat.py
+++ b/reviewboard/hostingsvcs/splat.py
@@ -5,15 +5,15 @@
 from django import forms
 from django.utils.translation import gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.bugtracker import BugTracker
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
 logger = logging.getLogger(__name__)
 
 
-class SplatForm(HostingServiceForm):
+class SplatForm(BaseHostingServiceRepositoryForm):
     """The Splat bug tracker configuration form."""
 
     splat_org_name = forms.SlugField(
diff --git a/reviewboard/hostingsvcs/testing/testcases.py b/reviewboard/hostingsvcs/testing/testcases.py
index 95a69668e243d8e65c43c1ee2a69dbf48ae19fd4..3887843e150aa73b05ff5f0d710bac0ed977fe3d 100644
--- a/reviewboard/hostingsvcs/testing/testcases.py
+++ b/reviewboard/hostingsvcs/testing/testcases.py
@@ -493,7 +493,8 @@
                 A specific repository the form will load from and save to.
 
         Returns:
-            reviewboard.hostingsvcs.forms.HostingServiceForm:
+            reviewboard.hostingsvcs.base.forms.
+            BaseHostingServiceRepositoryForm:
             The resulting hosting service form.
         """
         form_cls = self.service_class.get_field(name='form', plan=plan)
diff --git a/reviewboard/hostingsvcs/tests/test_hosting_service_auth_form.py b/reviewboard/hostingsvcs/tests/test_hosting_service_auth_form.py
index e56c216f57ed2d4c519c6c3fbe6c42e7eadc396e..a3ec0598a240769ae80aa5bb4769335280e3c509 100644
--- a/reviewboard/hostingsvcs/tests/test_hosting_service_auth_form.py
+++ b/reviewboard/hostingsvcs/tests/test_hosting_service_auth_form.py
@@ -1,7 +1,7 @@
 from reviewboard.hostingsvcs.base import hosting_service_registry
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             TwoFactorAuthCodeRequiredError)
-from reviewboard.hostingsvcs.forms import HostingServiceAuthForm
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceAuthForm
 from reviewboard.hostingsvcs.models import HostingServiceAccount
 from reviewboard.site.models import LocalSite
 from reviewboard.testing import TestCase
@@ -10,7 +10,7 @@
 
 
 class HostingServiceAuthFormTests(TestCase):
-    """Unit tests for reviewboard.hostingsvcs.forms.HostingServiceAuthForm."""
+    """Unit tests for BaseHostingServiceAuthForm."""
 
     fixtures = ['test_scmtools']
 
@@ -27,8 +27,9 @@
         hosting_service_registry.unregister(TestService)
 
     def test_override_help_texts(self):
-        """Testing HostingServiceAuthForm subclasses overriding help texts"""
-        class MyAuthForm(HostingServiceAuthForm):
+        """Testing BaseHostingServiceAuthForm subclasses overriding help texts
+        """
+        class MyAuthForm(BaseHostingServiceAuthForm):
             class Meta:
                 help_texts = {
                     'hosting_account_username': 'My help text.',
@@ -40,8 +41,8 @@
                          'My help text.')
 
     def test_override_labels(self):
-        """Testing HostingServiceAuthForm subclasses overriding labels"""
-        class MyAuthForm(HostingServiceAuthForm):
+        """Testing BaseHostingServiceAuthForm subclasses overriding labels"""
+        class MyAuthForm(BaseHostingServiceAuthForm):
             class Meta:
                 labels = {
                     'hosting_account_username': 'My label.',
@@ -53,8 +54,9 @@
                          'My label.')
 
     def test_get_credentials_default(self):
-        """Testing HostingServiceAuthForm.get_credentials default behavior"""
-        form = HostingServiceAuthForm(
+        """Testing BaseHostingServiceAuthForm.get_credentials default behavior
+        """
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -70,10 +72,10 @@
             })
 
     def test_get_credentials_default_with_2fa_code(self):
-        """Testing HostingServiceAuthForm.get_credentials default behavior
+        """Testing BaseHostingServiceAuthForm.get_credentials default behavior
         with two-factor auth code
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -91,10 +93,10 @@
             })
 
     def test_get_credentials_with_form_prefix(self):
-        """Testing HostingServiceAuthForm.get_credentials default behavior
+        """Testing BaseHostingServiceAuthForm.get_credentials default behavior
         with form prefix
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'myservice-hosting_account_username': 'myuser',
                 'myservice-hosting_account_password': 'mypass',
@@ -113,8 +115,8 @@
             })
 
     def test_save_new_account(self):
-        """Testing HostingServiceAuthForm.save with new account"""
-        form = HostingServiceAuthForm(
+        """Testing BaseHostingServiceAuthForm.save with new account"""
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -133,10 +135,10 @@
         self.assertIsNone(hosting_account.local_site)
 
     def test_save_new_account_with_existing_stored(self):
-        """Testing HostingServiceAuthForm.save with new account matching
+        """Testing BaseHostingServiceAuthForm.save with new account matching
         existing stored account information
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -160,9 +162,10 @@
         self.assertIsNone(hosting_account.local_site)
 
     def test_save_new_account_with_hosting_url(self):
-        """Testing HostingServiceAuthForm.save with new account and hosting URL
+        """Testing BaseHostingServiceAuthForm.save with new account and
+        hosting URL
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -182,10 +185,10 @@
         self.assertIsNone(hosting_account.local_site)
 
     def test_save_new_account_with_hosting_url_not_self_hosted(self):
-        """Testing HostingServiceAuthForm.save with new account and hosting URL
-        with non-self-hosted service
+        """Testing BaseHostingServiceAuthForm.save with new account and
+        hosting URL with non-self-hosted service
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -200,10 +203,10 @@
         self.assertIsNone(hosting_account.hosting_url)
 
     def test_save_new_account_without_hosting_url_self_hosted(self):
-        """Testing HostingServiceAuthForm.save with new account and no
+        """Testing BaseHostingServiceAuthForm.save with new account and no
         hosting URL with a self-hosted service
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -218,10 +221,11 @@
             })
 
     def test_save_new_account_with_local_site(self):
-        """Testing HostingServiceAuthForm.save with new account and Local Site
+        """Testing BaseHostingServiceAuthForm.save with new account and Local
+        Site
         """
         local_site = LocalSite.objects.create(name='test-site')
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -241,10 +245,10 @@
         self.assertIsNone(hosting_account.hosting_url)
 
     def test_save_new_account_without_username(self):
-        """Testing HostingServiceAuthForm.save with new account and no
+        """Testing BaseHostingServiceAuthForm.save with new account and no
         username in credentials
         """
-        class MyAuthForm(HostingServiceAuthForm):
+        class MyAuthForm(BaseHostingServiceAuthForm):
             def get_credentials(self):
                 return {}
 
@@ -266,13 +270,14 @@
             form.save()
 
     def test_save_existing_account(self):
-        """Testing HostingServiceAuthForm.save with updating existing account
+        """Testing BaseHostingServiceAuthForm.save with updating existing
+        account
         """
         orig_account = HostingServiceAccount.objects.create(
             service_name='test',
             username='myuser')
 
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -293,14 +298,14 @@
         self.assertIsNone(hosting_account.local_site)
 
     def test_save_existing_account_new_username(self):
-        """Testing HostingServiceAuthForm.save with updating existing account
-        with new username
+        """Testing BaseHostingServiceAuthForm.save with updating existing
+        account with new username
         """
         orig_account = HostingServiceAccount.objects.create(
             service_name='test',
             username='myuser')
 
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'mynewuser',
                 'hosting_account_password': 'mypass',
@@ -321,15 +326,15 @@
         self.assertIsNone(hosting_account.local_site)
 
     def test_save_existing_account_new_hosting_url(self):
-        """Testing HostingServiceAuthForm.save with updating existing account
-        with new hosting URL
+        """Testing BaseHostingServiceAuthForm.save with updating existing
+        account with new hosting URL
         """
         orig_account = HostingServiceAccount.objects.create(
             service_name='self_hosted_test',
             username='myuser',
             hosting_url='example1.com')
 
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': 'myuser',
                 'hosting_account_password': 'mypass',
@@ -351,8 +356,8 @@
         self.assertIsNone(hosting_account.local_site)
 
     def test_save_existing_account_new_service_fails(self):
-        """Testing HostingServiceAuthForm.save with updating existing account
-        with new hosting service fails
+        """Testing BaseHostingServiceAuthForm.save with updating existing
+        account with new hosting service fails
         """
         orig_account = HostingServiceAccount.objects.create(
             service_name='self_hosted_test',
@@ -365,12 +370,12 @@
         )
 
         with self.assertRaisesMessage(ValueError, expected_message):
-            HostingServiceAuthForm(hosting_service_cls=TestService,
+            BaseHostingServiceAuthForm(hosting_service_cls=TestService,
                                    hosting_account=orig_account)
 
     def test_save_existing_account_new_local_site_fails(self):
-        """Testing HostingServiceAuthForm.save with updating existing account
-        with new Local Site fails
+        """Testing BaseHostingServiceAuthForm.save with updating existing
+        account with new Local Site fails
         """
         orig_account = HostingServiceAccount.objects.create(
             service_name='text',
@@ -382,16 +387,16 @@
         )
 
         with self.assertRaisesMessage(ValueError, expected_message):
-            HostingServiceAuthForm(
+            BaseHostingServiceAuthForm(
                 hosting_service_cls=TestService,
                 hosting_account=orig_account,
                 local_site=LocalSite.objects.create(name='test-site'))
 
     def test_save_with_2fa_code_required(self):
-        """Testing HostingServiceAuthForm.save with two-factor auth code
+        """Testing BaseHostingServiceAuthForm.save with two-factor auth code
         required
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': '2fa-user',
                 'hosting_account_password': 'mypass',
@@ -410,10 +415,10 @@
             form.fields['hosting_account_two_factor_auth_code'].required)
 
     def test_save_with_2fa_code_provided(self):
-        """Testing HostingServiceAuthForm.save with two-factor auth code
+        """Testing BaseHostingServiceAuthForm.save with two-factor auth code
         provided
         """
-        form = HostingServiceAuthForm(
+        form = BaseHostingServiceAuthForm(
             {
                 'hosting_account_username': '2fa-user',
                 'hosting_account_password': 'mypass',
diff --git a/reviewboard/hostingsvcs/trac.py b/reviewboard/hostingsvcs/trac.py
index 8500bde92c0af266a416b46203f306c017573b0b..2fc27883526dbe8ae9edcfac743ecbd0a9c006e9 100644
--- a/reviewboard/hostingsvcs/trac.py
+++ b/reviewboard/hostingsvcs/trac.py
@@ -2,11 +2,11 @@
 from django.utils.translation import gettext_lazy as _
 
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
-class TracForm(HostingServiceForm):
+class TracForm(BaseHostingServiceRepositoryForm):
     trac_url = forms.CharField(
         label=_('Trac URL'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/unfuddle.py b/reviewboard/hostingsvcs/unfuddle.py
index 29fe855cc210510729ffd12fd7096937e284b171..3308a263f15beb5e08be7151804ec2721e5a8de9 100644
--- a/reviewboard/hostingsvcs/unfuddle.py
+++ b/reviewboard/hostingsvcs/unfuddle.py
@@ -4,16 +4,16 @@
 from django import forms
 from django.utils.translation import gettext, gettext_lazy as _
 
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
 from reviewboard.hostingsvcs.errors import (AuthorizationError,
                                             RepositoryError)
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 from reviewboard.scmtools.crypto_utils import (decrypt_password,
                                                encrypt_password)
 from reviewboard.scmtools.errors import FileNotFoundError
 
 
-class UnfuddleForm(HostingServiceForm):
+class UnfuddleForm(BaseHostingServiceRepositoryForm):
     unfuddle_account_domain = forms.CharField(
         label=_('Unfuddle account domain'),
         max_length=64,
diff --git a/reviewboard/hostingsvcs/versionone.py b/reviewboard/hostingsvcs/versionone.py
index c1a0b92bd5bd7f6dd1d91bdd16a1b0c9044e7c4b..3924ad27e6aeaf50870437b82fb44489851a5b42 100644
--- a/reviewboard/hostingsvcs/versionone.py
+++ b/reviewboard/hostingsvcs/versionone.py
@@ -2,11 +2,11 @@
 from django.utils.translation import gettext_lazy as _
 
 from reviewboard.admin.validation import validate_bug_tracker_base_hosting_url
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceRepositoryForm
 from reviewboard.hostingsvcs.base.hosting_service import BaseHostingService
-from reviewboard.hostingsvcs.forms import HostingServiceForm
 
 
-class VersionOneForm(HostingServiceForm):
+class VersionOneForm(BaseHostingServiceRepositoryForm):
     versionone_url = forms.CharField(
         label=_('VersionOne URL'),
         max_length=64,
diff --git a/reviewboard/webapi/resources/hosting_service_account.py b/reviewboard/webapi/resources/hosting_service_account.py
index ac5abea971dac583307802a2ea43b035aa828775..76734cb45b0799c1eef15f3ec16a29a1ae389ab9 100644
--- a/reviewboard/webapi/resources/hosting_service_account.py
+++ b/reviewboard/webapi/resources/hosting_service_account.py
@@ -13,7 +13,7 @@
 from djblets.webapi.fields import IntFieldType, StringFieldType
 
 from reviewboard.hostingsvcs.base import hosting_service_registry
-from reviewboard.hostingsvcs.forms import HostingServiceAuthForm
+from reviewboard.hostingsvcs.base.forms import BaseHostingServiceAuthForm
 from reviewboard.hostingsvcs.models import HostingServiceAccount
 from reviewboard.webapi.base import WebAPIResource
 from reviewboard.webapi.decorators import (webapi_check_login_required,
@@ -366,7 +366,7 @@
             }
 
         if service.needs_authorization:
-            form_cls = service.auth_form or HostingServiceAuthForm
+            form_cls = service.auth_form or BaseHostingServiceAuthForm
             form = form_cls(
                 {
                     'hosting_account_password': password,
