I am guilty of introducing "add --interactive" and am somewhat regretting it. Why? Because it encourages a wrong workflow, but the word "wrong" needs to be clarified. The workflow assumed by "add --interactive" (hence by its wrapper, "commit --interactive") goes like this: 1. You have some large task. You start hacking and keep hacking and hacking. 2. Your working tree might still be a messy state, but there are some good bits in the mess that are worth committing on their own, excluding the other changes in the working tree. This could happen for a number of reasons: - You might be actually done with the change and your working tree is perfect, but the change since the HEAD commit is too big to be a single logical change. You want to split the changes into smaller steps. - You might be still in the middle of what you initially wanted to achieve, but at the same time you found something worth changing, which is independently useful regardless of what you are doing. It may be a typo. It may be a bug that might or might not affect what you are doing. But as long as you found it and fixed it, you would want to make a separate commit. 3. So you would fire up "add --interactive", and isolate the "good bits" by updating the index selectively to prepare for commit. You would run "diff --cached" to review the change you are going to commit makes sense, and then finally make a commit. I am not saying the first two steps are wrong. Everybody does that all the time. What's wrong is the approach "add --interactive" takes in the last step. The isolation of "good bits" happens in the index, not in the working tree --- which is largely because git is designed to commit the state recorded in the index --- but that encourages the user to commit something that has never been in the working tree, so by definition what is committed in step 3 never could have been even tested. And that is what I feel is very wrong. People in the past claimed that they later would go back to each individual commit and test them, but that is simply hard to believe, because it is tedious in practice. We should be able to do better than that. Instead of the step 3 in the above, we could have a way to quickly stash the working tree state, reset the working tree to that of the last commit (or whatever commit we want to build a new commit on top of), and selectively apply parts of the the changes we stashed to the working tree. Then we can test the state in the working tree, and run "commit -a" as usual. What's still left in the stashed state can incrementally be trickled in to make further commits. Probably the operation would go like this. I'll describe them in terms of lower level operations, and leave the scripting to others. * Stashing the current state git commit -a -m 'stashed' git tag -f stash git reset --hard HEAD^ After this point, "diff stash^ stash" is the changes yet to be applied. * Switch to the commit you want to apply part of what was stashed to. This part is optional if you are only building on top of the current HEAD, but if you have a small but urgent bugfix you might want to switch to another branch (say, 'maint'). There is no magic command needed -- just run git checkout maint as usual, for example. * Trickle some of the stashed changes in, perhaps interactively: git pick stash would probably give an interactive UI similar to "add -i" to let you pick and choose from "git show stash" (either per-hunk or per-path), but unlike "add -i", which applies the chosen change only to the index, it applies the change to the working tree and to the index. As the last step of its operation, "git pick" would save the resulting index state as a tree: git tag -f pre-fixup `git-write-tree` * Review and test the change in the working tree. This does not need any special command. You may also make fix-up in the working tree as usual. Then you would make a commit, perhaps using the usual "git commit". * Then this is the tricky and interesting part. We need to subtract the change we already used to advance HEAD from "stashed changes". I do not think we currently have a single command to do this step, but it would probably go like this. 1. First, we build a tree that is stash^ plus the changes we committed right now. git read-tree -m -u stash^ git merge-recursive HEAD^ -- stash^ HEAD NEW_TREE=`git write-tree` NEW_BASE=`echo stash | git commit-tree $NEW_TREE` This would make our working tree and the index match the state you would have had, had you started from the original state and made only the changes you have committed just now. Note that the resulting tree contains the manual fix-ups you made since pre-fixup. 2. The tree state you would eventually want to have used to be in stash but that lacks the manual fix-up you made, which is the difference between pre-fixup and HEAD. So let's update the final state with this difference: git read-tree -m -u stash git merge-recursive pre-fixup -- stash HEAD NEW_TREE=`git write-tree` 3. The strategy is to keep stash pointed at a commit that has the tree state of what you eventually would want to have (which is now in $NEW_TREE), and represent the changes yet to be applied as "diff stash^ stash". So let's update the stash tag: NEW_STASH=`echo stash | git commit-tree $NEW_TREE -p $NEW_BASE` git tag -f stash $NEW_STASH * You just finished one step, and still have remainder that can be seen from "git show stash". Go back to "Switch to the commit" step (or "Trickle some of the stashed changes" step) above and repeat. The output from "git show stash" will keep shrinking, and when it becomes empty you are done. - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html