The main problem I have with the staging area is that it amounts to being something that's like a commit except for, you know, not actually being a commit, and therefore things that normally work on commits don't necessarily work on the staging area.
A better fix would be to make the staging area an actual commit, and then reframe everything as easy ways to edit the latest commit. (This meshes well with adding features like Mercurial's phases or changeset evolution that make commit editing somewhat safer).
A "draft commit" (I really like that name!) is not a commit, and should not be handled as such. This would make this feature more or less useless.
The whole point of the "draft commit" is that you can easily see changes against your (uncommited!) changes. That helps to build up a commit step by step.
Committing WIP stuff (and maybe even pushing that) makes the history useless. Branches don't help as you end up with millions of WIP branches that are all incompatible to each other (and the evolution that happened elsewhere). Only keeping WIP branches up to date is a full time job than.
Git has already a means to edit the latest commit easily: `git commit --amend`.
> The whole point of the "draft commit" is that you can easily see changes against your (uncommited!) changes. That helps to build up a commit step by step.
> Committing WIP stuff (and maybe even pushing that) makes the history useless.
Here's the thing. I'm a very big proponent of keeping history clean, and making sure that commits are atomic, and exorcising any "typo fixes" or the like commits from history. Not once have I found the concept of a staging area useful. Features like `git commit --amend` or `git add -i` are incredibly useful [1]. But not the staging area itself--it's only a thing that screws me up if I forget to add `-a` to `git commit`.
"Draft commit" also I think elucidates the other problem. You see, drafts of regular documents are frequently shared with other people, multiple versions of them created and shared, etc. Drafts don't become final until it's actually published--and there is utility in being able to track the differences in drafts as they are discussed. If you've got a "draft commit", then it should be able to go through this process--this is basically the process of code review.
Of course, we're already working with a VCS, which is designed to handle different versions of code, so... what if we made the "version history" of commits just... regular commits? Sure, shade them a different color, so you know that a commit is a draft, and you can tell which of the commit's parents [2] is the previous version. And knowing that a commit is a draft, when it actually gets pushed into the trunk, you can commit only that final commit and not include any of the previous history. Since the commits are using the same DAG logic under the head, questions like "what changed between version 2 and 5?" become just regular diff commands [3].
By the way, this system already exists. It's known as changeset evolution in Mercurial, and it appears that Sapling here has adopted it. My workflow in git tries to emulate this model to a degree, but the approach of having branches-based-on-branches doesn't mesh well with how git wants to do things.
[1] The number of times I have painstakingly sorted out which changes go into the commit with `git add -i` onto to immediately and accidentally undo them with a `git commit -a` is quite high. And because the staging area isn't an actual commit, it can't be recovered by digging into the reflog like actual commits can.
[2] If you amend or otherwise modify a commit, it has one parent, which is the previous version; if you rebase a commit, it has two parents, one of them the new commit it's based on and the other is the previous version.
[3] Worth noting that this question often turns out to be difficult to answer with most code review systems. Building a model of "commit history" into your VCS makes it come out for free!
A better fix would be to make the staging area an actual commit, and then reframe everything as easy ways to edit the latest commit. (This meshes well with adding features like Mercurial's phases or changeset evolution that make commit editing somewhat safer).