Re: Command-line interface thoughts

37 messages, 12 authors, 2016-06-15 · open the first message on its own page

Re: Command-line interface thoughts

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:51:25

Michael J Gruber [off-list ref] writes:
quoted
That is why I asked what the user experience of "git show NEXT" as opposed
to "git show INDEX" should look like. So what should it look like during a
"pull" that did not finish?
If NEXT is to mean the result of a commit in the current state, and the
current state would or should not allow a commit, then trying to access
that pseudo-commit should error out with a helpful message.
What "helpful message"? I asked for the user experience, not handwaving.

Do you mean to say that the error message would teach the user that the
current state is not something you can create a commit? What message would
that give the end user?  I am hoping the following is not what will happen:

  Q. I tried "git show NEXT" because I wanted to see what the next commit
     would look like, but I got an error, saying NEXT is not known as I
     haven't resolved a conflict.

  A. Yes, the message is correct.

  Q. But then how can I see what the next commit would look like?

  A. You would say "git diff HEAD NEXT".

  Q. Ah, that is the same as I always do before making a commit to see what
     I have added so far look sane. Thanks.

     ...after 2 minutes...

  Q. Sorry, it does not work. I get the same error, that says NEXT is not
     known yet.

  A. Ok, you would say "git diff HEAD" the old fashioned way. The person
     who thought NEXT would be useful didn't think things through.

  Q. Now I am seeing a diff between the conflicted state and the previous
     commit, I think I can get to where I want to go from here. Thanks.

Another option is to make NEXT/INDEX mean a tree (:0:). I have not
thought this through (and have not made a suggestion, accordingly) but I
do see a problem in the UI. (I don't think we need to change the
existing ui in that respect but can amend and improve it.)

Anyway, it's rc phase :)
Rc or not rc, just repeating a fuzzy and uncooked "idea" around phoney
ref-looking names that will end up confusing the users, and selling that
as if it is a logical conclusion to "we want to give an easier to
understand UI", without presenting a solid user experience design that is
convincing enough that the "idea" will reduce confusion will not get us
anywhere, especially when it is sprinkled with ad hominem attack at me.

Re: Command-line interface thoughts

From: Scott Chacon <hidden>
Date: 2016-06-15 22:51:25

Hey,

On Mon, Jun 6, 2011 at 9:14 AM, Junio C Hamano [off-list ref] wrote:
Michael J Gruber [off-list ref] writes:
quoted
quoted
That is why I asked what the user experience of "git show NEXT" as opposed
to "git show INDEX" should look like. So what should it look like during a
"pull" that did not finish?
If NEXT is to mean the result of a commit in the current state, and the
current state would or should not allow a commit, then trying to access
that pseudo-commit should error out with a helpful message.
What "helpful message"? I asked for the user experience, not handwaving.

Do you mean to say that the error message would teach the user that the
current state is not something you can create a commit? What message would
that give the end user?  I am hoping the following is not what will happen:

 Q. I tried "git show NEXT" because I wanted to see what the next commit
    would look like, but I got an error, saying NEXT is not known as I
    haven't resolved a conflict.

 A. Yes, the message is correct.
I'm not sure why this wouldn't just list out the index tree, having
some message for entries that have more than one stage.  Like a
porcelain-ized version of 'git ls-files --stage', maybe in this case
with a warning at the bottom that a subsequent commit command will not
complete.  Even something similar to what would happen if you ran
'commit' right then:

  fatal: 'commit' will not be possible because you have unmerged files.
 Q. But then how can I see what the next commit would look like?

 A. You would say "git diff HEAD NEXT".

 Q. Ah, that is the same as I always do before making a commit to see what
    I have added so far look sane. Thanks.
Why would this look sane? I would think this would say "* Unmerged
path <file>" just like 'diff --cached would do.
    ...after 2 minutes...

 Q. Sorry, it does not work. I get the same error, that says NEXT is not
    known yet.

 A. Ok, you would say "git diff HEAD" the old fashioned way. The person
    who thought NEXT would be useful didn't think things through.
I think the point would be that "git diff HEAD WTREE" would give you
this same output and if you had the basic concept of these three
important areas of Git that you could be explicit about what you
wanted to see or compare rather than having to look up the specific
special case that will show you what you want. Consider these very
common scenarios from a new user perspective: you want to see what is
changed in your working tree but not added yet, you want to see what
is added but not committed, you want to see the sum total of all
changes since your last commit and you want to see what the index
currently looks like.

Here are the commands currently:

a) diff
b) diff --cached
c) diff HEAD
d) ls-files --stage

Here would be the commands with the proposed pseudo-trees.

a) diff NEXT WTREE
b) diff HEAD NEXT
c) diff HEAD WTREE
d) show NEXT

It seems to me to be more guessable and straightforward for new users.
 But, yes, I assume there would be some difficulty in supporting it
everywhere.
 Q. Now I am seeing a diff between the conflicted state and the previous
    commit, I think I can get to where I want to go from here. Thanks.

quoted
Another option is to make NEXT/INDEX mean a tree (:0:). I have not
thought this through (and have not made a suggestion, accordingly) but I
do see a problem in the UI. (I don't think we need to change the
existing ui in that respect but can amend and improve it.)

Anyway, it's rc phase :)
Rc or not rc, just repeating a fuzzy and uncooked "idea" around phoney
ref-looking names that will end up confusing the users, and selling that
as if it is a logical conclusion to "we want to give an easier to
understand UI", without presenting a solid user experience design that is
convincing enough that the "idea" will reduce confusion will not get us
anywhere, especially when it is sprinkled with ad hominem attack at me.
I think I'm the only one that mentioned your name so I apologize if
you saw that as an attack.  I was not saying you are unreasonable in
not changing the UI all the time, or that you are unreasonable for not
liking the NEXT/WTREE - there are certainly cases I'm not considering.
(For example, I'm more concerned about things like 'git commit-tree
NEXT' or 'git rev-parse NEXT' if the index is in a weird state - it
obviously has to be special-cased and I would assume only usable at
the porcelain level, possibly only by 'diff', 'show' and 'grep'. It's
the implementation I'm mainly worried about, I feel that the UI would
be pretty straightforward in all these cases.)

Re: the ad-hominim stuff, I was simply remarking that the
'reset'/'checkout' debate has been had several times and there is
precedent for it being a non-starter.  I also see and understand the
argument from you and Linus about that, I just happen to disagree with
it. It was not meant to be an attack.

Scott

Re: Command-line interface thoughts

From: Michael J Gruber <hidden>
Date: 2016-06-15 22:51:25

Junio C Hamano venit, vidit, dixit 06.06.2011 18:14:
Michael J Gruber [off-list ref] writes:
quoted
quoted
That is why I asked what the user experience of "git show NEXT" as opposed
to "git show INDEX" should look like. So what should it look like during a
"pull" that did not finish?
If NEXT is to mean the result of a commit in the current state, and the
current state would or should not allow a commit, then trying to access
that pseudo-commit should error out with a helpful message.
What "helpful message"? I asked for the user experience, not handwaving.
I specified the exit behaviour, that is no handwaving.

[...]
quoted
Another option is to make NEXT/INDEX mean a tree (:0:). I have not
thought this through (and have not made a suggestion, accordingly) but I
do see a problem in the UI. (I don't think we need to change the
existing ui in that respect but can amend and improve it.)

Anyway, it's rc phase :)
Rc or not rc,
I spend my limited git time running builds and tests for master on
several systems these days (and following changed build environments
there which I can't control).
just repeating a fuzzy and uncooked "idea" around phoney
ref-looking names that will end up confusing the users, and selling that
as if it is a logical conclusion to "we want to give an easier to
understand UI", without presenting a solid user experience design that is
convincing enough that the "idea" will reduce confusion will not get us
anywhere, especially when it is sprinkled with ad hominem attack at me.
I've re-read all my posts in this thread and have no idea what you're
referring to here. If I were more sensitive I could spot attacks at
myself in the above, though. Just count your usage of terms like
"phoney", "fuzzy" etc. directed at other people's ideas and arguments.

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).

If we don't agree that there's a problem then there's no point
discussing solutions (or ideas/brainstorms thereof).

Michael

Re: Command-line interface thoughts

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:51:25

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

Re: Command-line interface thoughts

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:51:25

Holger Hellmuth wrote:
If someone finds the three-way diff completely mystifiying, how do
you expect him to resolve a merge conflict at all? Or recognize that
there is one? Or find the command to use after editing out the
conflict markers?

A novice user will have no real mental model anyway.
Yes, I think you're getting closer to the point I was trying to make.
A novice will have a naive mental model, and a good user interface
needs to be close to it but not too close.  Close because the UI must
be intuitive on its own.  Not too close because a good UI will help in
leading such a person to productive ways of thinking and working, by
making common tasks convenient.

So much for generalities.

Re: Command-line interface thoughts

From: Holger Hellmuth <hidden>
Date: 2016-06-15 22:51:25

On 07.06.2011 13:45, Jonathan Nieder wrote:
[...]
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.
If someone finds the three-way diff completely mystifiying, how do you 
expect him to resolve a merge conflict at all? Or recognize that there 
is one? Or find the command to use after editing out the conflict markers?

A novice user will have no real mental model anyway. He will be looking 
for simple (and easy to remember) commands for (mostly) simple needs.
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
if you look at the comments you put behind the commands, they look very 
much like the proposed diff command. How much time would a novice (and 
everyone else) need to remember your comments compared to your commands? 
A lot less.

Holger.

Re: Command-line interface thoughts

From: René Scharfe <hidden>
Date: 2016-06-15 22:51:25

Am 07.06.2011 13:45, schrieb Jonathan Nieder:
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?
Would it help if a header was shown in this case, describing the
following diff, e.g. something like this:

	$ cd /tmp && mkdir repo && cd repo && git init
	Initialized empty Git repository in /tmp/repo/.git/
	$ echo a >a && git add a && git commit -m.
	[master (root-commit) faeefb5] .
	 1 files changed, 1 insertions(+), 0 deletions(-)
	 create mode 100644 a
	$ echo b >a
	$ git diff
	Let's get rrready to diiiiff!!
	In corner a: the INDEX!  And in corner b: the WORKTREE!

	diff --git a/a b/a
	index 7898192..6178079 100644
	--- a/a
	+++ b/a
	@@ -1 +1 @@
	-a
	+b

Such a prefix would be ignored by patch etc..  You would still get it
wrong at the first try but now you'd get immediate feedback on what you
actually compared, without having to read the manpage.

René

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:25

René Scharfe wrote:
Would it help if a header was shown in this case, describing the
following diff, e.g. something like this:

	$ cd /tmp && mkdir repo && cd repo && git init
	Initialized empty Git repository in /tmp/repo/.git/
	$ echo a >a && git add a && git commit -m.
	[master (root-commit) faeefb5] .
	 1 files changed, 1 insertions(+), 0 deletions(-)
	 create mode 100644 a
	$ echo b >a
	$ git diff
	Let's get rrready to diiiiff!!
	In corner a: the INDEX!  And in corner b: the WORKTREE!

	diff --git a/a b/a
	index 7898192..6178079 100644
	--- a/a
	+++ b/a
	@@ -1 +1 @@
	-a
	+b

Such a prefix would be ignored by patch etc..  You would still get it
wrong at the first try but now you'd get immediate feedback on what you
actually compared, without having to read the manpage.
We have `diff.mnemonicprefix`, though it is not header... and is not set
by default ;-)

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:26

On Tue, 7 June 2011, Jonathan Nieder wrote:
Holger Hellmuth wrote:
quoted
If someone finds the three-way diff completely mystifiying, how do
you expect him to resolve a merge conflict at all? Or recognize that
there is one? Or find the command to use after editing out the
conflict markers?

A novice user will have no real mental model anyway.
Yes, I think you're getting closer to the point I was trying to make.
A novice will have a naive mental model, and a good user interface
needs to be close to it but not too close.  Close because the UI must
be intuitive on its own.  Not too close because a good UI will help in
leading such a person to productive ways of thinking and working, by
making common tasks convenient.

So much for generalities.
To reiterate; perhaps it is not stated clearly in documentation:

1. "git diff" is about examining _your_ changes.  This short form is the
   same in every SCM.

   Because of explicit index (cache, staging area) one needs to know if
   it is working area against index, or working area against HEAD. 
   Thinking about merge conflict case helps to remember; in such case
   you want your changes against partially resolved merge.

   Also advanced users can use index to hide fully cooked changes from
   having to browse during review.

   Novice users which do not use index (and use "git commit -a") would
   never notice the difference, if not for the complication of newly
   added files: in other SCM you would see on "<scm> diff" creation
   diff (well, there is "git add -N").  Same with removal if one uses
   "git rm" and not simply "rm".

2. "git diff --cached" is about cached (staged) changes, therefore
   it is index against HEAD.

3. "git diff <commit>" in general, and "git diff HEAD" in particular,
   is about your changes (worktree), compared to given commit.

At in no place I _have_ to explain what is compared with what to explain 
when and what for to use "git diff", "git diff --cached" and "git diff 
HEAD".

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts (ad-hominem attacks)

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:26

On Tue, 7 June 2011, Michael J Gruber wrote:
Junio C Hamano venit, vidit, dixit 06.06.2011 18:14:
 
quoted
just repeating a fuzzy and uncooked "idea" around phoney
ref-looking names that will end up confusing the users, and selling that
as if it is a logical conclusion to "we want to give an easier to
understand UI", without presenting a solid user experience design that is
convincing enough that the "idea" will reduce confusion will not get us
anywhere, especially when it is sprinkled with ad hominem attack at me.
I've re-read all my posts in this thread and have no idea what you're
referring to here.
I think one can see __ad hominem__ attack in *implication* that the idea
got shot down because of Junio (and Linus) _personal_ resistance to
fresh ideas.  And that is Junio stubborness than stand in the way of
new ideas.  Certainly somebody more sensitive might read it as such.
If I were more sensitive I could spot attacks at 
myself in the above, though. Just count your usage of terms like
"phoney", "fuzzy" etc. directed at other people's ideas and arguments.
Those "attacks" are at ideas and arguments, not at people.
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).

If we don't agree that there's a problem then there's no point
discussing solutions (or ideas/brainstorms thereof).
Well, some of current overloading might be leftover result of "git is too
complicated, see how many commands it have [in $PATH]" criticism of git
and comparison with other (D)VCS... and in reducing number of commands
the pendulum perhaps went too far in opposite direction.

I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason, see my other response in this
thread:

  http://thread.gmane.org/gmane.comp.version-control.git/175061/focus=175265

and that the pseudo-almost-ref notation it would require for each such
pseudo-ref considering many corner cases:

  git diff <pseudo-ref-A> <pseudo-ref-B>
  git diff <commit or tree> <pseudo-ref>
  git diff <pseudo-ref>
  git show <pseudo-ref>

in normal and in conflicted case.


I am also not sure if replacing "context-sensitive" git-checkout behavior
by "git revert-file" (or rather "git revert-path", as you can use pathspec,
c.f. "git checkout ."), is something to consider without rock-solid UI
design and a very good name.  True, context dependent grammars are harder
than context-free grammars, but people do understand context, don't they?

Anyway, if one does not remember "git checkout -- <file>", one can always
use obvious alternative, namely "git show :./<file> > <file>"...


BUT I quite like "git unadd" (and/or "git unstage") idea.  

It is not obvious that "git reset" can be used for files, and it requires
bit of analysis that it resets index from HEAD: 
1. "git reset [<options>]" always resets from commit (defaults to HEAD),
2. "git reset" == "git reset --mixed" modifies current branch and index
   (HEAD -> index -> worktree progression of --soft -> --mixed -> --hard
   et al.),
3. modifying branch tip doesn't make sense for checking out file, so
4. "git reset -- <file>" must set index version of file from HEAD.

Truth to be told I really just follow what "git status" tells me ;-)

Though I am always wondering why there isn't "git reset --hard <file>"
to mean the same as "git checkout HEAD <file>".

So +1 from me for "git unadd [<commit>] [--] <path>..." (and "git unstage")
to do _exactly the same_ as "git reset [<commit>] [--] <path>...".

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts (ad-hominem attacks)

From: Michael Nahas <hidden>
Date: 2016-06-15 22:51:26

On Wed, Jun 8, 2011 at 7:12 AM, Jakub Narebski [off-list ref] wrote:
I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason,
To be clear, I'm not advocating and have never advocated getting rid
of zero-argument "git diff".  I've advocated that every (whole
project) diff command should be expressible by a "git diff TREE1
TREE2".  I'm fine with defaults if one or zero trees are specified.
So "git diff" would default to "git diff NEXT WTREE".

It is not obvious that "git reset" can be used for files, and it requires
bit of analysis that it resets index from HEAD:
...
4. "git reset -- <file>" must set index version of file from HEAD.

Truth to be told I really just follow what "git status" tells me ;-)
I love those messages but if a user is relying on just copying a
warning message, then they are learning anything.  They're parroting.
I believe a user interface should have concepts and commands that make
sense, so that user will learn them and be able to apply them in other
areas.
--
Jakub Narebski
Poland

Re: Command-line interface thoughts (ad-hominem attacks)

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:26

On Wed, Jun 8, 2011, Michael Nahas wrote:
On Wed, Jun 8, 2011 at 7:12 AM, Jakub Narebski [off-list ref] wrote:
quoted
I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason,
To be clear, I'm not advocating and have never advocated getting rid
of zero-argument "git diff".  I've advocated that every (whole
project) diff command should be expressible by a "git diff TREE1
TREE2".  I'm fine with defaults if one or zero trees are specified.
Those pseudo-almost-refs (almost-tree-ish) are to help new users, isn't it?
But shouldn't new user learn that he/she should use "git diff" to review
his changes, rather than use "git diff NEXT WTREE" to compare staged
contents with working area?
So "git diff" would default to "git diff NEXT WTREE".
You mean that "git diff NEXT WTREE" output be the same as "git diff",
except for corner cases (merge conflict), isn't it?

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Holger Hellmuth <hidden>
Date: 2016-06-15 22:51:26

On 07.06.2011 22:33, Jakub Narebski wrote:
To reiterate; perhaps it is not stated clearly in documentation:
 >
1. "git diff" is about examining _your_ changes.  This short form is the
    same in every SCM.
you are right, more explicit mention in the docs would help about this.

But other SCMs don't have the additional target 'index'. Much easier to 
reason there. Also, wouldn't Joe User then conclude that 'git diff' must 
be comparing working area against HEAD ?
    Because of explicit index (cache, staging area) one needs to know if
    it is working area against index, or working area against HEAD.
    Thinking about merge conflict case helps to remember; in such case
    you want your changes against partially resolved merge.
This is far from a straightforward reasoning that would pop up in 
anyones mind. In truth, I can't follow that reasoning even now. In case 
of a merge conflict the working area doesn't concern me at all, I would 
want a diff between 'ours' and 'theirs'

Since perl has been brought up as example of this DWIM philosophy: In 
perl commands have their defaults, but you always can specify exactly 
what you want if you are not sure or want to make it explicit. You can 
use 'chomp' or you can use 'chomp $_'. But I can't make it explicit 
which two targets I want to compare with 'git diff'.
    Also advanced users can use index to hide fully cooked changes from
    having to browse during review.

    Novice users which do not use index (and use "git commit -a") would
    never notice the difference, if not for the complication of newly
    added files: in other SCM you would see on "<scm>  diff" creation
    diff (well, there is "git add -N").  Same with removal if one uses
    "git rm" and not simply "rm".
2. "git diff --cached" is about cached (staged) changes, therefore
    it is index against HEAD.
We use three words to talk about the index: cache, stage, index. So 
apart from having an additional target for diff that target also is 
diffused by three words. Sure, index is the real designation and cached 
and staged are used as verbs, but that is just one more confusing bit. 
Also 'cache' in computer science is a transparent buffer to access data 
faster (wikipedia definition). Not what I would think of the index.

Probably there are good reasons to not use "git diff --index" and 
probably they have been discussed a few times, but it doesn't make using 
diff easier. But that's a side issue.

If someone sees 'git diff --cached' he might know one target, the index. 
But how does he get the other? By reasoning that 'git diff' alone is 
already index against working area? But for that he would have first to 
conclude that 'git diff' is not working area against HEAD (as it is in 
other SCMs), see above.
3. "git diff<commit>" in general, and "git diff HEAD" in particular,
    is about your changes (worktree), compared to given commit.

At in no place I _have_ to explain what is compared with what to explain
when and what for to use "git diff", "git diff --cached" and "git diff
HEAD".
I'm sure every part of the user interface of gimp can be rationalized in 
the same way by someone deeply involved in the concepts and the 
structure of gimp, but still it is perceived as difficult by nearly 
everyone else. You look at it from inside and it looks logical. Others 
just don't have all the pieces to make that reasoning really work.

Holger.

Re: Command-line interface thoughts (ad-hominem attacks)

From: Michael Nahas <hidden>
Date: 2016-06-15 22:51:26

On Wed, Jun 8, 2011 at 8:42 AM, Jakub Narebski [off-list ref] wrote:
On Wed, Jun 8, 2011, Michael Nahas wrote:
quoted
On Wed, Jun 8, 2011 at 7:12 AM, Jakub Narebski [off-list ref] wrote:
quoted
quoted
I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason,
To be clear, I'm not advocating and have never advocated getting rid
of zero-argument "git diff".  I've advocated that every (whole
project) diff command should be expressible by a "git diff TREE1
TREE2".  I'm fine with defaults if one or zero trees are specified.
Those pseudo-almost-refs (almost-tree-ish) are to help new users, isn't it?
But shouldn't new user learn that he/she should use "git diff" to review
his changes, rather than use "git diff NEXT WTREE" to compare staged
contents with working area?
I think we need a new term that refers to NEXT, WTREE, and commits.
It could be "snapshots", but that is closely associated with commit
and has a feeling of being read-only.  Maybe "root-tree"?

I think most users - new or ortherwise - should use "git diff".  It's
the shorter command.  I think a man page saying "git diff" is
equivalent to "git diff NEXT WTREE" is (1) very specific as to what
the command does and (2) illuminates new users to the concepts, so
that when they see "git diff HEAD NEXT" or "git diff HEAD WTREE", they
can imagine what is going on.
quoted
So "git diff" would default to "git diff NEXT WTREE".
You mean that "git diff NEXT WTREE" output be the same as "git diff",
except for corner cases (merge conflict), isn't it?
I've addressed the conflict case already.  NEXT should contain HEAD
plus all the resolved files.

As far as I can tell, with that definition, "git diff NEXT WTREE" "git
diff HEAD NEXT" and "git diff HEAD WTREE" would produce the same
results as the current implementation of "git diff", "git diff
--cached" and "git diff HEAD" --- even in a conflicted state.

I've only been able to check that by experimentation; I asked if
someone who knew the code could confirm it.
--
Jakub Narebski
Poland

Re: Command-line interface thoughts (ad-hominem attacks)

From: Jeff King <hidden>
Date: 2016-06-15 22:51:26

On Wed, Jun 08, 2011 at 07:39:16AM -0400, Michael Nahas wrote:
On Wed, Jun 8, 2011 at 7:12 AM, Jakub Narebski [off-list ref] wrote:
quoted
I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason,
To be clear, I'm not advocating and have never advocated getting rid
of zero-argument "git diff".  I've advocated that every (whole
project) diff command should be expressible by a "git diff TREE1
TREE2".  I'm fine with defaults if one or zero trees are specified.
I agree with this, but...
So "git diff" would default to "git diff NEXT WTREE".
Isn't this going to be behavior change, since your NEXT is not quite the
same as the index? How do I now get an n-way combined diff of the
unmerged files in the index?

-Peff

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:27

On Wed, 8 Jun 2011, Holger Hellmuth wrote:
On 07.06.2011 22:33, Jakub Narebski wrote:
quoted
To reiterate; perhaps it is not stated clearly in documentation:

1. "git diff" is about examining _your_ changes.  This short form is the
    same in every SCM.
you are right, more explicit mention in the docs would help about this.

But other SCMs don't have the additional target 'index'. Much easier to 
reason there. Also, wouldn't Joe User then conclude that 'git diff' must 
be comparing working area against HEAD ?
Well, actually it should be that "git diff" is about examining _your_
*remaining* changes.

If Joe User doesn't use index, then "git diff" and "git diff HEAD" shows
the same contents (modulo "git add" / "git add -N" trouble).  So Joe
doesn't need to worry if it is worktree versus index, or versus HEAD;
it is enought to know when it is used.
 
quoted
    Because of explicit index (cache, staging area) one needs to know if
    it is working area against index, or working area against HEAD.
    Thinking about merge conflict case helps to remember; in such case
    you want your changes against partially resolved merge.
This is far from a straightforward reasoning that would pop up in 
anyones mind. In truth, I can't follow that reasoning even now. In case 
of a merge conflict the working area doesn't concern me at all, I would 
want a diff between 'ours' and 'theirs'.
What you want is irrelevant ;-)  Because in the case of merge conflict
entries in index is populated automatically, *your* changes are changes
agains index.  So there.

And what "git diff" would show in that case is --cc diff of file with
merge markers against stages '1' and '2' in index, which is quite useful.
Which is 3-way diff between 'ours' and 'theirs'.


Nb. I don't know how to get _remaining_ diff between 'ours' and 'theirs',
but the NEXT proposal doesn't address it either...
Since perl has been brought up as example of this DWIM philosophy: In 
perl commands have their defaults, but you always can specify exactly 
what you want if you are not sure or want to make it explicit. You can 
use 'chomp' or you can use 'chomp $_'.
By TIMTOWTDI I rather meant here that you can write

  if (...) {
     ...
  }

or

  ... if (...);

or

  ... or ...;


I wasn't saying anything about DWIM-mery, just TIMTOWTDI and context...
But I can't make it explicit which two targets I want to compare with
'git diff'. 
For me it looks XY problem; instead of wanting to compare two explicit
targets, you should specify what you want to see ;-).
 
quoted
    Also advanced users can use index to hide fully cooked changes from
    having to browse during review.
What is where "remaining" in 'examining your remaining changes' come
from.  Advanced users can "git add <file>" (or "git add -p" even) when
some change is fully cooked and ready to be included, to reduce size of
diff when reviewing remaining changes.
quoted
    Novice users which do not use index (and use "git commit -a") would
    never notice the difference, if not for the complication of newly
    added files: in other SCM you would see on "<scm>  diff" creation
    diff (well, there is "git add -N").  Same with removal if one uses
    "git rm" and not simply "rm".
quoted
2. "git diff --cached" is about cached (staged) changes, therefore
    it is index against HEAD.
We use three words to talk about the index: cache, stage, index. So 
apart from having an additional target for diff that target also is 
diffused by three words. Sure, index is the real designation and cached 
and staged are used as verbs, but that is just one more confusing bit. 
Also 'cache' in computer science is a transparent buffer to access data 
faster (wikipedia definition). Not what I would think of the index.
At the very beginning it was named 'dircache'... ;-)))

There was an attempt to introduce 'to stage', 'staged contents' and
'staging area', and you can use "git diff --staged" instead... but
support might be incomplete.


The area is called 'the index', but you examine 'cached' contents,
not 'indexed' contents.  One of resons for the index is making git
faster, so it is the cache as well (keeps e.g. cached stats info to
make it possible for git to swiftly find which files changed).
 
Probably there are good reasons to not use "git diff --index" and 
probably they have been discussed a few times, but it doesn't make using 
diff easier. But that's a side issue.
The issue is with "git apply" and "git stash", where --index means
'use staging area in addition to working directory' and not like
--cached for "git apply" 'use staging area _instead_ of working
directory" (though _instead_ is not very precise here).
 
If someone sees 'git diff --cached' he might know one target, the index. 
But how does he get the other? By reasoning that 'git diff' alone is 
already index against working area? But for that he would have first to 
conclude that 'git diff' is not working area against HEAD (as it is in 
other SCMs), see above.
"git diff --cached" / "git diff --staged" is about 'what changes are
in index' (are 'staged'), i.e. what you "git add"-ed / "git stage"-d.
Because changes always go working directory -> staging area -> repository
(commit) it is abvious that those are "staging area -> repository"
changes.
 
quoted
3. "git diff<commit>" in general, and "git diff HEAD" in particular,
    is about your changes (worktree), compared to given commit.

At in no place I _have_ to explain what is compared with what to explain
when and what for to use "git diff", "git diff --cached" and "git diff
HEAD".
I'm sure every part of the user interface of gimp can be rationalized in 
the same way by someone deeply involved in the concepts and the 
structure of gimp, but still it is perceived as difficult by nearly 
everyone else. You look at it from inside and it looks logical. Others 
just don't have all the pieces to make that reasoning really work.
What I wanted to say here that instead of teaching / trying to teach
new people something like the following:

  There is working area, index and current commit (HEAD).  To compare
  workdir with index use this, to compare index with HEAD use that, to
  compare workdir with HEAD use this one.

we better do explaining higher level concepts

  To examine your remaining changes, i.e. what you can "git stage",
  use "git diff".  To examine staged changes, i.e. what you 
  "git stage"-d, use "git diff --staged"; that is what "git commit"
  will create.  To compare working version with given older version,
  use "git diff <revision>", in particular to compare with last version
  use "git diff HEAD"; that is what "git commit --all" would create.


The "git diff NEXT WTREE" looks like training wheels to me.  And like
training wheels they could become obstacles and not help to learning
git.  Neverthemind they can snag on sharp corners^W corner-cases. ;-)))

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts (ad-hominem attacks)

From: Michael Nahas <hidden>
Date: 2016-06-15 22:51:27

On Wed, Jun 8, 2011 at 11:05 AM, Jeff King [off-list ref] wrote:
On Wed, Jun 08, 2011 at 07:39:16AM -0400, Michael Nahas wrote:
quoted
On Wed, Jun 8, 2011 at 7:12 AM, Jakub Narebski [off-list ref] wrote:
quoted
I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason,
To be clear, I'm not advocating and have never advocated getting rid
of zero-argument "git diff".  I've advocated that every (whole
project) diff command should be expressible by a "git diff TREE1
TREE2".  I'm fine with defaults if one or zero trees are specified.
I agree with this, but...
quoted
So "git diff" would default to "git diff NEXT WTREE".
Isn't this going to be behavior change, since your NEXT is not quite the
same as the index? How do I now get an n-way combined diff of the
unmerged files in the index?

-Peff
The index is a file in .git/ that serves many purposes.  NEXT is an
image of the whole project.  NEXT can be computed from the index and
HEAD.

During a conflicted merge, stage 0 of the index holds the resolved
files.  WTREE holds all merge files: the resolved and the unresolved
(which have <<<< ==== >>>> blocks in them).  I propose that during a
conflicted merge, that NEXT be computed as HEAD plus the resolved
files, that is, the files in stage 0 of the index.

"git diff HEAD NEXT" would print the resolved changes.
"git diff NEXT WTREE" would print the unresolved changes
"git diff HEAD WTREE" would print all changes.

I believe that is the same behaviour as "git diff", "git diff
--cached" and "git diff HEAD" during a conflicted merge.

I do not know how "n-way" merge works.  I saw somewhere that indicated
that it was a series of N-1 two-way merges.


Mike

Re: Command-line interface thoughts (ad-hominem attacks)

From: Jeff King <hidden>
Date: 2016-06-15 22:51:27

On Wed, Jun 08, 2011 at 02:57:09PM -0400, Michael Nahas wrote:
quoted
Isn't this going to be behavior change, since your NEXT is not quite the
same as the index? How do I now get an n-way combined diff of the
unmerged files in the index?
The index is a file in .git/ that serves many purposes.  NEXT is an
image of the whole project.  NEXT can be computed from the index and
HEAD.

During a conflicted merge, stage 0 of the index holds the resolved
files.  WTREE holds all merge files: the resolved and the unresolved
(which have <<<< ==== >>>> blocks in them).  I propose that during a
conflicted merge, that NEXT be computed as HEAD plus the resolved
files, that is, the files in stage 0 of the index.
OK. So NEXT actually has less information than the whole index, because
it doesn't contain information on what was on either side of the merge
originally (or in the merge base).
"git diff HEAD NEXT" would print the resolved changes.
"git diff NEXT WTREE" would print the unresolved changes
"git diff HEAD WTREE" would print all changes.

I believe that is the same behaviour as "git diff", "git diff
--cached" and "git diff HEAD" during a conflicted merge.
I assume you don't mean respectively here, but rather:

  git diff          => git diff NEXT WTREE
  git diff --cached => git diff HEAD NEXT
  git diff HEAD     => git diff HEAD WTREE

But even still, I don't think "git diff" is the same. Try this:

  git init repo && cd repo
  echo one >file && git add file && git commit -m one &&
  echo two >file && git add file && git commit -m two &&
  git checkout -b other HEAD^ &&
  echo three >file && git add file && git commit -m three &&
  ! git merge master &&
  git diff

I get:

  diff --cc file
  index 2bdf67a,f719efd..0000000
  --- a/file
  +++ b/file
  @@@ -1,1 -1,1 +1,5 @@@
  ++<<<<<<< HEAD
   +three
  ++=======
  + two
  ++>>>>>>> master

Note that this is _not_ a diff between NEXT and the working tree.  It is a
3-way "combined" diff of what's in the working tree compared to each side of
the merge.

If NEXT is a tree that contains HEAD plus stage 0 files, then we would
see a 2-way diff of the HEAD version of "file" and the working tree
version. I.e., the same as "git diff HEAD -- file":

  diff --git a/file b/file
  index 2bdf67a..087e97e 100644
  --- a/file
  +++ b/file
  @@ -1 +1,5 @@
  +<<<<<<< HEAD
   three
  +=======
  +two
  +>>>>>>> master

which looks similar, because we haven't started resolving anything yet.
But try resolving it like this:

  cat >file <<'EOF'
  three
  and
  two
  EOF

Now try "git diff" again. You should get:

  diff --cc file
  index 2bdf67a,f719efd..0000000
  --- a/file
  +++ b/file
  @@@ -1,1 -1,1 +1,3 @@@
   +three
  ++and
  + two

This shows us that "three" came from one side of the merge, "two" from
the other, and that "and" was found in neither side.

Compare to the 2-way that shows:

  diff --git a/file b/file
  index 2bdf67a..1ecff7e 100644
  --- a/file
  +++ b/file
  @@ -1 +1,3 @@
   three
  +and
  +two

There's nothing to distinguish added code pulled from the other side of
the merge versus changes that were made as part of the resolution.

I think this is what Junio was talking about when he said that the index
is more than a tree. There may be times when you want to treat the items
in stage 0 as a tree, but diffing against the index is more than just
diffing against that tree.
I do not know how "n-way" merge works.  I saw somewhere that indicated
that it was a series of N-1 two-way merges.
Git history can represent a merge of any number of branches (an "octopus
merge"), because the commits store only the final state and a list of
parent commits. The combined diff format is capable of handling an
arbitrary number of parents.

I should have just said "3-way", though, because it's not relevant here.
The index only has 2 stage bits, so we can only represent four stages
("resolved", "base", "ours", and "theirs"). So you can't represent an
n-way merge in the index.

So "git merge" just punts on an octopus merge if there are actual merge
conflicts that would need to go in the index. So in practice, people
just tend to do N-1 pair-wise merges.

You can see some example octopus merges (and their combined diff) if you
have a recent git (that supports --min-parents) with:

  git log --min-parents=3 -p --cc

in both git.git and linux-2.6.git.

-Peff

Re: Command-line interface thoughts (ad-hominem attacks)

From: Michael Nahas <hidden>
Date: 2016-06-15 22:51:27

Hi Peff,

First, thanks for correcting my diff-without-NEXT-and-WTREE to
diff-with-NEXT-and-WTREE pairing.

Second, I agree that the index is more than just NEXT.  There were
good reasons behind calling it "NEXT" and not "INDEX".

Third, I didn't know for sure that "git diff" during a merge conflict
would produce a three-way-diff result, but I suspected it would.  (You
really didn't have to produce all that code - I would have accepted
your word as an expert.  But thanks!)  So, yes, the two-way merge
result of "git diff NEXT WTREE" would be different.

I could argue that git should allow a 4-way diff where "git diff NEXT
WTREE OURS THEIR" prints all the unresolved changes as coming from
OURS or THEIR or neither.  But I think that's silly.

I will say that "git diff NEXT WTREE" will tell you what's left
unresolved and most of it is in <<<<====>>>>> blocks that tell you
whether it came from OURS or THEIRS.  If the user has any discipline,
they won't introduce unnecessary changes that were not necessary for
the merge.  If they don't have discipline, we really can't help them.

I'm not saying there is no use for a 3-way merge.  In fact, I'd guess
it's a requirement so that Alice can check Bob's merge before Bob
commits.  But I'm fine with making it "git diff --3-way" or the silly
"git diff NEXT WTREE OURS THEIRS" because I think its "git diff NEXT
WTREE" will be good enough 99% of the time.



On Wed, Jun 8, 2011 at 8:43 PM, Jeff King [off-list ref] wrote:
On Wed, Jun 08, 2011 at 02:57:09PM -0400, Michael Nahas wrote:
quoted
quoted
Isn't this going to be behavior change, since your NEXT is not quite the
same as the index? How do I now get an n-way combined diff of the
unmerged files in the index?
The index is a file in .git/ that serves many purposes.  NEXT is an
image of the whole project.  NEXT can be computed from the index and
HEAD.

During a conflicted merge, stage 0 of the index holds the resolved
files.  WTREE holds all merge files: the resolved and the unresolved
(which have <<<< ==== >>>> blocks in them).  I propose that during a
conflicted merge, that NEXT be computed as HEAD plus the resolved
files, that is, the files in stage 0 of the index.
OK. So NEXT actually has less information than the whole index, because
it doesn't contain information on what was on either side of the merge
originally (or in the merge base).
quoted
"git diff HEAD NEXT" would print the resolved changes.
"git diff NEXT WTREE" would print the unresolved changes
"git diff HEAD WTREE" would print all changes.

I believe that is the same behaviour as "git diff", "git diff
--cached" and "git diff HEAD" during a conflicted merge.
I assume you don't mean respectively here, but rather:

 git diff          => git diff NEXT WTREE
 git diff --cached => git diff HEAD NEXT
 git diff HEAD     => git diff HEAD WTREE

But even still, I don't think "git diff" is the same. Try this:

 git init repo && cd repo
 echo one >file && git add file && git commit -m one &&
 echo two >file && git add file && git commit -m two &&
 git checkout -b other HEAD^ &&
 echo three >file && git add file && git commit -m three &&
 ! git merge master &&
 git diff

I get:

 diff --cc file
 index 2bdf67a,f719efd..0000000
 --- a/file
 +++ b/file
 @@@ -1,1 -1,1 +1,5 @@@
 ++<<<<<<< HEAD
  +three
 ++=======
 + two
 ++>>>>>>> master

Note that this is _not_ a diff between NEXT and the working tree.  It is a
3-way "combined" diff of what's in the working tree compared to each side of
the merge.

If NEXT is a tree that contains HEAD plus stage 0 files, then we would
see a 2-way diff of the HEAD version of "file" and the working tree
version. I.e., the same as "git diff HEAD -- file":

 diff --git a/file b/file
 index 2bdf67a..087e97e 100644
 --- a/file
 +++ b/file
 @@ -1 +1,5 @@
 +<<<<<<< HEAD
  three
 +=======
 +two
 +>>>>>>> master

which looks similar, because we haven't started resolving anything yet.
But try resolving it like this:

 cat >file <<'EOF'
 three
 and
 two
 EOF

Now try "git diff" again. You should get:

 diff --cc file
 index 2bdf67a,f719efd..0000000
 --- a/file
 +++ b/file
 @@@ -1,1 -1,1 +1,3 @@@
  +three
 ++and
 + two

This shows us that "three" came from one side of the merge, "two" from
the other, and that "and" was found in neither side.

Compare to the 2-way that shows:

 diff --git a/file b/file
 index 2bdf67a..1ecff7e 100644
 --- a/file
 +++ b/file
 @@ -1 +1,3 @@
  three
 +and
 +two

There's nothing to distinguish added code pulled from the other side of
the merge versus changes that were made as part of the resolution.

I think this is what Junio was talking about when he said that the index
is more than a tree. There may be times when you want to treat the items
in stage 0 as a tree, but diffing against the index is more than just
diffing against that tree.
quoted
I do not know how "n-way" merge works.  I saw somewhere that indicated
that it was a series of N-1 two-way merges.
Git history can represent a merge of any number of branches (an "octopus
merge"), because the commits store only the final state and a list of
parent commits. The combined diff format is capable of handling an
arbitrary number of parents.

I should have just said "3-way", though, because it's not relevant here.
The index only has 2 stage bits, so we can only represent four stages
("resolved", "base", "ours", and "theirs"). So you can't represent an
n-way merge in the index.

So "git merge" just punts on an octopus merge if there are actual merge
conflicts that would need to go in the index. So in practice, people
just tend to do N-1 pair-wise merges.

You can see some example octopus merges (and their combined diff) if you
have a recent git (that supports --min-parents) with:

 git log --min-parents=3 -p --cc

in both git.git and linux-2.6.git.

-Peff

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:27

On Wed, 8 June 2011, Michael Nahas wrote:
On Wed, Jun 8, 2011 at 11:05 AM, Jeff King [off-list ref] wrote:
quoted
On Wed, Jun 08, 2011 at 07:39:16AM -0400, Michael Nahas wrote:
quoted
On Wed, Jun 8, 2011 at 7:12 AM, Jakub Narebski [off-list ref] wrote:
quoted
I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason,
To be clear, I'm not advocating and have never advocated getting rid
of zero-argument "git diff".  I've advocated that every (whole
project) diff command should be expressible by a "git diff TREE1
TREE2".  I'm fine with defaults if one or zero trees are specified.
I agree with this, but...
quoted
So "git diff" would default to "git diff NEXT WTREE".
Isn't this going to be behavior change, since your NEXT is not quite the
same as the index? How do I now get an n-way combined diff of the
unmerged files in the index?
The index is a file in .git/ that serves many purposes.  NEXT is an
image of the whole project.  NEXT can be computed from the index and
HEAD.

During a conflicted merge, stage 0 of the index holds the resolved
files.
It is simply not true.  During a conflicted merge, for conflicted files
there is _no_ stage 0!!!  Conflicted files have stage 1 == base, 2 == ours
and 3 == theirs, where those stages have all conflicts that can be resolved
automatically resolved, and places where there is conflict replaced by
merge-base ('base'), current branch into which we merge ('ours') and
merged branch ('theirs').
WTREE holds all merge files: the resolved and the unresolved 
(which have <<<< ==== >>>> blocks in them).
Worktree version has files with conflict merge markers added in place
where there is conflict.

I propose that during a 
conflicted merge, that NEXT be computed as HEAD plus the resolved 
files, that is, the files in stage 0 of the index.
Why _HEAD_?
 
"git diff HEAD NEXT" would print the resolved changes.
"git diff NEXT WTREE" would print the unresolved changes
"git diff HEAD WTREE" would print all changes.

I believe that is the same behaviour as "git diff", "git diff
--cached" and "git diff HEAD" during a conflicted merge.
"git diff NEXT WTREE" would not behave (with your proposal) like
"git diff", but like "git diff --ours".

"git diff HEAD NEXT" would not behave like "git diff --cached"
(which shows only '*Unmerged path foo').

"git diff HEAD WTREE" would be the same as "git diff HEAD" (just
longer to write), only because it doesn't involve index at all.
 
I do not know how "n-way" merge works.  I saw somewhere that indicated
that it was a series of N-1 two-way merges.
Where this "n-way merge" came from?  Peff wrote about "n-way combined
diff", which is something different.

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Michael Nahas <hidden>
Date: 2016-06-15 22:51:27

On Thu, Jun 9, 2011 at 5:48 AM, Jakub Narebski [off-list ref] wrote:
On Wed, 8 June 2011, Michael Nahas wrote:
quoted
On Wed, Jun 8, 2011 at 11:05 AM, Jeff King [off-list ref] wrote:
quoted
On Wed, Jun 08, 2011 at 07:39:16AM -0400, Michael Nahas wrote:
quoted
On Wed, Jun 8, 2011 at 7:12 AM, Jakub Narebski [off-list ref] wrote:
quoted
I don't quite think that we need "git diff NEXT WTREE"; the short
and sweet "git diff" is short for a reason,
To be clear, I'm not advocating and have never advocated getting rid
of zero-argument "git diff".  I've advocated that every (whole
project) diff command should be expressible by a "git diff TREE1
TREE2".  I'm fine with defaults if one or zero trees are specified.
I agree with this, but...
quoted
So "git diff" would default to "git diff NEXT WTREE".
Isn't this going to be behavior change, since your NEXT is not quite the
same as the index? How do I now get an n-way combined diff of the
unmerged files in the index?
The index is a file in .git/ that serves many purposes.  NEXT is an
image of the whole project.  NEXT can be computed from the index and
HEAD.

During a conflicted merge, stage 0 of the index holds the resolved
files.
It is simply not true.  During a conflicted merge, for conflicted files
there is _no_ stage 0!!!  Conflicted files have stage 1 == base, 2 == ours
and 3 == theirs, where those stages have all conflicts that can be resolved
automatically resolved, and places where there is conflict replaced by
merge-base ('base'), current branch into which we merge ('ours') and
merged branch ('theirs').
"resolved files" means "NOT conflicted files".  The merge conflicts if
any one file conflicts, but there may be other files that resolve
immediately.  And any conflicted files can be resolved by the user
running "git add" or "git rm"

If a file is resolved - either immediately or by user action - it
exists only in stage 0.
quoted
WTREE holds all merge files: the resolved and the unresolved
(which have <<<< ==== >>>> blocks in them).
Worktree version has files with conflict merge markers added in place
where there is conflict.
I assumed most people knew what I meant by <<<<====>>>> blocks.  But,
yes, I meant that the working tree has both versions present at
locations of conflicts.
quoted
I propose that during a
conflicted merge, that NEXT be computed as HEAD plus the resolved
files, that is, the files in stage 0 of the index.
Why _HEAD_?
Because we merged changed from another branch into HEAD.
Or we pull changes from a remote branch into HEAD.

When a commit is written, it will be part of the branch referenced by HEAD.
quoted
"git diff HEAD NEXT" would print the resolved changes.
"git diff NEXT WTREE" would print the unresolved changes
"git diff HEAD WTREE" would print all changes.

I believe that is the same behaviour as "git diff", "git diff
--cached" and "git diff HEAD" during a conflicted merge.
"git diff NEXT WTREE" would not behave (with your proposal) like
"git diff", but like "git diff --ours".
OURS and HEAD are the same thing, so I doubt a command that does not
involve "HEAD" would behave like "--ours"
"git diff HEAD NEXT" would not behave like "git diff --cached"
(which shows only '*Unmerged path foo').

"git diff HEAD WTREE" would be the same as "git diff HEAD" (just
longer to write), only because it doesn't involve index at all.
I refer you to any of my previous emails to which I kindly replied.
YES, "git diff HEAD" and "git diff HEAD WTREE" would be equivalent.
I, myself, would probably use "git diff HEAD" most of the time.
Nonetheless, saying "git diff" ALWAYS takes two arguments and saying
that if an argument is unspecified that there is a default is much
clearer and more regular interface than special casing everything and
using command-line options to say what you want, which is what we have
now.

quoted
I do not know how "n-way" merge works.  I saw somewhere that indicated
that it was a series of N-1 two-way merges.
Where this "n-way merge" came from?  Peff wrote about "n-way combined
diff", which is something different.
N-way merge exists.  It would be bad to say that I was answering a
question about conflicted merges if I didn't produce an answer for
N-way merges.  Unfortunately, I don't have enough information about
N-way merges to answer the question so I decided it was best to
acknowledge my ignorance and that I was giving an incomplete answer.


--
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Holger Hellmuth <hidden>
Date: 2016-06-15 22:51:27

On 08.06.2011 20:56, Jakub Narebski wrote:
[...]
quoted
quoted
     Because of explicit index (cache, staging area) one needs to know if
     it is working area against index, or working area against HEAD.
     Thinking about merge conflict case helps to remember; in such case
     you want your changes against partially resolved merge.
          --------
quoted
This is far from a straightforward reasoning that would pop up in
anyones mind. In truth, I can't follow that reasoning even now. In case
of a merge conflict the working area doesn't concern me at all, I would
want a diff between 'ours' and 'theirs'.
What you want is irrelevant ;-)
No, because you used my wants in your reasoning above. Makes them highly 
relevant ;-)
Because in the case of merge conflict
entries in index is populated automatically, *your* changes are changes
agains index.  So there.

And what "git diff" would show in that case is --cc diff of file with
merge markers against stages '1' and '2' in index, which is quite useful.
Which is 3-way diff between 'ours' and 'theirs'.
Ah okay. This detail about the merge process never really registered 
with me. Which shows that your logic deduction what 'git diff' does is 
often not possible for the casual user

[...]
quoted
But I can't make it explicit which two targets I want to compare with
'git diff'.
For me it looks XY problem; instead of wanting to compare two explicit
targets, you should specify what you want to see ;-).
Then don't call the command 'diff' (... I proclaim in the knowledge that 
that isn't possible). 'diff' is the short form of 'difference' which 
means literally a comparison between *two* things. If someone wants to 
see something he would pick the words 'show' or 'list'. So user 
expectation is different from what you want diff to be.

Also there are no good words for what someone wants to see in this case. 
At least I would assume the git project would have found them if they 
existed. '--cached' is definitely not one of them. But we have fitting 
and widely known names for the targets, i.e 'working tree', 'index' and 
'head'.

[...]
quoted
quoted
At in no place I _have_ to explain what is compared with what to explain
when and what for to use "git diff", "git diff --cached" and "git diff
HEAD".
I'm sure every part of the user interface of gimp can be rationalized in
the same way by someone deeply involved in the concepts and the
structure of gimp, but still it is perceived as difficult by nearly
everyone else. You look at it from inside and it looks logical. Others
just don't have all the pieces to make that reasoning really work.
What I wanted to say here that instead of teaching / trying to teach
new people something like the following:

   There is working area, index and current commit (HEAD).  To compare
   workdir with index use this, to compare index with HEAD use that, to
   compare workdir with HEAD use this one.
If they know working area, index and head, you don't have to tell them 
three times how to compare this with that, they just have to know they 
can compare any which way they want. In fact, the situation *now* is 
exactly what you describe, you have to tell everyone for any of the 3 
combinations the command to use because it is not obvious.
we better do explaining higher level concepts

   To examine your remaining changes, i.e. what you can "git stage",
   use "git diff".  To examine staged changes, i.e. what you
   "git stage"-d, use "git diff --staged"; that is what "git commit"
   will create.  To compare working version with given older version,
   use "git diff<revision>", in particular to compare with last version
   use "git diff HEAD"; that is what "git commit --all" would create.
Do you realize that you are just enumerating all the possible 
combinations again, exactly what you wanted to avoid? Ok, unfair 
argument, you want to just make it clear how to remember the commands. 
But if I already need 3 emails from you to see the concept behind these 
commands (and lets assume my slow-wittedness is par for the course) many 
others will probably have the same problems. It may be a nice concept, 
but the relation to the user interface is only detectable by close 
examination.

Teaching concepts is good. But if git is only usable after having 
learned all those concepts, the entry barrier is much too big. With 
commands like 'git put' and an improved diff people can use git first, 
then learn the concepts while using git. Which is what most people have 
to do anyway if they encounter git at the work place for example.
The "git diff NEXT WTREE" looks like training wheels to me.  And like
training wheels they could become obstacles and not help to learning
git.  Neverthemind they can snag on sharp corners^W corner-cases. ;-)))
If your goal is that anyone who uses git is a git expert, they may be a 
hindrance (as are all the porcelain commands really). If you also want 
to make git friendly to people who will never get past intermediate or 
beginner stage or will only use a small part of git or use git seldomly, 
training wheels are good.

Holger.

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:27

On Thu, Jun 9, 2011, Michael Nahas wrote:
On Thu, Jun 9, 2011 at 5:48 AM, Jakub Narebski [off-list ref] wrote:
quoted
On Wed, 8 June 2011, Michael Nahas wrote:
quoted
On Wed, Jun 8, 2011 at 11:05 AM, Jeff King [off-list ref] wrote:
quoted
quoted
quoted
Isn't this going to be behavior change, since your NEXT is not quite the
same as the index?
[...]
quoted
quoted
I propose that during a
conflicted merge, that NEXT be computed as HEAD plus the resolved
files, that is, the files in stage 0 of the index.
Why _HEAD_?
Because we merged changed from another branch into HEAD.
Or we pull changes from a remote branch into HEAD.

When a commit is written, it will be part of the branch referenced
by HEAD. 
And by selecting HEAD for diff's NEXT you would have problems with rebase,
where you also can have conflicts, where 'ours' and 'theirs' are switched
around (at least from one point of view).
 
quoted
quoted
"git diff HEAD NEXT" would print the resolved changes.
"git diff NEXT WTREE" would print the unresolved changes
"git diff HEAD WTREE" would print all changes.

I believe that is the same behaviour as "git diff", "git diff
--cached" and "git diff HEAD" during a conflicted merge.
"git diff NEXT WTREE" would not behave (with your proposal) like
"git diff", but like "git diff --ours".
OURS and HEAD are the same thing, so I doubt a command that does not
involve "HEAD" would behave like "--ours"
OURS and HEAD are not the same thing.  In OURS you have _conflicted_
chunks replaced with HEAD ('ours') version, but chunks that can be
resolved sutomatically are resolved; sometimes to 'theirs' version.

"git diff" in case of conflict prints 3-way combined diff between
'ours', 'theirs' and working area version.  As "git diff NEXT WTREE"
doesn't print 3-way combined diff, it would be different for conflicts
from "git diff".

"git diff --ours" for nonconflicted entry (stage 0 in index) would
print ordinary diff between index and working area, just like
"git diff NEXT WTREE".  What I just realized that at least from what
you wrote (corner case!) in case of conflicts it would be different
from "git diff NEXT WTREE", as ours != HEAD.

[...]
quoted
quoted
I do not know how "n-way" merge works.  I saw somewhere that indicated
that it was a series of N-1 two-way merges.
Where this "n-way merge" came from?  Peff wrote about "n-way combined
diff", which is something different.
N-way merge exists.  It would be bad to say that I was answering a
question about conflicted merges if I didn't produce an answer for
N-way merges.  Unfortunately, I don't have enough information about
N-way merges to answer the question so I decided it was best to
acknowledge my ignorance and that I was giving an incomplete answer.
Actually while git can do n-way merge (so called "octopus" merge), it
either resolves it cleanly, or refuses merge; it does not try to resolve
conflict and present conflicts in the index.  So it is always "3-way
combined diff".

But you didn't answer about _combined diff_...

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:27

Jakub Narebski wrote:
On Thu, Jun 9, 2011, Michael Nahas wrote:
quoted
On Thu, Jun 9, 2011 at 5:48 AM, Jakub Narebski [off-list ref] wrote:
quoted
On Wed, 8 June 2011, Michael Nahas wrote:
[...]
quoted
quoted
quoted
"git diff HEAD NEXT" would print the resolved changes.
"git diff NEXT WTREE" would print the unresolved changes
"git diff HEAD WTREE" would print all changes.

I believe that is the same behaviour as "git diff", "git diff
--cached" and "git diff HEAD" during a conflicted merge.
"git diff NEXT WTREE" would not behave (with your proposal) like
"git diff", but like "git diff --ours".
OURS and HEAD are the same thing, so I doubt a command that does not
involve "HEAD" would behave like "--ours"
OURS and HEAD are not the same thing.  In OURS you have _conflicted_
chunks replaced with HEAD ('ours') version, but chunks that can be
resolved sutomatically are resolved; sometimes to 'theirs' version.
I'm very sorry, my mistake.  I have actually checked and OURS is the
same as HEAD version.

You wrote that NEXT contains either stage 0 for resolved files, or
OURS (HEAD) version for files with conflicts.  But that is exactly
what "git diff --ours" show.
"git diff" in case of conflict prints 3-way combined diff between
'ours', 'theirs' and working area version.  As "git diff NEXT WTREE"
doesn't print 3-way combined diff, it would be different for conflicts
from "git diff".

"git diff --ours" for nonconflicted entry (stage 0 in index) would
print ordinary diff between index and working area, just like
"git diff NEXT WTREE". [...]
-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts (ad-hominem attacks)

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:27

On Thu, 9 Jun 2011, Michael Nahas wrote:
Hi Peff,

First, thanks for correcting my diff-without-NEXT-and-WTREE to
diff-with-NEXT-and-WTREE pairing.

Second, I agree that the index is more than just NEXT.  There were
good reasons behind calling it "NEXT" and not "INDEX".
NEXT has to be _well defined_ (is it tree-ish or a multi-tree in some 
cases), and definition examined if it is _useful_ (e.g. if you can get
results of "git diff" with "git diff NEXT <sth>..." both for conflicted 
and resolved cleanly entries).
 
This thread served to specify original handwavy definition of NEXT...
Third, I didn't know for sure that "git diff" during a merge conflict
would produce a three-way-diff result, but I suspected it would.  (You
really didn't have to produce all that code - I would have accepted
your word as an expert.  But thanks!)  So, yes, the two-way merge
result of "git diff NEXT WTREE" would be different.

I could argue that git should allow a 4-way diff where "git diff NEXT
WTREE OURS THEIR" prints all the unresolved changes as coming from
OURS or THEIR or neither.  But I think that's silly.
It would be "git diff NEXT OURS THEIRS WTREE" or "git diff BASE OURS 
THEIRS WTREE" -- the putative merge results should be last; the 
convention of combined diff format is like for ordinary diff: first 
source(s), then destination.
I will say that "git diff NEXT WTREE" will tell you what's left
unresolved and most of it is in <<<<====>>>>> blocks that tell you
whether it came from OURS or THEIRS.  If the user has any discipline,
they won't introduce unnecessary changes that were not necessary for
the merge.  If they don't have discipline, we really can't help them.
What if he/she removed conflict markers, test compiled... and realized
that it was mismerge, then fixed?  Then to examine current fixed 
contents he/she doesn't have help of <<<< ==== >>>> blocks...
I'm not saying there is no use for a 3-way merge.  In fact, I'd guess
it's a requirement so that Alice can check Bob's merge before Bob
commits.  But I'm fine with making it "git diff --3-way" or the silly
"git diff NEXT WTREE OURS THEIRS" because I think its "git diff NEXT
WTREE" will be good enough 99% of the time.
"git diff --cc".  But I think with having to say explicitly 
"git diff --3way" / "git diff --cc" Alice wouldn't know that it has such 
useful tool...


P.S. Could you not quote text in bulk, if you are not answering to it 
block by block?  It is unnecessary download, and burden of scrolling 
down to check if there is anything added at bottom.
-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:27

On Thu, 9 Jun 2011, Holger Hellmuth wrote:
On 08.06.2011 20:56, Jakub Narebski wrote:
[...]
quoted
quoted
But I can't make it explicit which two targets I want to compare with
'git diff'.
For me it looks XY problem; instead of wanting to compare two explicit
targets, you should specify what you want to see ;-).
Then don't call the command 'diff' (... I proclaim in the knowledge that 
that isn't possible). 'diff' is the short form of 'difference' which 
means literally a comparison between *two* things.
Blame CVS (I think) on that.  It introduced no arguments "cvs diff" to
get current changes, and other version control systems picked this
convention up, including Git.
 
"diff" is 'are there any differences', or 'are there any changes'.
Implicit rules (targets) are very useful.
If someone wants to 
see something he would pick the words 'show' or 'list'. So user 
expectation is different from what you want diff to be.
There is always "git status"...
Also there are no good words for what someone wants to see in this case. 
At least I would assume the git project would have found them if they 
existed. '--cached' is definitely not one of them. But we have fitting 
and widely known names for the targets, i.e 'working tree', 'index' and 
'head'.
"I want to see if there are any remiaining changes", "I want to see what
'git commit' would bring", "I want to see what 'git commit -a' would bring".
Neither of those is about targets for diff.

[...]
quoted
The "git diff NEXT WTREE" looks like training wheels to me.  And like
training wheels they could become obstacles and not help to learning
git.  Neverthemind they can snag on sharp corners^W corner-cases. ;-)))
If your goal is that anyone who uses git is a git expert, they may be a 
hindrance (as are all the porcelain commands really). If you also want 
to make git friendly to people who will never get past intermediate or 
beginner stage or will only use a small part of git or use git seldomly, 
training wheels are good.
Those "training wheels" are useless for beginner, and might be not very
useful to middle expert user either, depending on corner cases.

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Holger Hellmuth <hidden>
Date: 2016-06-15 22:51:27

On 10.06.2011 18:44, Jakub Narebski wrote:
On Thu, 9 Jun 2011, Holger Hellmuth wrote:
quoted
Also there are no good words for what someone wants to see in this case.
At least I would assume the git project would have found them if they
existed. '--cached' is definitely not one of them. But we have fitting
and widely known names for the targets, i.e 'working tree', 'index' and
'head'.
"I want to see if there are any remiaining changes", "I want to see what
'git commit' would bring", "I want to see what 'git commit -a' would bring".
Neither of those is about targets for diff.
Are you proposing a command "git 
--I-want-to-see-if-there-are-any-remaining-changes" ? ;-). I was looking 
for short command or parameter names that are easy to remember, not for 
definitions of the output of cryptic commands.

But lets see. If I didn't know much git, where would I look for the 
right command for your three needs? Where would I expect the solution? 
(note I'm not proposing any of these commands)

"I want to see if there are any remiaining changes"?
git status
git status --full
git status --detailed

"I want to see what 'git commit' would bring"
git commit --dry-run

"I want to see what 'git commit -a' would bring"
git commit -a --dry-run

Now I'll add a question I would want to ask:
"I want to see the changes between what I have in my working tree and 
what I already added to the index"
git diff WTREE INDEX


Btw. even the 'git diff' man page emphasizes that diff is about a 
comparision between two things. Citation: "Show changes *between* two 
trees, a tree and the working tree, a tree and the index file,...".

[...]
quoted
quoted
The "git diff NEXT WTREE" looks like training wheels to me.  And like
training wheels they could become obstacles and not help to learning
git.  Neverthemind they can snag on sharp corners^W corner-cases. ;-)))
If your goal is that anyone who uses git is a git expert, they may be a
hindrance (as are all the porcelain commands really). If you also want
to make git friendly to people who will never get past intermediate or
beginner stage or will only use a small part of git or use git seldomly,
training wheels are good.
Those "training wheels" are useless for beginner, and might be not very
useful to middle expert user either, depending on corner cases.
"useless for beginner". No reasoning, just a fat road block for my opinion?
As git expert you are so far removed from any beginner status. Are you 
sure you still know how a beginner thinks?

Holger.

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:27

Dnia piątek 10. czerwca 2011 20:07, Holger Hellmuth napisał:
On 10.06.2011 18:44, Jakub Narebski wrote:
quoted
On Thu, 9 Jun 2011, Holger Hellmuth wrote:
quoted
Also there are no good words for what someone wants to see in this case.
At least I would assume the git project would have found them if they
existed. '--cached' is definitely not one of them. But we have fitting
and widely known names for the targets, i.e 'working tree', 'index' and
'head'.
"I want to see if there are any remiaining changes", "I want to see what
'git commit' would bring", "I want to see what 'git commit -a' would bring".
Neither of those is about targets for diff.
Are you proposing a command "git 
--I-want-to-see-if-there-are-any-remaining-changes" ? ;-). I was looking 
for short command or parameter names that are easy to remember, not for 
definitions of the output of cryptic commands.

But lets see. If I didn't know much git, where would I look for the 
right command for your three needs? Where would I expect the solution? 
(note I'm not proposing any of these commands)

"I want to see if there are any remaining changes"?
git status
git status --full
git status --detailed
"Any differences"?

git diff


"I want to see what I staged"

git diff --staged


Isn't it simpler than "I want to see the changes between what I already
staged, which is put in place called index, but must refer to it by NEXT,
and the changes I didn't staged, in my working area, which I refer to by
WORK... no, it is TREE... oh, wait, it is WTREE" :-)  I am exaggerating
much here, but I think you can see what I want to point out.
Now I'll add a question I would want to ask:
"I want to see the changes between what I have in my working tree and 
what I already added to the index"
That's not a beginner question.
git diff WTREE INDEX
           ^^^^^^^^^^^ --- reverse to "git diff"

In this direction it is surely suprising... you see, how again and again
having to explicitely state what to compare with which leads to mistakes
such like this one, and the one in few mails earlier.
 
Btw. even the 'git diff' man page emphasizes that diff is about a 
comparision between two things. Citation: "Show changes *between* two 
trees, a tree and the working tree, a tree and the index file,...".
 
That's more about explaining result of command.  Besides manpages are
reference documentation; new users should start with user's manual, or
tutorial (or "Pro Git"), not manpages.
 
quoted
[...]
quoted
quoted
The "git diff NEXT WTREE" looks like training wheels to me.  And like
training wheels they could become obstacles and not help to learning
git.  Neverthemind they can snag on sharp corners^W corner-cases. ;-)))
If your goal is that anyone who uses git is a git expert, they may be a
hindrance (as are all the porcelain commands really). If you also want
to make git friendly to people who will never get past intermediate or
beginner stage or will only use a small part of git or use git seldomly,
training wheels are good.
Those "training wheels" are useless for beginner, and might be not very
useful to middle expert user either, depending on corner cases.
"useless for beginner". No reasoning, just a fat road block for my opinion?
As git expert you are so far removed from any beginner status. Are you 
sure you still know how a beginner thinks?
Well, that depends by what you mean by beginner.  Beginner to git, but
not beginner to version control knows about "<scm> diff" form to check
for one's changes, for example.

But I don't think that beginner knows that there is such thing like the
index, and know that he/she has to compare the index to the working area.
When he/she starts to use the index, probably he/she isn't a beginner
anymore.

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Holger Hellmuth <hidden>
Date: 2016-06-15 22:51:28

Am 10.06.2011 20:35, schrieb Jakub Narebski:
Dnia piątek 10. czerwca 2011 20:07, Holger Hellmuth napisał:
quoted
On 10.06.2011 18:44, Jakub Narebski wrote:
quoted
On Thu, 9 Jun 2011, Holger Hellmuth wrote:
quoted
Also there are no good words for what someone wants to see in this case.
At least I would assume the git project would have found them if they
existed. '--cached' is definitely not one of them. But we have fitting
and widely known names for the targets, i.e 'working tree', 'index' and
'head'.
"I want to see if there are any remiaining changes", "I want to see what
'git commit' would bring", "I want to see what 'git commit -a' would bring".
Neither of those is about targets for diff.
Are you proposing a command "git 
--I-want-to-see-if-there-are-any-remaining-changes" ? ;-). I was looking 
for short command or parameter names that are easy to remember, not for 
definitions of the output of cryptic commands.

But lets see. If I didn't know much git, where would I look for the 
right command for your three needs? Where would I expect the solution? 
(note I'm not proposing any of these commands)

"I want to see if there are any remaining changes"?
git status
git status --full
git status --detailed
"Any differences"?

git diff
But difference to what --> User checks man page, again.

"I want to see what I staged"

git diff --staged
User never heard of 'staged'. He asks instead "I want to see what I
added" --> git diff --added --> Error Message --> User checks man page,
again
Isn't it simpler than "I want to see the changes between what I already
staged, which is put in place called index, but must refer to it by NEXT,
and the changes I didn't staged, in my working area, which I refer to by
WORK... no, it is TREE... oh, wait, it is WTREE" :-)  I am exaggerating
much here, but I think you can see what I want to point out.
Sure. I'm not a fan of 'NEXT' either. I would use INDEX. Or even index
if that doesn't clash with anything. WTREE as well is not optimal but it
is something you can get at as soon as you remember the term 'working
tree'. And you know what you will get without consulting the manuals if
you are unsure.
quoted
Now I'll add a question I would want to ask:
"I want to see the changes between what I have in my working tree and 
what I already added to the index"
That's not a beginner question.
Ok, I had a different definition of beginner, especially since I and all
the git-user I know at my work place used the index from the beginning.
The index is a wonderful idea but it isn't that hard to understand. If
you look at the gittutorial man page (and any of the other 3 top
tutorials in google) 3 of those 4 tutorials talk about the index and git
add, only one uses 'git commit -a' instead.

Only one mentions 'git diff --cached' by the way, seems to be an
advanced topic ;-)

quoted
git diff WTREE INDEX
           ^^^^^^^^^^^ --- reverse to "git diff"

In this direction it is surely suprising... you see, how again and again
having to explicitely state what to compare with which leads to mistakes
such like this one, and the one in few mails earlier.
I'm a sloopy person as you have noticed. Also very forgetful. I usually
don't bother with the order of 'diff' parameters when I can get the
direction from the diff output.
quoted
Btw. even the 'git diff' man page emphasizes that diff is about a 
comparision between two things. Citation: "Show changes *between* two 
trees, a tree and the working tree, a tree and the index file,...".
 
That's more about explaining result of command.  Besides manpages are
reference documentation; new users should start with user's manual, or
tutorial (or "Pro Git"), not manpages.
Ok, so lets look at 'Pro Git'. Besides using your description it is also
talking about comparision between working area and staging area and
comparing staged changes to last commit.
Well, that depends by what you mean by beginner.  Beginner to git, but
not beginner to version control knows about "<scm> diff" form to check
for one's changes, for example.

But I don't think that beginner knows that there is such thing like the
index, and know that he/she has to compare the index to the working area.
When he/she starts to use the index, probably he/she isn't a beginner
anymore.
Learning git is not a role playing game where you have to master level 1
before you can use all the tricks of level 2 ;-). But any which way we
call them there are a lot of users using git with index and all, but who
have to search in the docs whenever they want to do something like
unadding something from the index.

Small things like 'git unadd', Jeff Kings 'git put' and git diff with
targets probably would help this casual/intermediate/advanced user (take
your pick).

Holger.

git diff --added (Re: Command-line interface thoughts)

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:51:28

Holger Hellmuth wrote:
User never heard of 'staged'. He asks instead "I want to see what I
added" --> git diff --added --> Error Message --> User checks man page,
again
Do you think it would be valuable to introduce --added as a synonym
for --cached and slowly steer documentation to encourage the latter
in place of the former?

Examples, to see how it could work in practice:

	# Instead of searching tracked files in the working tree,
	# search blobs registered in the index file (i.e., accepted
	# with "git add" instead of the iffy hacks that are up in
	# the air).  The main advantage of this over plain "git grep"
	# is speed.
	git grep --added -e foo

	# Remove foo.c from the next commit, without touching the
	# worktree.
	git rm --added foo.c

	# Apply patch to the index, leaving the worktree alone.
	git apply --added some-change.patch

	# List changes that I marked with "git add" for inclusion in
	# the next commit.
	git diff --added

I like it a lot more than "staged". ;-)  Though --index-only still
seems a little clearer to me.

Re: git diff --added (Re: Command-line interface thoughts)

From: Miles Bader <hidden>
Date: 2016-06-15 22:51:28

Jonathan Nieder [off-list ref] writes:
Do you think it would be valuable to introduce --added as a synonym
for --cached and slowly steer documentation to encourage the latter
in place of the former?
"--added" sounds very awkward though; "--staged" is much more natural.

-miles

-- 
Idiot, n. A member of a large and powerful tribe whose influence in human
affairs has always been dominant and controlling.

Re: git diff --added (Re: Command-line interface thoughts)

From: Miles Bader <hidden>
Date: 2016-06-15 22:51:28

On Mon, Jun 13, 2011 at 4:11 AM, Miles Bader [off-list ref] wrote:
quoted
Do you think it would be valuable to introduce --added as a synonym
for --cached and slowly steer documentation to encourage the latter
in place of the former?
"--added" sounds very awkward though; "--staged" is much more natural.
I should note _why_ this is so:

The main problem is well-known -- that "git add" is a bit overloaded
and slightly awkward in some case (e.g., to remove a file, you need to
add it...).  But whatever, it works well enough, because people are
used to it.

However in the case of git diff, if one sees "git diff --added", it
sounds like it means "show me a diff of added files" -- but the term
"added files" is ambiguous; and the fact that "git add" is in fact,
overloaded with multiple meanings doesn't really help, the basic
ambiguity makes "git diff --added" awkward and unclear.

A far better way would be to (1) make "git diff --staged" an alias for
"git-diff --cached" (2) start promoting "git stage" in documentation,
instead of "git add".

-Miles

-- 
Cat is power.  Cat is peace.

Re: git diff --added (Re: Command-line interface thoughts)

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:51:28

Miles Bader wrote:
"--added" sounds very awkward though; "--staged" is much more natural.
You make a strong case.  How about something like this?

-- >8 --
Subject: Documentation: explain diff --cached in terms of non --cached form

"git diff" is a somewhat odd command, since it has two fairly
different roles:

 - on one hand, it is the command to explain the worktree or index in
   terms of something else;
 - on the other hand, it is the command to compare two blobs, trees,
   or on-disk files.

To a new user, that second role might seem to be the most basic and
most natural, since it is most closely analagous to the ordinary
non-git "diff" command, but in practice the first one is the one that
gets used most often and it is somewhat different.  Avoid surprises
by treating this first role separately in the introductory paragraph
and calling it "primary".

The motivation is that it is hard enough to remember the various 0-
and 1-tree forms of "git diff"; hopefully fending off the distraction
of a false analogy with 2-tree "git diff" will help with that.  This
patch also tries to clarify those mnemonics (especially: "--cached"
mean to use the index in place of the worktree) by rearranging the
material slightly.  The most obvious mechanical changes involved are
listing 0- and 1-tree "git diff" separately in the synopsis and
reordering the text to put "git diff HEAD" before "git diff --cached
HEAD".

Some small wording improvements snuck in while at it, including
mentioning the --staged synonym for --cached a little more often.

Signed-off-by: Jonathan Nieder <redacted>
---
 Documentation/git-diff.txt |   61 +++++++++++++++++++++++--------------------
 1 files changed, 33 insertions(+), 28 deletions(-)
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index f8d0819..7a66017 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -9,59 +9,64 @@ git-diff - Show changes between commits, commit and working tree, etc
 SYNOPSIS
 --------
 [verse]
-'git diff' [options] [<commit>] [--] [<path>...]
+'git diff' [options] [--] [<path>...]
+'git diff' [options] <commit> [--] [<path>...]
 'git diff' [options] --cached [<commit>] [--] [<path>...]
 'git diff' [options] <commit> <commit> [--] [<path>...]
 'git diff' [options] [--no-index] [--] <path> <path>
 
 DESCRIPTION
 -----------
-Show changes between the working tree and the index or a tree, changes
-between the index and a tree, changes between two trees, or changes
-between two files on disk.
+The primary purpose of 'git diff' is to compare files in the working
+tree to stored versions in the repository.  It can also be used to
+show changes between the index and a tree, changes between two trees,
+or changes between two files on disk.
 
-'git diff' [--options] [--] [<path>...]::
+'git diff' [options] [--] [<path>...]::
 
 	This form is to view the changes you made relative to
-	the index (staging area for the next commit).  In other
-	words, the differences are what you _could_ tell git to
-	further add to the index but you still haven't.  You can
-	stage these changes by using linkgit:git-add[1].
+	the index (staging area for the next commit).  It is
+	the most common use of 'git diff'; the differences are
+	what you _could_ tell git to further add to the index
+	but you still haven't.  You can stage these changes by
+	using linkgit:git-add[1] (aka linkgit:git-stage[1]).
 +
-If exactly two paths are given and at least one points outside
-the current repository, 'git diff' will compare the two files /
-directories. This behavior can be forced by --no-index.
+If exactly two paths are given and one points outside the current
+repository, 'git diff' will compare the two files or directories.
+This behavior can be forced with the `--no-index` option.
 
-'git diff' [--options] --cached [<commit>] [--] [<path>...]::
-
-	This form is to view the changes you staged for the next
-	commit relative to the named <commit>.  Typically you
-	would want comparison with the latest commit, so if you
-	do not give <commit>, it defaults to HEAD.
-	If HEAD does not exist (e.g. unborned branches) and
-	<commit> is not given, it shows all staged changes.
-	--staged is a synonym of --cached.
-
-'git diff' [--options] <commit> [--] [<path>...]::
+'git diff' [options] <commit> [--] [<path>...]::
 
 	This form is to view the changes you have in your
 	working tree relative to the named <commit>.  You can
-	use HEAD to compare it with the latest commit, or a
+	use HEAD to compare with the latest commit, or a
 	branch name to compare with the tip of a different
 	branch.
 
-'git diff' [--options] <commit> <commit> [--] [<path>...]::
+'git diff' [options] --cached [<commit>] [--] [<path>...]::
+'git diff' [options] --staged [<commit>] [--] [<path>...]::
+
+	If passed --cached or its synonym --staged,
+	'git diff' will view the changes you have staged for
+	the next commit instead of examining the working tree.
+	Typically you would want a comparison with the latest
+	commit, so if you do not give <commit>, it defaults
+	to HEAD.
+	If HEAD does not exist (e.g. unborn branches) and
+	<commit> is not given, it shows all staged changes.
+
+'git diff' [options] <commit> <commit> [--] [<path>...]::
 
 	This is to view the changes between two arbitrary
-	<commit>.
+	commits.
 
-'git diff' [--options] <commit>..<commit> [--] [<path>...]::
+'git diff' [options] <commit>..<commit> [--] [<path>...]::
 
 	This is synonymous to the previous form.  If <commit> on
 	one side is omitted, it will have the same effect as
 	using HEAD instead.
 
-'git diff' [--options] <commit>\...<commit> [--] [<path>...]::
+'git diff' [options] <commit>\...<commit> [--] [<path>...]::
 
 	This form is to view the changes on the branch containing
 	and up to the second <commit>, starting at a common ancestor
-- 
1.7.6.rc1

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:28

On Sat, 11 June 2011, Holger Hellmuth wrote:
Am 10.06.2011 20:35, schrieb Jakub Narebski:
quoted
Dnia piątek 10. czerwca 2011 20:07, Holger Hellmuth napisał:
quoted
On 10.06.2011 18:44, Jakub Narebski wrote:
quoted
On Thu, 9 Jun 2011, Holger Hellmuth wrote:
quoted
quoted
quoted
quoted
Also there are no good words for what someone wants to see in this case.
At least I would assume the git project would have found them if they
existed. '--cached' is definitely not one of them. But we have fitting
and widely known names for the targets, i.e 'working tree', 'index' and
'head'.
"I want to see if there are any remaining changes", "I want to see what
'git commit' would bring", "I want to see what 'git commit -a' would bring".
Neither of those is about targets for diff.
Are you proposing a command "git 
--I-want-to-see-if-there-are-any-remaining-changes" ? ;-). I was looking 
for short command or parameter names that are easy to remember, not for 
definitions of the output of cryptic commands.

But lets see. If I didn't know much git, where would I look for the 
right command for your three needs? Where would I expect the solution? 
(note I'm not proposing any of these commands)

"I want to see if there are any remaining changes"?
git status
git status --full
git status --detailed
"Any differences"?

git diff
But difference to what --> User checks man page, again.
User's changes.  User doesn't need to know what are those two places
called.
 
quoted

"I want to see what I staged"

git diff --staged
User never heard of 'staged'. He asks instead "I want to see what I
added" --> git diff --added --> Error Message --> User checks man page,
again
User uses "git stage <file>", so he/she uses "git diff --staged".
 
[...]
quoted
quoted
git diff WTREE INDEX
          ^^^^^^^^^^^ --- reverse to "git diff"

In this direction it is surely suprising... you see, how again and again
having to explicitely state what to compare with which leads to mistakes
such like this one, and the one in few mails earlier.
I'm a sloopy person as you have noticed. Also very forgetful. I usually
don't bother with the order of 'diff' parameters when I can get the
direction from the diff output.
For other people getting the reverse of changes can be certainly
suprising (I though I added this, not deleted...).  When you specify
endpoints manually, there is a chance to get them in wrong direction.
Especially that there is NEXT WTREE but HEAD NEXT.
Small things like 'git unadd', Jeff Kings 'git put' and git diff with
targets probably would help this casual/intermediate/advanced user (take
your pick).
I agree with 'git unadd'.  Jeff Kings 'git put' and git diff targets have
the problems that need to be fully solved before considering for inclusion.

BTW. there is code for 'git put'.  Where is code for git diff targets?

-- 
Jakub Narebski
Poland

Re: Command-line interface thoughts

From: Holger Hellmuth <hidden>
Date: 2016-06-15 22:51:28

Am 13.06.2011 12:15, schrieb Jakub Narebski:
For other people getting the reverse of changes can be certainly
suprising (I though I added this, not deleted...).  When you specify
endpoints manually, there is a chance to get them in wrong direction.
Especially that there is NEXT WTREE but HEAD NEXT.
Other people have that problem anyway when they use 'git diff <commit>
<othercommit>'. Or when they use linux diff, where the man page doesn't
even specify which direction it compares. Obviously someone thought that
"--- a.txt,  +++ b.txt" or the direction of '>' and '<' give enough hints.

[...]
BTW. there is code for 'git put'.  Where is code for git diff targets?
Do you accept perl code? ;-) I've never seriously coded in C

Holger.

Re: Command-line interface thoughts

From: Michael Haggerty <hidden>
Date: 2016-06-15 22:51:28

On 06/13/2011 12:15 PM, Jakub Narebski wrote:
BTW. there is code for 'git put'.  Where is code for git diff targets?
Is this just a rhetorical question, or would code be useful?  From the
tone of the conversation, I got the impression that the change has no
chance of being accepted.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

Re: Command-line interface thoughts

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:51:28

On Thu, 14 Jun 2011, Michael Haggerty wrote:
On 06/13/2011 12:15 PM, Jakub Narebski wrote:
quoted
BTW. there is code for 'git put'.  Where is code for git diff targets?
Is this just a rhetorical question, or would code be useful?  From the
tone of the conversation, I got the impression that the change has no
chance of being accepted.
It was not entirely rhetorical question.

First, code speak louder than words. A feature for which there exist
implementation (and documentation, and tests) has much more chance being
accepted / merged in, than purely theoretical discussion on user
interface. Though the latter is needed too, of course.

Second, writing proof of concept implementation, or at least trying
to write documentation and/or test for new feature or new behavior
help to flesh out ideas, to give them definite shape.


But I know that not everybody is a programmer, and from those not all
are proficient in C (at least for this case), Perl, Python or shell
scripting, and with Git API to implement new feature.

-- 
Jakub Narebski
Poland
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help