Subject: Re: Command-line interface thoughts

From: Jonathan Nieder <[email-masked]>
Date: Tue, 7 Jun 2011 06:45:26 -0500

Hi,

Michael J Gruber wrote:

> I'm actually wondering whether there is any agreement on the sheer fact
> that there is a problem in the ui, namely having too many different
> commands or options (reset/commit/add/checkout resp. diff invocations;
> I've described that already) for different aspects of a "similar"
> concept (cp content version from A to B resp. diff it).

I agree that there is a problem --- a difficult learning curve that
means for example it took a year or so before I was used to the "git
diff describes the changes you are preparing" mnemonic for the various
0- and 1-tree git diff forms --- but I do not agree with your specific
characterization of it.  If there are too many ways to spell
operations of a certain class then we should be looking to deprecate
some of them, and that is a direction I do not think would be very
fruitful.

So I'd prefer to focus on actual UI bugs, of the form, "A reasonable
person tried this command, expecting this effect, and got some other
effect instead" or "A reasonable person was searching for a command
with this effect and the only solutions she came up with were
convoluted".

Example:

Long ago, I remember wanting to see what unstaged changes were in
the worktree --- that is, I wanted to compare the content of the
index to the worktree.  So, tell "git diff" to look at the index:

	git diff --cached

No, I should have used "git diff" and the model of "git diff" I had
was completely wrong.  How can we avoid this confusion?

One answer would be to adapt "git diff" to match a familiar model,
that of the ordinary "diff" command.  "diff" takes two arguments,
preimage and postimage, so that would be:

	git diff INDEX WORKTREE

If there were an unmerged path in the index, this would do a
three-way diff, just like "git diff" currently does.

That all sounds great, but I do not find it completely satisfactory.
One problem is that if this is the mental model people have of
"git diff", the three-way diff for a multiple stages, behavior of
"git diff <paths>", and so on, however they are spelled, will look
completely mystifying.  From the point of view of "this command
explains the changes in the worktree" they make sense, while from the
point of view of "compare A to B" they don't make much sense at all.
So this change just defers the learning process.

I think part of the problem in the current UI is that the
documentation never spells out the idea of what plain "git diff" is
for.  Worse, "--cached means to look to the index in place of the
worktree" doesn't seem to be spelled out anywhere except gitcli(7).  I
am not sure it is worth the headache of spelling the latter out
instead of changing the UI to be easier to explain.

Something like "git diff --index-only" would at least set people
thinking in the right direction --- "index only as opposed to what?".

With an INDEX pseudo-tree,

	git diff INDEX

is a synonym for "git diff", and to do "git diff --cached" one would
have to write

	git diff HEAD INDEX

I like the "rename --cached to --index-only" proposal more but am
not too satisfied with it, either.  In a way it is tempting to teach
people

	git diff-files -p;	# compare worktree to index
	git diff-index -p HEAD;	# compare worktree to HEAD
	git diff-index -p --cached HEAD;	# compare index to HEAD
	git diff-tree -p HEAD HEAD^;	# compare HEAD^ to HEAD

I wish there were some other alternative that can be learned more
gracefully.

Sorry for the longwinded, meandering message.  Still, I hope it
clarifies a little.

Jonathan