git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[StGit PATCH 08/14] Add a --hard flag to stg reset

From
Karl Hasselström <kha@treskal.com>
Date
Jun 12, 2008, 05:34 UTC
Message-ID
<20080612053456.23549.41821.stgit@yoghurt>
In-Reply-To
<20080612052913.23549.69687.stgit@yoghurt>

With this flag, reset will overwrite any local changes. Useful e.g. when undoing a push that has polluted the index+worktree with a heap of conflicts.

Signed-off-by: Karl Hasselström <kha@treskal.com>
---
 stgit/commands/reset.py  |   13 +++++++----
 stgit/lib/git.py         |    4 +++
 stgit/lib/transaction.py |   17 ++++++++++++--
 t/t3101-reset-hard.sh    |   56 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 8 deletions(-)
 create mode 100755 t/t3101-reset-hard.sh
diff --git a/stgit/commands/reset.py b/stgit/commands/reset.py
index b2643b1..a7b5d35 100644
--- a/stgit/commands/reset.py
+++ b/stgit/commands/reset.py
@@ -17,12 +17,13 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
+from optparse import make_option
 from stgit.commands import common
 from stgit.lib import git, log, transaction
 from stgit.out import out
 
 help = 'reset the patch stack to an earlier state'
-usage = """%prog <state> [<patchnames>]
+usage = """%prog [options] <state> [<patchnames>]
 
 Reset the patch stack to an earlier state. The state is specified with
 a commit from a stack log; for a branch foo, StGit stores the stack
@@ -43,9 +44,10 @@ If one or more patch names are given, reset only those patches, and
 leave the rest alone."""
 
 directory = common.DirectoryHasRepositoryLib()
-options = []
+options = [make_option('--hard', action = 'store_true',
+                       help = 'discard changes in your index/worktree')]
 
-def reset_stack(stack, iw, state, only_patches):
+def reset_stack(stack, iw, state, only_patches, hard):
     only_patches = set(only_patches)
     def mask(s):
         if only_patches:
@@ -55,7 +57,7 @@ def reset_stack(stack, iw, state, only_patches):
     patches_to_reset = mask(set(state.applied + state.unapplied))
     existing_patches = set(stack.patchorder.all)
     to_delete = mask(existing_patches - patches_to_reset)
-    trans = transaction.StackTransaction(stack, 'reset')
+    trans = transaction.StackTransaction(stack, 'reset', discard_changes = hard)
 
     # If we have to change the stack base, we need to pop all patches
     # first.
@@ -113,4 +115,5 @@ def func(parser, options, args):
         state = log.Log(stack.repository, ref, stack.repository.rev_parse(ref))
     else:
         raise common.CmdException('Wrong number of arguments')
-    return reset_stack(stack, stack.repository.default_iw, state, patches)
+    return reset_stack(stack, stack.repository.default_iw, state, patches,
+                       options.hard)
diff --git a/stgit/lib/git.py b/stgit/lib/git.py
index 35e03d2..4c2605b 100644
--- a/stgit/lib/git.py
+++ b/stgit/lib/git.py
@@ -736,6 +736,10 @@ class IndexAndWorktree(RunWithEnvCwd):
     env = property(lambda self: utils.add_dict(self.__index.env,
                                                self.__worktree.env))
     cwd = property(lambda self: self.__worktree.directory)
+    def checkout_hard(self, tree):
+        assert isinstance(tree, Tree)
+        self.run(['git', 'read-tree', '--reset', '-u', tree.sha1]
+                 ).discard_output()
     def checkout(self, old_tree, new_tree):
         # TODO: Optionally do a 3-way instead of doing nothing when we
         # have a problem. Or maybe we should stash changes in a patch?
diff --git a/stgit/lib/transaction.py b/stgit/lib/transaction.py
index 6347b14..10c9b39 100644
--- a/stgit/lib/transaction.py
+++ b/stgit/lib/transaction.py
@@ -73,7 +73,14 @@ class StackTransaction(object):
       method. This will either succeed in writing the updated state to
       your refs and index+worktree, or fail without having done
       anything."""
-    def __init__(self, stack, msg, allow_conflicts = False):
+    def __init__(self, stack, msg, discard_changes = False,
+                 allow_conflicts = False):
+        """Create a new L{StackTransaction}.
+
+        @param discard_changes: Discard any changes in index+worktree
+        @type discard_changes: bool
+        @param allow_conflicts: Whether to allow pre-existing conflicts
+        @type allow_conflicts: bool or function of L{StackTransaction}"""
         self.__stack = stack
         self.__msg = msg
         self.__patches = _TransPatchMap(stack)
@@ -83,6 +90,7 @@ class StackTransaction(object):
         self.__error = None
         self.__current_tree = self.__stack.head.data.tree
         self.__base = self.__stack.base
+        self.__discard_changes = discard_changes
         if isinstance(allow_conflicts, bool):
             self.__allow_conflicts = lambda trans: allow_conflicts
         else:
@@ -107,7 +115,7 @@ class StackTransaction(object):
                 'This can happen if you modify a branch with git.',
                 '"stg repair --help" explains more about what to do next.')
             self.__abort()
-        if self.__current_tree == tree:
+        if self.__current_tree == tree and not self.__discard_changes:
             # No tree change, but we still want to make sure that
             # there are no unresolved conflicts. Conflicts
             # conceptually "belong" to the topmost patch, and just
@@ -118,7 +126,10 @@ class StackTransaction(object):
             out.error('Need to resolve conflicts first')
             self.__abort()
         assert iw != None
-        iw.checkout(self.__current_tree, tree)
+        if self.__discard_changes:
+            iw.checkout_hard(tree)
+        else:
+            iw.checkout(self.__current_tree, tree)
         self.__current_tree = tree
     @staticmethod
     def __abort():
diff --git a/t/t3101-reset-hard.sh b/t/t3101-reset-hard.sh
new file mode 100755
index 0000000..1e02805
--- /dev/null
+++ b/t/t3101-reset-hard.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description='Simple test cases for "stg reset"'
+
+. ./test-lib.sh
+
+# Ignore our own output files.
+cat > .git/info/exclude <<EOF
+/expected.txt
+/actual.txt
+EOF
+
+test_expect_success 'Initialize StGit stack with three patches' '
+    stg init &&
+    echo 000 >> a &&
+    git add a &&
+    git commit -m a &&
+    echo 111 >> a &&
+    git commit -a -m p1 &&
+    echo 222 >> a &&
+    git commit -a -m p2 &&
+    echo 333 >> a &&
+    git commit -a -m p3 &&
+    stg uncommit -n 3
+'
+
+cat > expected.txt <<EOF
+C a
+EOF
+test_expect_success 'Pop middle patch, creating a conflict' '
+    ! stg pop p2 &&
+    stg status a > actual.txt &&
+    test_cmp expected.txt actual.txt &&
+    test "$(echo $(stg applied))" = "p1 p3" &&
+    test "$(echo $(stg unapplied))" = "p2"
+'
+
+test_expect_success 'Try to reset without --hard' '
+    ! stg reset master.stgit^~1 &&
+    stg status a > actual.txt &&
+    test_cmp expected.txt actual.txt &&
+    test "$(echo $(stg applied))" = "p1 p3" &&
+    test "$(echo $(stg unapplied))" = "p2"
+'
+
+cat > expected.txt <<EOF
+EOF
+test_expect_success 'Try to reset with --hard' '
+    stg reset --hard master.stgit^~1 &&
+    stg status a > actual.txt &&
+    test_cmp expected.txt actual.txt &&
+    test "$(echo $(stg applied))" = "p1" &&
+    test "$(echo $(stg unapplied))" = "p3 p2"
+'
+
+test_done
Previous: Karl HasselströmNext: Karl Hasselström
Message 26 of 32 in “Undo series”
  1. 00/14 Undo seriesKarl Hasselström, Jun 12, 2008
  2. 01/14 Fix typoKarl Hasselström, Jun 12, 2008
  3. 02/14 Library functions for tree and blob manipulationKarl Hasselström, Jun 12, 2008
  4. 03/14 Write to a stack log when stack is modifiedKarl Hasselström, Jun 12, 2008
  5. Catalin MarinasJun 17, 2008
  6. Karl HasselströmJun 17, 2008
  7. Karl HasselströmJun 17, 2008
  8. Catalin MarinasJun 17, 2008
  9. Karl HasselströmJun 17, 2008
  10. Catalin MarinasJun 18, 2008
  11. Karl HasselströmJun 18, 2008
  12. Catalin MarinasJun 18, 2008
  13. Karl HasselströmJun 18, 2008
  14. Catalin MarinasJun 19, 2008
  15. Karl HasselströmJun 19, 2008
  16. Catalin MarinasJun 20, 2008
  17. Karl HasselströmJun 23, 2008
  18. Catalin MarinasJul 12, 2008
  19. Karl HasselströmJul 14, 2008
  20. Karl HasselströmJul 1, 2008
  21. Catalin MarinasJul 3, 2008
  22. 04/14 Add utility function for reordering patchesKarl Hasselström, Jun 12, 2008
  23. 05/14 New command: stg resetKarl Hasselström, Jun 12, 2008
  24. 06/14 Log conflicts separatelyKarl Hasselström, Jun 12, 2008
  25. 07/14 Log conflicts separately for all commandsKarl Hasselström, Jun 12, 2008
  26. 08/14 Add a --hard flag to stg resetKarl Hasselström, Jun 12, 2008
  27. 09/14 Don't write a log entry if there were no changesKarl Hasselström, Jun 12, 2008
  28. 10/14 Move stack reset function to a shared locationKarl Hasselström, Jun 12, 2008
  29. 11/14 New command: stg undoKarl Hasselström, Jun 12, 2008
  30. 12/14 New command: stg redoKarl Hasselström, Jun 12, 2008
  31. 13/14 Log and undo external modificationsKarl Hasselström, Jun 12, 2008
  32. 14/14 Make "stg log" show stack log instead of patch logKarl Hasselström, Jun 12, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.