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

Re: [PATCH] git-add -p: be able to undo a given hunk

From
Jeff King <peff@peff.net>
Date
Jul 26, 2009, 15:39 UTC
Message-ID
<20090726153950.GA16780@sigill.intra.peff.net>
In-Reply-To
<20090725145237.GB18545@artemis.corp>
On Sat, Jul 25, 2009 at 04:52:37PM +0200, Pierre Habouzit wrote:
Show 16 quoted lines
> FWIW it's what I was doing so far, and it's not very efficient for many
> patterns, you talked about the bit where you want to keep some of the
> debug, for this one I used to do that:
> 
> while I have meaning full commits to do:
>     git add -p; commit;
> git add -p the things I want to trash and commit
> git stash
> git reset --hard HEAD~1
> git stash apply
> 
> That sucks.
> [...]
> For all those reasons I believe it's a good thing to be able to have
> something to remove hunks from the working-directory. Jeff's suggestions
> to move them to some stash is the best suggestion so far, and is safe.

Here's kind of a weird idea I've been considering. Feel free to write it off as insane ranting.

My two complaints about using stash for separating changes are:
  - it lacks the tool support for splitting changes that we have for
    making commits (like "add -p"), and it lacks the ability to build up
    a set of changes over multiple commands (like we can do for commits)
  - it works as a single destination. You stash and delete a change from
    the working tree, or you leave it. It's hard to say "there are 3
    different types of change here" and sort them all at once.

My idea is to instead have a general set of "registers" that contain states, each of which is basically an index. You can copy state from register to register, from working tree to register, or from register to register. You can also do any of those moves by looking at differences between two states and saying "move this change" (i.e., like what "add -p" does for the regular index).

So one way of splitting changes would be to say:
  1. Set registers 'a' and 'b' to the same state as HEAD
  2. Pick changes from the working tree to go to 'a'
  3. Pick changes from the working tree to go to 'b'
  4. Commit 'a' on top of HEAD
  5. Commit 'b' on top of new HEAD (and this would probably actually
     mean the changes from 'b' to the old HEAD, not setting the new HEAD
     state to what's in 'b').

So it's sort of a generalized form of the index, where you have N "index registers" and you sort your changes into them. And during steps 2 and 3, you could also make more changes, pick them out, etc.

The workflow you want maps into that pretty simply: you would sort your changes into "stuff you want to commit" and "stuff that is debugging cruft". And then you would just throw away the latter register (or use a special "trash" register).

And the workflow I described is "pick the changes for 'a', then for 'a'". But there's no reason you couldn't go through the changes, sorting each into "put this one into 'a', and this one into 'b'". Which is what you asked for.

Is this really that different from what you proposed? No, I don't really think so in terms of implementation, but it is really about a different mental model:

  1. You never delete things. You only copy or move them into registers.
  2. The interface should be the same whether you are moving between
     registers, or to/from the working tree.
  3. It extends naturally to multiple registers.
Anyway, just some stray thoughts. No code, so feel free to ignore. ;)
-Peff
Previous: Pierre HabouzitNext: Pierre Habouzit
Message 71 of 76 in “git-add -p: be able to undo a given hunk”
  1. git-add -p: be able to undo a given hunkPierre Habouzit, Jul 23, 2009
  2. Thomas RastJul 23, 2009
  3. Pierre HabouzitJul 23, 2009
  4. Implement unstage and reset modes for git-add--interactiveThomas Rast, Jul 24, 2009
  5. 1/3 Introduce git-unstageThomas Rast, Jul 24, 2009
  6. Bert WesargJul 24, 2009
  7. Bert WesargJul 24, 2009
  8. Elijah NewrenJul 24, 2009
  9. 2/3 Introduce git-discardThomas Rast, Jul 24, 2009
  10. Elijah NewrenJul 24, 2009
  11. Bert WesargJul 24, 2009
  12. Elijah NewrenJul 24, 2009
  13. Pierre HabouzitJul 25, 2009
  14. 3/3 Implement unstage --patch and discard --patchThomas Rast, Jul 24, 2009
  15. Matthias KestenholzJul 24, 2009
  16. Bert WesargJul 24, 2009
  17. Junio C HamanoJul 24, 2009
  18. Nanako ShiraishiJul 24, 2009
  19. Thomas RastJul 24, 2009
  20. Junio C HamanoJul 24, 2009
  21. 0/5 {checkout,reset,stash} --patchThomas Rast, Jul 25, 2009
  22. 1/5 git-apply--interactive: Refactor patch mode codeThomas Rast, Jul 25, 2009
  23. 2/5 builtin-add: refactor the meat of interactive_add()Thomas Rast, Jul 25, 2009
  24. 3/5 Implement 'git reset --patch'Thomas Rast, Jul 25, 2009
  25. 4/5 Implement 'git checkout --patch'Thomas Rast, Jul 25, 2009
  26. 5/5 Implement 'git stash save --patch'Thomas Rast, Jul 25, 2009
  27. Sverre RabbelierJul 26, 2009
  28. Thomas RastJul 26, 2009
  29. Thomas RastJul 27, 2009
  30. 0/5 {checkout,reset,stash} --patchThomas Rast, Jul 28, 2009
  31. 1/5 git-apply--interactive: Refactor patch mode codeThomas Rast, Jul 28, 2009
  32. 2/5 builtin-add: refactor the meat of interactive_add()Thomas Rast, Jul 28, 2009
  33. 3/5 Implement 'git reset --patch'Thomas Rast, Jul 28, 2009
  34. 4/5 Implement 'git checkout --patch'Thomas Rast, Jul 28, 2009
  35. 5/5 Implement 'git stash save --patch'Thomas Rast, Jul 28, 2009
  36. 6/5 DWIM 'git stash save -p' for 'git stash -p'Thomas Rast, Jul 28, 2009
  37. Jeff KingAug 9, 2009
  38. Thomas RastAug 9, 2009
  39. 0/5 Re: {checkout,reset,stash} --patchNicolas Sebrecht, Aug 9, 2009
  40. Thomas RastAug 9, 2009
  41. 0/5 Re: {checkout,reset,stash} --patchNicolas Sebrecht, Aug 9, 2009
  42. Thomas RastAug 9, 2009
  43. 0/5 Re: {checkout,reset,stash} --patchNicolas Sebrecht, Aug 9, 2009
  44. Thomas RastAug 10, 2009
  45. 0/6 {checkout,reset,stash} --patchThomas Rast, Aug 13, 2009
  46. 1/6 git-apply--interactive: Refactor patch mode codeThomas Rast, Aug 13, 2009
  47. 2/6 Add a small patch-mode testing libraryThomas Rast, Aug 13, 2009
  48. 3/6 builtin-add: refactor the meat of interactive_add()Thomas Rast, Aug 13, 2009
  49. 4/6 Implement 'git reset --patch'Thomas Rast, Aug 13, 2009
  50. 4/6 Implement 'git reset --patch'Thomas Rast, Aug 15, 2009
  51. 5/6 Implement 'git checkout --patch'Thomas Rast, Aug 13, 2009
  52. 5/6 Implement 'git checkout --patch'Thomas Rast, Aug 15, 2009
  53. 6/6 Implement 'git stash save --patch'Thomas Rast, Aug 13, 2009
  54. 7/6 DWIM 'git stash save -p' for 'git stash -p'Thomas Rast, Aug 13, 2009
  55. 0/6 Re: {checkout,reset,stash} --patchNicolas Sebrecht, Aug 14, 2009
  56. Jeff KingAug 15, 2009
  57. Junio C HamanoAug 15, 2009
  58. Thomas RastAug 15, 2009
  59. Thomas RastAug 15, 2009
  60. Jeff KingAug 18, 2009
  61. Thomas RastAug 19, 2009
  62. Jeff KingAug 19, 2009
  63. Junio C HamanoJul 23, 2009
  64. Nanako ShiraishiJul 24, 2009
  65. Junio C HamanoJul 24, 2009
  66. Jeff KingJul 24, 2009
  67. Junio C HamanoJul 25, 2009
  68. Thomas RastJul 25, 2009
  69. Pierre HabouzitJul 25, 2009
  70. Pierre HabouzitJul 25, 2009
  71. Jeff KingJul 26, 2009
  72. Pierre HabouzitJul 27, 2009
  73. Jeff KingJul 27, 2009
  74. Thomas RastJul 27, 2009
  75. Jeff KingJul 27, 2009
  76. Pierre HabouzitJul 24, 2009

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.