{"thread":{"id":"8077","subject":"[StGIT PATCH 2/5] Generate patch names of more uniform length","startedAt":"2007-05-11T01:39:58Z","lastAt":"2007-05-11T01:40:27Z","messageCount":6,"participants":["Karl Hasselström"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"41802","messageId":"20070511013400.13161.9160.stgit@yoghurt","threadId":"8077","inReplyTo":null,"subject":"[StGIT PATCH 0/5] Some tweaks and enhancements","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-05-11T01:39:58Z","receivedAt":"2007-05-11T01:39:58Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"The first and last patches of this series implements the things Petr\nasked for (automatic patch naming with \"stg new\", and uncommitting to\na specified committish). Number 2 and 3 are small cleanups; 4 is a\nrefactoring that's useful in its own right, but also makes it easier\nto do 5.\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"},{"id":"41800","messageId":"20070511014004.13161.39982.stgit@yoghurt","threadId":"8077","inReplyTo":"20070511013400.13161.9160.stgit@yoghurt","subject":"[StGIT PATCH 1/5] Make the \"name\" argument to \"stg new\" optional","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-05-11T01:40:05Z","receivedAt":"2007-05-11T01:40:05Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"From: Karl Hasselström <kha@treskal.com>\n\nIf no name is given, one is generated from the commit message. This\ncan be very handy.\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n---\n\n Documentation/stg-new.txt  |    5 +++--\n stgit/commands/common.py   |   25 -------------------------\n stgit/commands/new.py      |   15 +++++++++++----\n stgit/commands/pick.py     |    2 +-\n stgit/commands/uncommit.py |    3 +--\n stgit/stack.py             |   17 +++++++++++------\n stgit/utils.py             |   27 ++++++++++++++++++++++++++-\n t/t1003-new.sh             |   29 +++++++++++++++++++++++++++++\n 8 files changed, 82 insertions(+), 41 deletions(-)\n\ndiff --git a/Documentation/stg-new.txt b/Documentation/stg-new.txt\nindex 009659a..fbf2f67 100644\n--- a/Documentation/stg-new.txt\n+++ b/Documentation/stg-new.txt\n@@ -10,7 +10,7 @@ stg-new - stgdesc:new[]\n SYNOPSIS\n --------\n [verse]\n-'stg' new [OPTIONS] <name>\n+'stg' new [OPTIONS] [name]\n \n DESCRIPTION\n -----------\n@@ -22,7 +22,8 @@ tree are not included in the patch. A stglink:refresh[] command is\n needed for this.\n \n The given <name> must be unique in the stack, and may only contain\n-alphanumeric characters, dashes and underscores.\n+alphanumeric characters, dashes and underscores. If no name is given,\n+one is generated from the first line of the commit message.\n \n An editor will be launched to edit the commit message to be used for\n the patch, unless the '--message' flag already specified one.  The\ndiff --git a/stgit/commands/common.py b/stgit/commands/common.py\nindex 674d8c1..28026da 100644\n--- a/stgit/commands/common.py\n+++ b/stgit/commands/common.py\n@@ -323,31 +323,6 @@ def address_or_alias(addr_str):\n                  for addr in addr_str.split(',')]\n     return ', '.join([addr for addr in addr_list if addr])\n \n-def patch_name_from_msg(msg):\n-    \"\"\"Return a string to be used as a patch name. This is generated\n-    from the first 30 characters of the top line of the string passed\n-    as argument.\"\"\"\n-    if not msg:\n-        return None\n-\n-    subject_line = msg[:30].lstrip().split('\\n', 1)[0].lower()\n-    return re.sub('[\\W]+', '-', subject_line).strip('-')\n-\n-def make_patch_name(msg, unacceptable, default_name = 'patch',\n-                    alternative = True):\n-    \"\"\"Return a patch name generated from the given commit message,\n-    guaranteed to make unacceptable(name) be false. If the commit\n-    message is empty, base the name on default_name instead.\"\"\"\n-    patchname = patch_name_from_msg(msg)\n-    if not patchname:\n-        patchname = default_name\n-    if alternative and unacceptable(patchname):\n-        suffix = 0\n-        while unacceptable('%s-%d' % (patchname, suffix)):\n-            suffix += 1\n-        patchname = '%s-%d' % (patchname, suffix)\n-    return patchname\n-\n def prepare_rebase(real_rebase, force=None):\n     if not force:\n         # Be sure we won't loose results of stg-(un)commit by error.\ndiff --git a/stgit/commands/new.py b/stgit/commands/new.py\nindex 2c1e94b..f192e34 100644\n--- a/stgit/commands/new.py\n+++ b/stgit/commands/new.py\n@@ -25,7 +25,7 @@ from stgit import stack, git\n \n \n help = 'create a new patch and make it the topmost one'\n-usage = \"\"\"%prog [options] <name>\n+usage = \"\"\"%prog [options] [name]\n \n Create a new, empty patch and make it the topmost one. If the\n '--message' option is not passed, an editor is invoked with the\n@@ -33,7 +33,10 @@ Create a new, empty patch and make it the topmost one. If the\n /usr/share/stgit/templates/patchdescr.tmpl file used a as template,\n together with generated lines. By default, the local changes in the\n working tree are not included in the patch. A 'refresh' command is\n-needed for this.\"\"\"\n+needed for this.\n+\n+If no name is given for the new patch, one is generated from the first\n+line of the commit message.\"\"\"\n \n options = [make_option('-m', '--message',\n                        help = 'use MESSAGE as the patch description'),\n@@ -57,7 +60,11 @@ options = [make_option('-m', '--message',\n def func(parser, options, args):\n     \"\"\"Creates a new patch\n     \"\"\"\n-    if len(args) != 1:\n+    if len(args) == 0:\n+        name = None # autogenerate a name\n+    elif len(args) == 1:\n+        name = args[0]\n+    else:\n         parser.error('incorrect number of arguments')\n \n     check_conflicts()\n@@ -66,7 +73,7 @@ def func(parser, options, args):\n     if options.author:\n         options.authname, options.authemail = name_email(options.author)\n \n-    crt_series.new_patch(args[0], message = options.message,\n+    crt_series.new_patch(name, message = options.message,\n                          show_patch = options.showpatch,\n                          author_name = options.authname,\n                          author_email = options.authemail,\ndiff --git a/stgit/commands/pick.py b/stgit/commands/pick.py\nindex edd614d..75def2a 100644\n--- a/stgit/commands/pick.py\n+++ b/stgit/commands/pick.py\n@@ -75,7 +75,7 @@ def func(parser, options, args):\n         elif len(patch_branch) == 2:\n             patch = patch_branch[0]\n         else:\n-            patch = make_patch_name(commit.get_log(), crt_series.patch_exists)\n+            patch = None\n \n     if options.parent:\n         parent = git_id(options.parent)\ndiff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py\nindex 462846c..04c7e52 100644\n--- a/stgit/commands/uncommit.py\n+++ b/stgit/commands/uncommit.py\n@@ -95,8 +95,7 @@ def func(parser, options, args):\n         if patchnames:\n             patchname = patchnames[n]\n         else:\n-            patchname = make_patch_name(commit.get_log(),\n-                                        crt_series.patch_exists)\n+            patchname = None\n \n         crt_series.new_patch(patchname,\n                              can_edit = False, before_existing = True,\ndiff --git a/stgit/stack.py b/stgit/stack.py\nindex 76704e8..d0008bc 100644\n--- a/stgit/stack.py\n+++ b/stgit/stack.py\n@@ -777,20 +777,25 @@ class Series(StgitObject):\n                   before_existing = False, refresh = True):\n         \"\"\"Creates a new patch\n         \"\"\"\n-        self.__patch_name_valid(name)\n \n-        if self.patch_applied(name) or self.patch_unapplied(name):\n-            raise StackException, 'Patch \"%s\" already exists' % name\n+        if name != None:\n+            self.__patch_name_valid(name)\n+            if self.patch_applied(name) or self.patch_unapplied(name):\n+                raise StackException, 'Patch \"%s\" already exists' % name\n \n         if not message and can_edit:\n-            descr = edit_file(self, None, \\\n-                              'Please enter the description for patch \"%s\" ' \\\n-                              'above.' % name, show_patch)\n+            descr = edit_file(\n+                self, None,\n+                'Please enter the description for the patch above.',\n+                show_patch)\n         else:\n             descr = message\n \n         head = git.get_head()\n \n+        if name == None:\n+            name = make_patch_name(descr, self.patch_exists)\n+\n         patch = Patch(name, self.__patch_dir, self.__refs_dir)\n         patch.create()\n \ndiff --git a/stgit/utils.py b/stgit/utils.py\nindex d04d077..18198c0 100644\n--- a/stgit/utils.py\n+++ b/stgit/utils.py\n@@ -1,7 +1,7 @@\n \"\"\"Common utility functions\n \"\"\"\n \n-import errno, os, os.path, sys\n+import errno, os, os.path, re, sys\n from stgit.config import config\n \n __copyright__ = \"\"\"\n@@ -172,3 +172,28 @@ def call_editor(filename):\n     if err:\n         raise EditorException, 'editor failed, exit code: %d' % err\n     print 'done'\n+\n+def patch_name_from_msg(msg):\n+    \"\"\"Return a string to be used as a patch name. This is generated\n+    from the first 30 characters of the top line of the string passed\n+    as argument.\"\"\"\n+    if not msg:\n+        return None\n+\n+    subject_line = msg[:30].lstrip().split('\\n', 1)[0].lower()\n+    return re.sub('[\\W]+', '-', subject_line).strip('-')\n+\n+def make_patch_name(msg, unacceptable, default_name = 'patch',\n+                    alternative = True):\n+    \"\"\"Return a patch name generated from the given commit message,\n+    guaranteed to make unacceptable(name) be false. If the commit\n+    message is empty, base the name on default_name instead.\"\"\"\n+    patchname = patch_name_from_msg(msg)\n+    if not patchname:\n+        patchname = default_name\n+    if alternative and unacceptable(patchname):\n+        suffix = 0\n+        while unacceptable('%s-%d' % (patchname, suffix)):\n+            suffix += 1\n+        patchname = '%s-%d' % (patchname, suffix)\n+    return patchname\ndiff --git a/t/t1003-new.sh b/t/t1003-new.sh\nnew file mode 100755\nindex 0000000..0be5d9b\n--- /dev/null\n+++ b/t/t1003-new.sh\n@@ -0,0 +1,29 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2007 Karl Hasselström\n+#\n+\n+test_description='Test the new command.\n+\n+'\n+\n+. ./test-lib.sh\n+\n+test_expect_success \\\n+    'Initialize the StGIT repository' '\n+    stg init\n+'\n+\n+test_expect_success \\\n+    'Create a named patch' '\n+    stg new foo -m foobar &&\n+    [ $(stg applied -c) -eq 1 ]\n+'\n+\n+test_expect_success \\\n+    'Create a patch without giving a name' '\n+    stg new -m yo &&\n+    [ $(stg applied -c) -eq 2 ]\n+'\n+\n+test_done\n"},{"id":"41798","messageId":"20070511014010.13161.42319.stgit@yoghurt","threadId":"8077","inReplyTo":"20070511013400.13161.9160.stgit@yoghurt","subject":"[StGIT PATCH 2/5] Generate patch names of more uniform length","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-05-11T01:40:10Z","receivedAt":"2007-05-11T01:40:10Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"From: Karl Hasselström <kha@treskal.com>\n\nCut the generated patch name at 30 characters after getting rid of\nunwanted characters, not before. This gives patch names of more\nuniform length, since consecutive unwanted characters were replaced by\na single dash.\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n---\n\n stgit/utils.py |    8 ++++----\n 1 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/stgit/utils.py b/stgit/utils.py\nindex 18198c0..3612a4b 100644\n--- a/stgit/utils.py\n+++ b/stgit/utils.py\n@@ -175,13 +175,13 @@ def call_editor(filename):\n \n def patch_name_from_msg(msg):\n     \"\"\"Return a string to be used as a patch name. This is generated\n-    from the first 30 characters of the top line of the string passed\n-    as argument.\"\"\"\n+    from the top line of the string passed as argument, and is at most\n+    30 characters long.\"\"\"\n     if not msg:\n         return None\n \n-    subject_line = msg[:30].lstrip().split('\\n', 1)[0].lower()\n-    return re.sub('[\\W]+', '-', subject_line).strip('-')\n+    subject_line = msg.split('\\n', 1)[0].lstrip().lower()\n+    return re.sub('[\\W]+', '-', subject_line).strip('-')[:30]\n \n def make_patch_name(msg, unacceptable, default_name = 'patch',\n                     alternative = True):\n"},{"id":"41803","messageId":"20070511014016.13161.33634.stgit@yoghurt","threadId":"8077","inReplyTo":"20070511013400.13161.9160.stgit@yoghurt","subject":"[StGIT PATCH 3/5] Remove an unnecessary parameter to make_patch_name","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-05-11T01:40:16Z","receivedAt":"2007-05-11T01:40:16Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"From: Karl Hasselström <kha@treskal.com>\n\nThe \"alternative\" parameter was a boolean that indicated whether we\nwere interested in testing if the first generated name was acceptable,\nor if we would just always accept it. But that can be accomplished by\ngiving an \"unacceptable\" function that always returns False, so\nthere's no need for an additional parameter.\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n---\n\n stgit/commands/imprt.py |    8 +++++---\n stgit/utils.py          |    5 ++---\n 2 files changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/stgit/commands/imprt.py b/stgit/commands/imprt.py\nindex 89af472..6fcdc62 100644\n--- a/stgit/commands/imprt.py\n+++ b/stgit/commands/imprt.py\n@@ -242,9 +242,11 @@ def __create_patch(filename, message, author_name, author_email,\n         patch = __strip_patch_name(patch)\n \n     if not patch:\n-        patch = make_patch_name(message, crt_series.patch_exists,\n-                                alternative = not (options.ignore\n-                                                   or options.replace))\n+        if options.ignore or options.replace:\n+            unacceptable_name = lambda name: False\n+        else:\n+            unacceptable_name = crt_series.patch_exists\n+        patch = make_patch_name(message, unacceptable_name)\n     else:\n         # fix possible invalid characters in the patch name\n         patch = re.sub('[^\\w.]+', '-', patch).strip('-')\ndiff --git a/stgit/utils.py b/stgit/utils.py\nindex 3612a4b..fbfe748 100644\n--- a/stgit/utils.py\n+++ b/stgit/utils.py\n@@ -183,15 +183,14 @@ def patch_name_from_msg(msg):\n     subject_line = msg.split('\\n', 1)[0].lstrip().lower()\n     return re.sub('[\\W]+', '-', subject_line).strip('-')[:30]\n \n-def make_patch_name(msg, unacceptable, default_name = 'patch',\n-                    alternative = True):\n+def make_patch_name(msg, unacceptable, default_name = 'patch'):\n     \"\"\"Return a patch name generated from the given commit message,\n     guaranteed to make unacceptable(name) be false. If the commit\n     message is empty, base the name on default_name instead.\"\"\"\n     patchname = patch_name_from_msg(msg)\n     if not patchname:\n         patchname = default_name\n-    if alternative and unacceptable(patchname):\n+    if unacceptable(patchname):\n         suffix = 0\n         while unacceptable('%s-%d' % (patchname, suffix)):\n             suffix += 1\n"},{"id":"41801","messageId":"20070511014021.13161.60939.stgit@yoghurt","threadId":"8077","inReplyTo":"20070511013400.13161.9160.stgit@yoghurt","subject":"[StGIT PATCH 4/5] If any uncommit would fail, don't uncommit anything","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-05-11T01:40:22Z","receivedAt":"2007-05-11T01:40:22Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"From: Karl Hasselström <kha@treskal.com>\n\n\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n---\n\n stgit/commands/uncommit.py |   26 +++++++++++++++-----------\n 1 files changed, 15 insertions(+), 11 deletions(-)\n\ndiff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py\nindex 04c7e52..f86af57 100644\n--- a/stgit/commands/uncommit.py\n+++ b/stgit/commands/uncommit.py\n@@ -80,23 +80,26 @@ def func(parser, options, args):\n     print 'Uncommitting %d patches...' % patch_nr,\n     sys.stdout.flush()\n \n-    for n in xrange(0, patch_nr):\n-        # retrieve the commit (only commits with a single parent are allowed)\n-        commit_id = crt_series.get_base()\n+    def get_commit(commit_id):\n         commit = git.Commit(commit_id)\n         try:\n             parent, = commit.get_parents()\n         except ValueError:\n-            raise CmdException, 'Commit %s does not have exactly one parent' \\\n-                  % commit_id\n+            raise CmdException('Commit %s does not have exactly one parent'\n+                               % commit_id)\n+        return (commit, commit_id, parent)\n+\n+    commits = []\n+    next_commit = crt_series.get_base()\n+    for i in xrange(patch_nr):\n+        commit, commit_id, parent = get_commit(next_commit)\n+        commits.append((commit, commit_id, parent))\n+        next_commit = parent\n+\n+    for (commit, commit_id, parent), patchname in \\\n+        zip(commits, patchnames or (None for i in xrange(len(commits)))):\n         author_name, author_email, author_date = \\\n                      name_email_date(commit.get_author())\n-\n-        if patchnames:\n-            patchname = patchnames[n]\n-        else:\n-            patchname = None\n-\n         crt_series.new_patch(patchname,\n                              can_edit = False, before_existing = True,\n                              top = commit_id, bottom = parent,\n@@ -105,4 +108,5 @@ def func(parser, options, args):\n                              author_email = author_email,\n                              author_date = author_date)\n \n+\n     print 'done'\n"},{"id":"41799","messageId":"20070511014027.13161.869.stgit@yoghurt","threadId":"8077","inReplyTo":"20070511013400.13161.9160.stgit@yoghurt","subject":"[StGIT PATCH 5/5] Uncommit to a named commit","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2007-05-11T01:40:27Z","receivedAt":"2007-05-11T01:40:27Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"From: Karl Hasselström <kha@treskal.com>\n\nAdd a new flag to \"stg uncommit\": --to. This flag takes a committish\nparameter, and uncommits everything up until that commit.\n\nSigned-off-by: Karl Hasselström <kha@treskal.com>\n---\n\n stgit/commands/uncommit.py |   49 +++++++++++++++++++++++++++++++-------------\n t/t1300-uncommit.sh        |    8 +++++++\n 2 files changed, 42 insertions(+), 15 deletions(-)\n\ndiff --git a/stgit/commands/uncommit.py b/stgit/commands/uncommit.py\nindex f86af57..de6a37c 100644\n--- a/stgit/commands/uncommit.py\n+++ b/stgit/commands/uncommit.py\n@@ -25,7 +25,7 @@ from stgit.utils import *\n from stgit import stack, git\n \n help = 'turn regular GIT commits into StGIT patches'\n-usage = \"\"\"%prog [<patchname1> [<patchname2> ... ] | -n [<prefix>]]\n+usage = \"\"\"%prog [<patchnames>] | -n NUM [<prefix>]] | -t <committish>\n \n Take one or more git commits at the base of the current stack and turn\n them into StGIT patches. The new patches are created as applied patches\n@@ -35,24 +35,34 @@ By default, the number of patches to uncommit is determined by the\n number of patch names provided on the command line. First name is used\n for the first patch to uncommit, i.e. for the newest patch.\n \n-The --number option specifies the number of patches to uncommit.  In\n+The -n/--number option specifies the number of patches to uncommit. In\n this case, at most one patch name may be specified. It is used as\n-prefix to which the patch number is appended.\n+prefix to which the patch number is appended. If no patch names are\n+provided on the command line, StGIT automatically generates them based\n+on the first line of the patch description.\n \n-If no patch names are provided on the command line, StGIT\n-automatically generates them based on the first line of the patch\n-description.\n+The -t/--to option specifies that all commits up to and including the\n+given commit should be uncommitted.\n \n Only commits with exactly one parent can be uncommitted; in other\n words, you can't uncommit a merge.\"\"\"\n \n options = [make_option('-n', '--number', type = 'int',\n-                       help = 'uncommit the specified number of commits')]\n+                       help = 'uncommit the specified number of commits'),\n+           make_option('-t', '--to',\n+                       help = 'uncommit to the specified commit')]\n \n def func(parser, options, args):\n     \"\"\"Uncommit a number of patches.\n     \"\"\"\n-    if options.number:\n+    if options.to:\n+        if options.number:\n+            parser.error('cannot give both --to and --number')\n+        if len(args) != 0:\n+            parser.error('cannot specify patch name with --to')\n+        patch_nr = patchnames = None\n+        to_commit = git.rev_parse(options.to)\n+    elif options.number:\n         if options.number <= 0:\n             parser.error('invalid value passed to --number')\n \n@@ -77,9 +87,6 @@ def func(parser, options, args):\n         raise CmdException, \\\n               'This branch is protected. Uncommit is not permitted'\n \n-    print 'Uncommitting %d patches...' % patch_nr,\n-    sys.stdout.flush()\n-\n     def get_commit(commit_id):\n         commit = git.Commit(commit_id)\n         try:\n@@ -91,11 +98,23 @@ def func(parser, options, args):\n \n     commits = []\n     next_commit = crt_series.get_base()\n-    for i in xrange(patch_nr):\n-        commit, commit_id, parent = get_commit(next_commit)\n-        commits.append((commit, commit_id, parent))\n-        next_commit = parent\n+    if patch_nr:\n+        print 'Uncommitting %d patches...' % patch_nr,\n+        for i in xrange(patch_nr):\n+            commit, commit_id, parent = get_commit(next_commit)\n+            commits.append((commit, commit_id, parent))\n+            next_commit = parent\n+    else:\n+        print 'Uncommitting to %s...' % to_commit\n+        while True:\n+            commit, commit_id, parent = get_commit(next_commit)\n+            commits.append((commit, commit_id, parent))\n+            if commit_id == to_commit:\n+                break\n+            next_commit = parent\n+        patch_nr = len(commits)\n \n+    sys.stdout.flush()\n     for (commit, commit_id, parent), patchname in \\\n         zip(commits, patchnames or (None for i in xrange(len(commits)))):\n         author_name, author_email, author_date = \\\ndiff --git a/t/t1300-uncommit.sh b/t/t1300-uncommit.sh\nindex 519234e..2e7ff21 100755\n--- a/t/t1300-uncommit.sh\n+++ b/t/t1300-uncommit.sh\n@@ -70,4 +70,12 @@ test_expect_success \\\n \t[ \"$(stg id foo-patch//top)\" = \"$(stg id bar-patch//bottom)\" ] &&\n \tstg commit\n \t'\n+\n+test_expect_success \\\n+    'Uncommit the patches with --to' '\n+    stg uncommit --to HEAD^ &&\n+    [ \"$(stg id foo-patch//top)\" = \"$(stg id bar-patch//bottom)\" ] &&\n+    stg commit\n+'\n+\n test_done\n"}]}