diff --git a/docs/rbtools/rbt/commands/patch.txt b/docs/rbtools/rbt/commands/patch.txt
index 9c20e19c68f988a9420c2574413fd820c4be571c..65e48dd5ed585196d2b8415e2fdad8115b102294 100644
--- a/docs/rbtools/rbt/commands/patch.txt
+++ b/docs/rbtools/rbt/commands/patch.txt
@@ -48,6 +48,10 @@ Options
 
    Numerical pX argument for patch.
 
+.. cmdoption:: -c, --commit
+
+   Commit using information fetched from the review request (Git only).
+
 .. cmdoption:: --server
 
    Specify a different Review Board server to use.
diff --git a/rbtools/api/resource.py b/rbtools/api/resource.py
index c0d5617376afbab12e57eb5ca544b5f9e7ace849..c075c4cc74984b804215ce889628c0b7b0542e2b 100644
--- a/rbtools/api/resource.py
+++ b/rbtools/api/resource.py
@@ -596,6 +596,19 @@ RESOURCE_MAP['application/vnd.reviewboard.org.draft-screenshots'] = \
 class ReviewRequestResource(ItemResource):
     """The Review Request resource specific base class."""
 
+    @property
+    def absolute_url(self):
+        """Returns the absolute URL for the Review Request.
+
+        The value of absolute_url is returned if it's defined.
+        Otherwise the absolute URL is generated and returned.
+        """
+        if 'absolute_url' in self.fields:
+            return self.fields['absolute_url']
+        else:
+            base_url = self._url.split('/api/')[0]
+            return urlparse.urljoin(base_url, self.url)
+
     @request_method_decorator
     def submit(self, description=None, changenum=None):
         """Submit a review request"""
diff --git a/rbtools/clients/__init__.py b/rbtools/clients/__init__.py
index 7b4c0e0887611d970e898f6e5aba3209f05683e3..c3617e754cc2a49c463a49ba1a8676944dabbc85 100644
--- a/rbtools/clients/__init__.py
+++ b/rbtools/clients/__init__.py
@@ -125,6 +125,14 @@ class SCMClient(object):
         print 'Results:\n' + res
         return res
 
+    def has_pending_changes(self):
+        """Checks if there are changes waiting to be committed.
+
+        Derived classes should override this method if they wish to support
+        checking for pending changes.
+        """
+        raise NotImplementedError
+
     def apply_patch(self, patch_file, base_path, base_dir, p=None):
         """
         Apply the patch patch_file and return True if the patch was
@@ -139,6 +147,14 @@ class SCMClient(object):
             cmd = ['patch', '-i', str(patch_file)]
         self._execute(cmd)
 
+    def create_commmit(self, message, author):
+        """Creates a commit based on the provided message and author.
+
+        Derived classes should override this method if they wish to support
+        committing changes to their repositories.
+        """
+        raise NotImplementedError
+
     def sanitize_changenum(self, changenum):
         """Return a "sanitized" change number.
 
diff --git a/rbtools/clients/git.py b/rbtools/clients/git.py
index 5e4cf5b88495cb0391a6020c4cb91c40934d7d2f..c86fca8bda9d608363535df66eef60208e9cde97 100644
--- a/rbtools/clients/git.py
+++ b/rbtools/clients/git.py
@@ -6,6 +6,7 @@ from rbtools.clients import SCMClient, RepositoryInfo
 from rbtools.clients.perforce import PerforceClient
 from rbtools.clients.svn import SVNClient, SVNRepositoryInfo
 from rbtools.utils.checks import check_install
+from rbtools.utils.console import edit_text
 from rbtools.utils.process import die, execute
 
 
@@ -503,6 +504,15 @@ class GitClient(SCMClient):
             'base_commit_id': self.merge_base,
         }
 
+    def has_pending_changes(self):
+        """Checks if there are changes waiting to be committed.
+
+        Returns True if the working directory has been modified or if changes
+        have been staged in the index, otherwise returns False.
+        """
+        status = execute(['git', 'status', '--porcelain'])
+        return status != ''
+
     def apply_patch(self, patch_file, base_path=None, base_dir=None, p=None):
         """
         Apply the patch patch_file and return True if the patch was
@@ -514,3 +524,9 @@ class GitClient(SCMClient):
             cmd = ['git', 'apply', patch_file]
 
         self._execute(cmd)
+
+    def create_commmit(self, message, author):
+        modified_message = edit_text(message)
+        execute(['git', 'add', '--all', ':/'])
+        execute(['git', 'commit', '-m', modified_message,
+                 '--author="%s <%s>"' % (author.fullname, author.email)])
diff --git a/rbtools/commands/patch.py b/rbtools/commands/patch.py
index f8a3629ed639671647c5d31bfbf1744cb75e6038..ab2ea9de2ce1716020600f3ab00076269f0b27c7 100644
--- a/rbtools/commands/patch.py
+++ b/rbtools/commands/patch.py
@@ -12,6 +12,12 @@ class Patch(Command):
     author = "The Review Board Project"
     args = "<review-request-id>"
     option_list = [
+        Option("-c", "--commit",
+               dest="commit",
+               action="store_true",
+               default=False,
+               help="Commit using information fetched "
+                    "from the review request (Git only)."),
         Option("--diff-revision",
                dest="diff_revision",
                default=None,
@@ -91,6 +97,33 @@ class Patch(Command):
         tool.apply_patch(diff_file_path, repository_info.base_path,
                          base_dir, self.options.px)
 
+    def _extract_commit_message(self, review_request):
+        """Returns a commit message based on the review request.
+
+        The commit message returned contains the Summary, Description, Bugs,
+        and Testing Done fields from the review request, if available.
+        """
+        info = []
+
+        summary = review_request.summary
+        description = review_request.description
+
+        if not description.startswith(summary):
+            info.append(summary)
+
+        info.append(description)
+
+        if review_request.testing_done:
+            info.append('Testing Done:\n%s' % review_request.testing_done)
+
+        if review_request.bugs_closed:
+            info.append('Bugs closed: %s'
+                        % ', '.join(review_request.bugs_closed))
+
+        info.append('Reviewed at %s' % review_request.absolute_url)
+
+        return '\n\n'.join(info)
+
     def main(self, request_id):
         """Run the command."""
         repository_info, tool = self.initialize_scm_tool(
@@ -108,5 +141,34 @@ class Patch(Command):
         if self.options.patch_stdout:
             print diff_body
         else:
+            try:
+                if tool.has_pending_changes():
+                    message = 'Working directory is not clean.'
+
+                    if not self.options.commit:
+                        print 'Warning: %s' % message
+                    else:
+                        raise CommandError(message)
+            except NotImplementedError:
+                pass
+
             self.apply_patch(repository_info, tool, request_id, diff_revision,
                              tmp_patch_file, base_dir)
+
+            if self.options.commit:
+                try:
+                    review_request = api_root.get_review_request(
+                        review_request_id=request_id)
+                except APIError, e:
+                    raise CommandError('Error getting review request %s: %s'
+                                       % (request_id, e))
+
+                message = self._extract_commit_message(review_request)
+                author = review_request.get_submitter()
+
+                try:
+                    tool.create_commmit(message, author)
+                    print('Changes committed to current branch.')
+                except NotImplementedError:
+                    raise CommandError('--commit is not supported with %s'
+                                       % tool.name)
diff --git a/rbtools/commands/post.py b/rbtools/commands/post.py
index 814213a4cb8ccaa3287dee8928f4d63af66a062e..6299a023facf47cca715702cd4f573dfee9af03b 100644
--- a/rbtools/commands/post.py
+++ b/rbtools/commands/post.py
@@ -2,7 +2,6 @@ import logging
 import os
 import re
 import sys
-from urlparse import urljoin
 
 from rbtools.api.errors import APIError
 from rbtools.commands import Command, CommandError, Option
@@ -438,13 +437,7 @@ class Post(Command):
                 raise CommandError(
                     "Error updating review request draft: %s" % e)
 
-        request_url = 'r/%s/' % review_request.id
-        review_url = urljoin(server_url, request_url)
-
-        if not review_url.startswith('http'):
-            review_url = 'http://%s' % review_url
-
-        return review_request.id, review_url
+        return review_request.id, review_request.absolute_url
 
     def main(self, *args):
         """Create and update review requests."""
diff --git a/rbtools/utils/console.py b/rbtools/utils/console.py
new file mode 100644
index 0000000000000000000000000000000000000000..8699f1ca00bbdcbf80ae9175a5ffbe6aae4a0d6d
--- /dev/null
+++ b/rbtools/utils/console.py
@@ -0,0 +1,20 @@
+import os
+import subprocess
+
+from rbtools.utils.filesystem import make_tempfile
+
+
+def edit_text(content):
+    """Allows a user to edit a block of text and returns the saved result.
+
+    The environment's default text editor is used if available, otherwise
+    vim is used.
+    """
+    tempfile = make_tempfile(content)
+    editor = os.environ.get('EDITOR', 'vim')
+    subprocess.call([editor, tempfile])
+    f = open(tempfile)
+    result = f.read()
+    f.close()
+
+    return result
