Subject: Re: Two ideas for improving git's user interface

From: Carl Worth <[email-masked]>
Date: Fri, 03 Feb 2006 15:57:44 -0800

[I'm still hesitant to be jumping into this discussion with both feet
like this, so please imagine lots of disclaimers of ignorance before
any claims I make---I would not be surprised or offended to learn I'm
wildly wrong about how I think some things work.]

On Wed, 01 Feb 2006 18:25:46 -0800, Junio C Hamano wrote:
> Carl Worth <[email-masked]> writes:
> 
> > If not, we should be able to simplify things since a lot of the
> > UI complexity being discussed (-a vs. no -a, path names vs. no path
> > names), hinges on the handling of skewed files.
> 
> I am in agreement with you that "skewed files" might lead to
> confusion, but I do not see how that relates to "-a vs no -a" nor
> "path names vs no path names" issues.

In the case of skewed files, "-a" commits the current file content,
while "no -a" commits the skewed content. Similarly, "path names"
commits the current contents while "no path names" commits the skewed
content.

> Let's say we try to detect and forbid committing skewed files.  How
> would we do that?

I wasn't imagining adding extra checks (== more complexity). Instead I
was imagining something like a command that would mark a path to be
committed. I don't yet have a good suggestion for a short name for the
operation, but I'll call it "mark" for sake of discussion. This mark
operation would be used similarly to update-index but instead of
storing into the index an object created from the current contents of
the specified path, it would simply mark the path in the index as
to-be-committed. When committing such a path later, the object would
be created based on the contents of the path at that time.

So I imagined eliminating skewed files first by providing operations
based around "mark" rather than update-index, (since "mark" avoids all
of the confusing oops-I-committed-stale-file-contents scenarios), and
second by making all commands that update the index from the object DB
also update the working directory, (effectively making git-read-tree
always act according to its current -u).

But as a prerequisite, this kind of plan would require the user to
never actually _want_ to stash skewed contents in the index. On a
separate branch of the current thread, Linus has said he likes to do
that, so I'll continue to discuss that there, and before the outcome
of that discussion, this idea need not even be considered further.

> 1. "git commit" is the traditional one; it commits the current index.
> 
> 2. "git commit --also fileA..." updates fileA... on top of the current
> 
> 3. "git commit fileA..." initializes a temporary index from the
> 
> 4. "git commit -a" by definition would not have skewed files and there
>    is nothing to check.

The one comment I have about this proposal is a certain lack of
orthogonality. Namely the base "commit" performs one operation,
(committing the contents of the index), and "commit --also" performs
that same operation plus something more (that much is good so
far). The problem starts with "commit file" which does not perform the
base operation at all, but just does something different. Similarly,
"commit -a" is also doing something different, (its behavior can be
described as an additional step performed _before_ the base "commit"
but could also be described as an operation independent of the
original state of the index, if I'm not mistaken).

Before "-a" existed, there was better orthogonality, but apparently
there wasn't a good fit with what some users wanted to do, (hence the
addition of "-a" and the recent proposal of yet more variations on
"commit").

>         $ git diff --cached
>         $ git commit
...
>         $ git diff HEAD
>         $ git commit -a
...
> For that you may need to do something like:
> 
> 	git-diff-index --cached HEAD ;# already in index but do not look at A
>         git-diff-index HEAD -- A ;# and path A is taken from working tree
> 
> which is a bit cumbersome.
> 
> Without --also (the new semantics), the check would be
> straightforward:
..
>  +++++  $ git diff HEAD -- A
> 	$ git commit A

Thanks for the examples. If nothing else, I hope the above makes clear
that it's not always obvious how to achieve a preview diff of a
commit. I would love to see the number of fundamental variations of
"commit" shrink rather than grow, but especially if it does grow, I
think it will always be important for users to be able to easily view
"status" and "diff" previews of commits, (preferably by providing the
same arguments to some 'preview' commands as will be passed to
commit).

-Carl