From: Junio C Hamano <hidden> Date: 2016-06-15 22:50:31
Jeff King [off-list ref] writes:
Is "git add -p" broken, then? It takes pathspecs relative to the current
directory, but "git add -p" without arguments operates from the root,
not from the current subdirectory.
I would say so; "add -p" was an ill-executed afterthought. The codepath
was originally meant to be used from "-i" as the top-level interface that
was a fully interactive way to prepare for the next commit, which is an
operation that is inherently full-tree.
There are two schools of thought in previous threads discussing full-tree
vs current-directory-relative. I think each side has merits.
If we defaulted to the current directory (i.e. "git grep"), that would
feel more natural as it is more consistent with how tools that are not git
aware (e.g. "GNU grep" run in the same directory) behave. A downside is
when you are somewhere deep in a working tree, you have to know how deep
you are and repeat "../" that many times, i.e. "git grep pattern ../../"
If we defaulted to the root-level (i.e. "git diff"), you do not have that
downside (iow, "git diff" run from a deep directory is a full tree
operation), and you can limit the scope to the current directory by a
single dot, i.e. "git diff .". A huge downside is that this may feel
awkward for new people who do not yet breath git [*1*], as no other git
aware tool would behave like this, limiting its scope to some directory
that is higher above.
In the past, I have took the third position, saying that tools that
semantically needs to be full-tree should be full-tree (i.e. ones that
make or format commits), and others should be relative to the current
directory (i.e. ones that are used to inspect your progress, such as
grep), but that is not a very understandable guideline that people can
easily follow. If we have to choose between the two and make things
consistent, my personal preference is to make everything relative to the
current working directory.
I actually do not mind too much myself if all commands that can take
pathspecs consistently defaulted to "full-tree" pathspec given no
pathspec. But if we were to go that route, everybody should join their
voice to defend that decision when outside people say "in 1.8.0 'git grep'
run from a subdirectory shows matches from all the irrelevant parts of the
tree; with all the cruft its output is unreadable". I won't be the sole
champion of such a behaviour when I do not fully believe in it.
[Footnote]
*1* In the case of "git diff", this is largely mitigated as its output is
always relative to the root of the working tree, but other tools may not
have that luxury.
On Mon, Feb 7, 2011 at 1:46 PM, Junio C Hamano [off-list ref] wrote:
I actually do not mind too much myself if all commands that can take
pathspecs consistently defaulted to "full-tree" pathspec given no
pathspec. But if we were to go that route, everybody should join their
voice to defend that decision when outside people say "in 1.8.0 'git grep'
run from a subdirectory shows matches from all the irrelevant parts of the
tree; with all the cruft its output is unreadable". I won't be the sole
champion of such a behaviour when I do not fully believe in it.
That could be one more item for the next git survey (i.e. how do you
want the defaults to be?). Most of people in this list more or less
breath git already and therefore are bias (I think).
Personally "git add -u --full-tree" is good enough to me. It does have
the same problem that git --full-tree has: what *.h in "git grep
--full-tree -- '*.h'" means. But I'm OK with not supporting that case
until we agree on something.
--
Duy
From: SZEDER Gábor <hidden> Date: 2016-06-15 22:50:31
On Sun, Feb 06, 2011 at 10:46:20PM -0800, Junio C Hamano wrote:
Jeff King [off-list ref] writes:
quoted
Is "git add -p" broken, then? It takes pathspecs relative to the current
directory, but "git add -p" without arguments operates from the root,
not from the current subdirectory.
I would say so; "add -p" was an ill-executed afterthought. The codepath
was originally meant to be used from "-i" as the top-level interface that
was a fully interactive way to prepare for the next commit, which is an
operation that is inherently full-tree.
There are two schools of thought in previous threads discussing full-tree
vs current-directory-relative. I think each side has merits.
If we defaulted to the current directory (i.e. "git grep"), that would
feel more natural as it is more consistent with how tools that are not git
aware (e.g. "GNU grep" run in the same directory) behave. A downside is
when you are somewhere deep in a working tree, you have to know how deep
you are and repeat "../" that many times, i.e. "git grep pattern ../../"
If we defaulted to the root-level (i.e. "git diff"), you do not have that
downside (iow, "git diff" run from a deep directory is a full tree
operation), and you can limit the scope to the current directory by a
single dot, i.e. "git diff .". A huge downside is that this may feel
awkward for new people who do not yet breath git [*1*], as no other git
aware tool would behave like this, limiting its scope to some directory
that is higher above.
In the past, I have took the third position, saying that tools that
semantically needs to be full-tree should be full-tree (i.e. ones that
make or format commits), and others should be relative to the current
directory (i.e. ones that are used to inspect your progress, such as
grep), but that is not a very understandable guideline that people can
easily follow. If we have to choose between the two and make things
consistent, my personal preference is to make everything relative to the
current working directory.
_Everything_ relative to the current working directory? I can't
imagine how would that work in practice. Could you explain what would
the following commands do, for example, when they are relative to the
current working directory?
$ cd t
$ git checkout next
$ git merge somebranch
$ git reset HEAD^
Best,
Gábor
From: Jeff King <hidden> Date: 2016-06-15 22:50:31
On Sun, Feb 06, 2011 at 10:46:20PM -0800, Junio C Hamano wrote:
I actually do not mind too much myself if all commands that can take
pathspecs consistently defaulted to "full-tree" pathspec given no
pathspec. But if we were to go that route, everybody should join their
voice to defend that decision when outside people say "in 1.8.0 'git grep'
run from a subdirectory shows matches from all the irrelevant parts of the
tree; with all the cruft its output is unreadable". I won't be the sole
champion of such a behaviour when I do not fully believe in it.
The problem is that I don't feel comfortable writing an RFC that says
"in 1.8.0 we will default to full-tree because it is somehow better".
Because I don't think it is better; it is simply a different way of
thinking about it, and different people will have different preferences.
I think even the same people may different preferences from project to
project. For most of my projects, the scope of the repo is well-defined,
and I want full-tree semantics (e.g., I hack on a bug, go into t/ to
tweak and run the tests, and then want to "git add -u" the whole thing
when everything looks good). But I also recently worked on a gigantic
project that was split into several sub-components. I would cd 3 or 4
levels deep into the sub-component that I was working on, and I would
prefer my "git add -u" to stay in that sub-component, and my "git grep"
to look only in that sub-component.
Which implies to me that the "relative" or "full-tree" view should be a
per-repo configurable thing. But that introduces its own set of
headaches, as people may script around things like "git add", and it
would become predictable to do so only from the top-level of the working
tree.
-Peff
From: Eric Raible <hidden> Date: 2016-06-15 22:50:31
On 11:59 AM, Junio C Hamano wrote:
I actually do not mind too much myself if all commands that can take
pathspecs consistently defaulted to "full-tree" pathspec given no
pathspec. But if we were to go that route, everybody should join their
voice to defend that decision when outside people say "in 1.8.0 'git grep'
run from a subdirectory shows matches from all the irrelevant parts of the
tree; with all the cruft its output is unreadable". I won't be the sole
champion of such a behaviour when I do not fully believe in it.
IFUC this shouldn't affect any (correctly written) scripts,
and so the only downside is that (when run in a subdir) commands
that are currently spelled:
git xxx
would with this change need to be spelled:
git xxx .
One advantage of this approach is that one's fingers would
learn the "only this dir" two char sequence very quickly.
So FWIW, I will do my best to help defend such a decision.
From: SZEDER Gábor <hidden> Date: 2016-06-15 22:50:31
On Mon, Feb 07, 2011 at 02:50:35PM -0500, Jeff King wrote:
On Sun, Feb 06, 2011 at 10:46:20PM -0800, Junio C Hamano wrote:
quoted
I actually do not mind too much myself if all commands that can take
pathspecs consistently defaulted to "full-tree" pathspec given no
pathspec. But if we were to go that route, everybody should join their
voice to defend that decision when outside people say "in 1.8.0 'git grep'
run from a subdirectory shows matches from all the irrelevant parts of the
tree; with all the cruft its output is unreadable". I won't be the sole
champion of such a behaviour when I do not fully believe in it.
The problem is that I don't feel comfortable writing an RFC that says
"in 1.8.0 we will default to full-tree because it is somehow better".
Because I don't think it is better; it is simply a different way of
thinking about it, and different people will have different preferences.
I think even the same people may different preferences from project to
project. For most of my projects, the scope of the repo is well-defined,
and I want full-tree semantics (e.g., I hack on a bug, go into t/ to
tweak and run the tests, and then want to "git add -u" the whole thing
when everything looks good). But I also recently worked on a gigantic
project that was split into several sub-components. I would cd 3 or 4
levels deep into the sub-component that I was working on, and I would
prefer my "git add -u" to stay in that sub-component, and my "git grep"
to look only in that sub-component.
It sounds like your work focused solely on the sub-component you cd-d
into. Did you have any other changes outside of that sub-component?
Because when not, then both the current and the whole-tree "git add -u"
would have the same effect.
The current and the whole-tree "git grep" would behave differently, of
course. But even then a whole-tree "git grep" would be harmless and
easy to limit in scope, though might be a bit annoying in the "cd deep
down" case. In that case you would immediately see the matches
outside of cwd, know that you forgot to limit the operation to cwd, so
you hit the up key, simply append the "." to the last command, and you
get what you wanted.
As mentioned in this or other related threads, this is not at all that
simple the other way around, i.e. with current "git grep" when you are
in the sub-component and you happen to need a grep on the whole tree,
because you have to pay attention to use the right number of "../"s.
A whole-tree "git add -u" is just as easy to limit in scope as the
whole-tree "git grep" would be, but certainly more annoying when you
forget to limit it to cwd. But even in that case there is no harm
done, because all the changes you've made are there, but you have to
unstage changes from the index or split the commit.
Current "git add -u" is worst of all, because it's not just difficult
to circumvent (how many "../" do I need?), but it's downright
dangerous, because you can lose changes when forget that it's limited
in scope. I managed to do something like this while fixing two
already bisected bugs:
git checkout deadbeef # BugA was introduced in that commit
vim git.c # fix BugA
cd t
test ; vim test ; test
git add -u # again forgetting that a
# fundamentally whole-tree oriented
# tool has operations with
# non-whole-tree defaults...
git commit -m 'Fix BugA' # will write proper commit msg later
git branch fix_BugA # to find the commit later
git reset --hard babefeed # instead of "git checkout babefeed"
# BugB was introduced there
# goodbye bugfix!
# hack away to fix BugB # until realisation sets in
# Damn.
You could argue that there are several ways I could have prevented
shooting myself in the foot, e.g. using "git checkout" instead of "git
reset --hard", or by using plain "git commit" without the "-m" option
I might have noticed the unstaged changes in the commit template. I
would even tend to agree, but I still think that git should be
consistent with _itself_ in the first place, and since git's
fundamental concepts are whole-tree oriented and there are many
commands that only make sense on the whole tree, defaulting to
whole-tree operations for commands taking a pathspec is indeed better.
And safer too.
Best,
Gábor
From: Jeff King <hidden> Date: 2016-06-15 22:50:32
On Tue, Feb 08, 2011 at 11:05:18AM +0100, SZEDER Gábor wrote:
quoted
I think even the same people may different preferences from project to
project. For most of my projects, the scope of the repo is well-defined,
and I want full-tree semantics (e.g., I hack on a bug, go into t/ to
tweak and run the tests, and then want to "git add -u" the whole thing
when everything looks good). But I also recently worked on a gigantic
project that was split into several sub-components. I would cd 3 or 4
levels deep into the sub-component that I was working on, and I would
prefer my "git add -u" to stay in that sub-component, and my "git grep"
to look only in that sub-component.
It sounds like your work focused solely on the sub-component you cd-d
into. Did you have any other changes outside of that sub-component?
Because when not, then both the current and the whole-tree "git add -u"
would have the same effect.
Yes, I often did have other changes. They were usually one of two types.
The build infrastructure was in a separate directory, so one type would
be local tweaks to the build that should not end up getting committed.
The other type was required changes to another component that would get
committed separately (e.g., while working on component "foo" you realize
that it depends on a new feature in component "bar"; you leave "foo"
modified in the working tree, work on "bar", commit it, then come back
to "foo").
The current and the whole-tree "git grep" would behave differently, of
course. But even then a whole-tree "git grep" would be harmless and
easy to limit in scope, though might be a bit annoying in the "cd deep
down" case. In that case you would immediately see the matches
outside of cwd, know that you forgot to limit the operation to cwd, so
you hit the up key, simply append the "." to the last command, and you
get what you wanted.
Yeah, grep is not as annoying because it does not have the "oops, I just
pushed this commit and it turns out that I screwed up "git add" five
minutes ago and it only had half of the files I intended" problem.
As mentioned in this or other related threads, this is not at all that
simple the other way around, i.e. with current "git grep" when you are
in the sub-component and you happen to need a grep on the whole tree,
because you have to pay attention to use the right number of "../"s.
Yes, it is annoying, but that is merely a syntactic issue. If we aliased
"/" to "the root of the project", then most arguments for full-tree
could be reversed for the relative case (e.g., "sure, but it's easy
enough to type 'git add /'").
For the record, I would much prefer full-tree behavior as the default,
and I think the '/' syntax is ugly and confusing. If you were asking at
the beginning of "git add -u" what the behavior should be, I would
absolutely say full-tree. But we're not there; we're talking about
changing existing behavior. And I'm not sure there is a clear-cut,
obvious-to-anybody-who-will-annoyed-with-the-change argument that
full-tree behavior is definitively better.
The most compelling I have seen is "you tend to notice accidental
full-tree sooner than accidental relative behavior". Which you mentioned
in your email. I just don't know if that passes the "will satisfy
annoyed users" test.
I dunno. I would not be sad at all if we moved to full-tree defaults
everywhere. I just don't want to have to be the one that annoyed users
yell at. :)
-Peff