[prev in list] [next in list] [prev in thread] [next in thread] 

List:       git
Subject:    Re: [PATCH] git-add -p: be able to undo a given hunk
From:       Jeff King <peff () peff ! net>
Date:       2009-07-26 15:39:50
Message-ID: 20090726153950.GA16780 () sigill ! intra ! peff ! net
[Download RAW message or body]

On Sat, Jul 25, 2009 at 04:52:37PM +0200, Pierre Habouzit wrote:

> 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
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic