diff --git a/reviewboard/hostingsvcs/errors.py b/reviewboard/hostingsvcs/errors.py
index 762a549382eb305807bc04434f453a2f66e98710..773b085c11927cee550d5b3d542eeac6b0b45c23 100644
--- a/reviewboard/hostingsvcs/errors.py
+++ b/reviewboard/hostingsvcs/errors.py
@@ -3,7 +3,10 @@ from __future__ import unicode_literals
 
 class HostingServiceError(Exception):
     """Base class for errors related to a hosting service."""
-    pass
+    def __init__(self, message, http_code=None):
+        super(HostingServiceError, self).__init__(message)
+
+        self.http_code = http_code
 
 
 class RepositoryError(HostingServiceError):
diff --git a/reviewboard/hostingsvcs/github.py b/reviewboard/hostingsvcs/github.py
index a6915c4b32885e48c58cb61254cb6d2272678821..e9a75ff28fdae2c58b44ed7e1dd664831e7d6d0f 100644
--- a/reviewboard/hostingsvcs/github.py
+++ b/reviewboard/hostingsvcs/github.py
@@ -11,6 +11,7 @@ from django.conf import settings
 from django.conf.urls import patterns, url
 from django.contrib.sites.models import Site
 from django.core.cache import cache
+from django.core.exceptions import ObjectDoesNotExist
 from django.http import HttpResponse
 from django.utils import six
 from django.utils.six.moves.urllib.error import HTTPError, URLError
@@ -299,6 +300,16 @@ class GitHubClient(HostingServiceClient):
         return self.api_get_list(self._build_api_url(url),
                                  start=start, per_page=per_page)
 
+    def api_get_remote_repository(self, api_url, owner, repository_id):
+        try:
+            return self.api_get(self._build_api_url(
+                '%srepos/%s/%s' % (api_url, owner, repository_id)))
+        except HostingServiceError as e:
+            if e.http_code == 404:
+                return None
+            else:
+                raise
+
     def api_get_tree(self, repo_api_url, sha, recursive=False):
         url = self._build_api_url(repo_api_url, 'git/trees/%s' % sha)
 
@@ -354,14 +365,15 @@ class GitHubClient(HostingServiceClient):
             if x_github_otp.startswith('required;'):
                 raise TwoFactorAuthCodeRequiredError(
                     _('Enter your two-factor authentication code. '
-                      'This code will be sent to you by GitHub.'))
+                      'This code will be sent to you by GitHub.'),
+                    http_code=e.code)
 
             if e.code == 401:
-                raise AuthorizationError(rsp['message'])
+                raise AuthorizationError(rsp['message'], http_code=e.code)
 
-            raise HostingServiceError(rsp['message'])
+            raise HostingServiceError(rsp['message'], http_code=e.code)
         else:
-            raise HostingServiceError(six.text_type(e))
+            raise HostingServiceError(six.text_type(e), http_code=e.code)
 
 
 class GitHub(HostingService):
@@ -815,17 +827,47 @@ class GitHub(HostingService):
         return ProxyPaginator(
             paginator,
             normalize_page_data_func=lambda page_data: [
-                RemoteRepository(self,
-                                 repository_id=repo['id'],
-                                 name=repo['name'],
-                                 owner=repo['owner']['login'],
-                                 scm_type='Git',
-                                 path=repo['clone_url'],
-                                 mirror_path=repo['mirror_url'],
-                                 extra_data=repo)
+                RemoteRepository(
+                    self,
+                    repository_id='%s/%s' % (repo['owner']['login'],
+                                             repo['name']),
+                    name=repo['name'],
+                    owner=repo['owner']['login'],
+                    scm_type='Git',
+                    path=repo['clone_url'],
+                    mirror_path=repo['mirror_url'],
+                    extra_data=repo)
                 for repo in page_data
             ])
 
+    def get_remote_repository(self, repository_id):
+        """Get the remote repository for the ID.
+
+        The ID is expected to be an ID returned from get_remote_repositories(),
+        in the form of "owner/repo_id".
+
+        If the repository is not found, ObjectDoesNotExist will be raised.
+        """
+        parts = repository_id.split('/')
+        repo = None
+
+        if len(parts) == 2:
+            repo = self.client.api_get_remote_repository(
+                self.get_api_url(self.account.hosting_url),
+                *parts)
+
+        if not repo:
+            raise ObjectDoesNotExist
+
+        return RemoteRepository(self,
+                                repository_id=repository_id,
+                                name=repo['name'],
+                                owner=repo['owner']['login'],
+                                scm_type='Git',
+                                path=repo['clone_url'],
+                                mirror_path=repo['mirror_url'],
+                                extra_data=repo)
+
     def _reset_authorization(self, client_id, client_secret, token):
         """Resets the authorization info for an OAuth app-linked token.
 
diff --git a/reviewboard/hostingsvcs/service.py b/reviewboard/hostingsvcs/service.py
index 8a8284a059be5a26fc763be84b04e5ed73498824..0236f96d950524daffcf1c727fdd781dd06946d1 100644
--- a/reviewboard/hostingsvcs/service.py
+++ b/reviewboard/hostingsvcs/service.py
@@ -313,6 +313,14 @@ class HostingService(object):
         """
         raise NotImplementedError
 
+    def get_remote_repository(self, repository_id):
+        """Get the remote repository for the ID.
+
+        This should be implemented by subclasses, and is expected to return
+        a RemoteRepository if found, or raise ObjectDoesNotExist if not found.
+        """
+        raise NotImplementedError
+
     @classmethod
     def get_repository_fields(cls, username, hosting_url, plan, tool_name,
                               field_vars):
diff --git a/reviewboard/hostingsvcs/tests.py b/reviewboard/hostingsvcs/tests.py
index a5e203751653f5af0e609b9f4d77a2b5b5242ee7..82e1c0c2a0805b069950508621d7ea84d977924e 100644
--- a/reviewboard/hostingsvcs/tests.py
+++ b/reviewboard/hostingsvcs/tests.py
@@ -5,6 +5,7 @@ from hashlib import md5
 from textwrap import dedent
 
 from django.conf.urls import patterns, url
+from django.core.exceptions import ObjectDoesNotExist
 from django.http import HttpResponse
 from django.utils import six
 from django.utils.six.moves import cStringIO as StringIO
@@ -1351,6 +1352,7 @@ class GitHubTests(ServiceTests):
         repo = paginator.page_data[0]
 
         self.assertIsInstance(repo, RemoteRepository)
+        self.assertEqual(repo.id, 'myuser/myrepo')
         self.assertEqual(repo.owner, 'myuser')
         self.assertEqual(repo.name, 'myrepo')
         self.assertEqual(repo.scm_type, 'Git')
@@ -1365,6 +1367,7 @@ class GitHubTests(ServiceTests):
         repo = paginator.page_data[0]
 
         self.assertIsInstance(repo, RemoteRepository)
+        self.assertEqual(repo.id, 'myuser/myrepo2')
         self.assertEqual(repo.owner, 'myuser')
         self.assertEqual(repo.name, 'myrepo2')
         self.assertEqual(repo.scm_type, 'Git')
@@ -1414,6 +1417,7 @@ class GitHubTests(ServiceTests):
         self.assertEqual(len(paginator.page_data), 1)
         public_repo = paginator.page_data[0]
         self.assertIsInstance(public_repo, RemoteRepository)
+        self.assertEqual(public_repo.id, 'other/myrepo')
         self.assertEqual(public_repo.owner, 'other')
         self.assertEqual(public_repo.name, 'myrepo')
         self.assertEqual(public_repo.scm_type, 'Git')
@@ -1466,6 +1470,7 @@ class GitHubTests(ServiceTests):
         public_repo, private_repo = paginator.page_data
 
         self.assertIsInstance(public_repo, RemoteRepository)
+        self.assertEqual(public_repo.id, 'myorg/myrepo')
         self.assertEqual(public_repo.owner, 'myorg')
         self.assertEqual(public_repo.name, 'myrepo')
         self.assertEqual(public_repo.scm_type, 'Git')
@@ -1473,6 +1478,7 @@ class GitHubTests(ServiceTests):
         self.assertEqual(public_repo.mirror_path, 'myrepo_mirror')
 
         self.assertIsInstance(private_repo, RemoteRepository)
+        self.assertEqual(private_repo.id, 'myuser/myrepo2')
         self.assertEqual(private_repo.owner, 'myuser')
         self.assertEqual(private_repo.name, 'myrepo2')
         self.assertEqual(private_repo.scm_type, 'Git')
@@ -1517,6 +1523,70 @@ class GitHubTests(ServiceTests):
 
         service.get_remote_repositories('myuser', filter_type='private')
 
+    def test_get_remote_repository(self, **kwargs):
+        """Testing GitHub.get_remote_repository"""
+        def _http_get(service, url, *args, **kwargs):
+            self.assertEqual(
+                url,
+                'https://api.github.com/repos/myuser/myrepo'
+                '?access_token=123')
+
+            repo_data = {
+                'id': 1,
+                'owner': {
+                    'login': 'myuser',
+                },
+                'name': 'myrepo',
+                'clone_url': 'myrepo_path',
+                'mirror_url': 'myrepo_mirror',
+                'private': 'false'
+            }
+
+            return json.dumps(repo_data), {}
+
+        account = self._get_hosting_account()
+        account.data['authorization'] = {
+            'token': '123',
+        }
+
+        service = account.service
+        self.spy_on(service.client.http_get, call_fake=_http_get)
+
+        remote_repository = service.get_remote_repository('myuser/myrepo')
+
+        self.assertIsInstance(remote_repository, RemoteRepository)
+        self.assertEqual(remote_repository.id, 'myuser/myrepo')
+        self.assertEqual(remote_repository.owner, 'myuser')
+        self.assertEqual(remote_repository.name, 'myrepo')
+        self.assertEqual(remote_repository.scm_type, 'Git')
+        self.assertEqual(remote_repository.path, 'myrepo_path')
+        self.assertEqual(remote_repository.mirror_path, 'myrepo_mirror')
+
+    def test_get_remote_repository_invalid(self, **kwargs):
+        """Testing GitHub.get_remote_repository with invalid repository ID"""
+        def _http_get(service, url, *args, **kwargs):
+            self.assertEqual(
+                url,
+                'https://api.github.com/repos/myuser/invalid'
+                '?access_token=123')
+
+            payload = {
+                'message': 'Not Found',
+            }
+
+            raise HTTPError(url, 404, '', {}, StringIO(json.dumps(payload)))
+
+        account = self._get_hosting_account()
+        account.data['authorization'] = {
+            'token': '123',
+        }
+
+        service = account.service
+        self.spy_on(service.client.http_get, call_fake=_http_get)
+
+        self.assertRaises(ObjectDoesNotExist,
+                          service.get_remote_repository, 'myuser/invalid')
+
     def _test_check_repository(self, expected_user='myuser', **kwargs):
         def _http_get(service, url, *args, **kwargs):
             self.assertEqual(
