Discussion:
GIT - error: no such remote ref refs/heads/TestBranch
Sean Kelley
2006-12-19 20:33:07 UTC
Permalink
Hi,

I was wondering if someone could help me. I had a branch on our
remote GIT server called TestBranch. I logged into the Remote server
and ran:

<from remote server>
git branch -D TestBranch

But in my local clone:

***@oifig:~/Work/kernel$ git pull origin
***@git.example.com's password:
error: no such remote ref refs/heads/TestBranch
Fetch failure: git+ssh://git.example.com/data/git/proj/kernel/mh.git
***@oifig:~/Work/kernel$

Any ideas how to correct this?

Sean
Junio C Hamano
2006-12-19 22:06:03 UTC
Permalink
Post by Sean Kelley
Hi,
I was wondering if someone could help me. I had a branch on our
remote GIT server called TestBranch. I logged into the Remote server
<from remote server>
git branch -D TestBranch
error: no such remote ref refs/heads/TestBranch
Fetch failure: git+ssh://git.example.com/data/git/proj/kernel/mh.git
Any ideas how to correct this?
If you know remote does not have it, then probably not fetching
from it would be a good idea.

Look at your local $GIT_DIR/remotes/origin (or [remote "origin"]
section in $GIT_DIR/config) and remove the refspec that tells
git to fetch it.

In $GIT_DIR/remotes/origin, you may want to remove a like like this:

Pull: refs/heads/TestBranch:<something>

If it is coming from $GIT_DIR/config, it would probably look
like:

[remote "origin"]
fetch = refs/heads/TestBranch:<something>

and you would want to remove the "fetch = " line.
Carl Worth
2006-12-20 22:31:14 UTC
Permalink
Post by Junio C Hamano
Post by Sean Kelley
error: no such remote ref refs/heads/TestBranch
Fetch failure: git+ssh://git.example.com/data/git/proj/kernel/mh.git
Any ideas how to correct this?
If you know remote does not have it, then probably not fetching
from it would be a good idea.
I think a common case is just wanting to track the upstream contents,
whether branches appear or disappear, and being able to do that
without manually maintaining a local configuration file listing the
current remote branches.

Presumably the recently added globbing support would provide that
ability, correct?

Is there any plan to make git-clone take advantage of this capability
so that one can track an upstream that has branches that get
added/remove without having to learn how to manually maintain the
current list of branches in .git/config ?

-Carl
Junio C Hamano
2006-12-20 22:36:12 UTC
Permalink
Post by Carl Worth
Is there any plan to make git-clone take advantage of this capability
so that one can track an upstream that has branches that get
added/remove without having to learn how to manually maintain the
current list of branches in .git/config ?
Could you check "log master..next" and see if you like what has
been cooking, please?

The next batch of 'master' updates will have jc/clone topic (see
the latest issue of "What's cooking" message on the list) which
will include what has been cooking in 'next' around this area.
Carl Worth
2006-12-20 22:57:27 UTC
Permalink
Post by Junio C Hamano
Post by Carl Worth
Is there any plan to make git-clone take advantage of this capability
so that one can track an upstream that has branches that get
added/remove without having to learn how to manually maintain the
current list of branches in .git/config ?
Could you check "log master..next" and see if you like what has
been cooking, please?
Oh, yes, there it is. (I had skimmed the log for master..next but had
missed it---I guess that I also searched for "glob" instead of
"wildcard" didn't help).

Anyway, yes, the description of the new stuff there looks very
interesting, and I'll maybe I'll start running from next a bit to see
how this stuff all works.

I guess the big reason I wrote was that I was surprised to see your
reply instructing Sean on how to update the config file without also
saying something like, "by the way, this need to update the config
file like this will be going away with new work on git-clone that is
being done now and is expected to be in the upcoming git 1.5".

I thought that was the case, but didn't want to say it without
confirming it first. Thanks for confirming it for me.

-Carl
Junio C Hamano
2006-12-20 23:36:51 UTC
Permalink
Post by Carl Worth
Anyway, yes, the description of the new stuff there looks very
interesting, and I'll maybe I'll start running from next a bit to see
how this stuff all works.
Good.

Do you have comments on recent changes (both on 'master' and
some parts of 'next') from teachability point of view? I think
you are "the guilty guy" who defined the theme for v1.5.0 to be
"usability and teachability" ;-).
Carl Worth
2006-12-21 06:55:58 UTC
Permalink
Post by Junio C Hamano
Do you have comments on recent changes (both on 'master' and
some parts of 'next') from teachability point of view? I think
you are "the guilty guy" who defined the theme for v1.5.0 to be
"usability and teachability" ;-).
I'm flattered to be blamed for what I consider a very good theme for
the release.

I don't have a lot of detailed comments right now other than to repeat
a "good job!" to everyone who has done a lot to improve things lately,
(coming up with more use-oriented documentation, adding a reasonable
shorthand "add"[*] for update-index, cleaning up a lot of bad error
message and needless spew, making much more reasonable default clone
behavior, etc. etc.). I think git's really come a long ways as far as
usability and teachability, (while nothing fundamental has really
changed and old-time users should hardly notice anything different).

I think I'll have a few minor tweaks to suggest to the documentation
if I get a chance to take a detailed pass over it, (which I hope to do
before the new year).

And I'd definitely like to enable "git checkout <revision>" with a new
complaint on git-commit before the 1.5 release. I'll see if I can't
find time to work on implementing that.

-Carl

[*] I'm still somewhat unsettled that the "new" add command conflates
the notions of adding content into the index for paths that previously
didn't exist in the index with the notion of updating the content in
the index for paths that did exist already. I think those notions are
generally distinct from the users point of view---the first changes a
file's state in a fundamental way, (from "untracked" to "tracked"),
while the second merely updates its content with no change to its
state.

One way to see the distinction is to imagine two different useful
operations "add all untracked file paths to the index" and "update
content for all tracked paths". If we had separate commands for 'add'
and 'update' then it would be natural to express these two variants
with "git add --all" and "git update --all".

As things stand now, the first operation is available already with
"git add .", (and oddly, with "git add", and I agree that should be
removed). Meanwhile the second operation is not currently available in
git, (but I recently proposed it as "git add -a|--all" in response to
a request). As pointed out in that thread, there's a bit of a problem
in that "git add --all" is really easy to mistake for a command that
would add all untracked files to the index, (since it's when adding
new paths that people will most often use "git add" so it will
naturally be associated with adding new paths). It's less likely for
users to establish the "update content" notion of "git add" since it
often won't be needed at all, (tutorials and the git-commit
documentation recommend "commit -a" to avoid the need to use "git add"
in its updating sense).

So, to summarize, I think it's good to have a much shorter command to
type than "update-index" for the update-content-of-path-in-index
operation. So using "add" for this is better than "update-index"
already. And if that's how it stays, I can certainly live with it.

But I think it might be even better if the updating notion were on a
separate command name (update ? stage ?), and this in spite of the
fact that fewer commands is generally better for learnability.

It's not a major issue---and it's nothing that I would make a big fuss
over, so feel free to ignore it if it appears a non-issue to you.
Peter Baumann
2006-12-21 10:49:28 UTC
Permalink
--pgp-sign-Multipart_Wed_Dec_20_22:55:50_2006-1
Content-Type: text/plain; charset=US-ASCII
Post by Junio C Hamano
Do you have comments on recent changes (both on 'master' and
some parts of 'next') from teachability point of view? I think
you are "the guilty guy" who defined the theme for v1.5.0 to be
"usability and teachability" ;-).
I'm flattered to be blamed for what I consider a very good theme for
the release.
I don't have a lot of detailed comments right now other than to repeat
a "good job!" to everyone who has done a lot to improve things lately,
(coming up with more use-oriented documentation, adding a reasonable
shorthand "add"[*] for update-index, cleaning up a lot of bad error
message and needless spew, making much more reasonable default clone
behavior, etc. etc.). I think git's really come a long ways as far as
usability and teachability, (while nothing fundamental has really
changed and old-time users should hardly notice anything different).
I think I'll have a few minor tweaks to suggest to the documentation
if I get a chance to take a detailed pass over it, (which I hope to do
before the new year).
And I'd definitely like to enable "git checkout <revision>" with a new
complaint on git-commit before the 1.5 release. I'll see if I can't
find time to work on implementing that.
-Carl
[*] I'm still somewhat unsettled that the "new" add command conflates
the notions of adding content into the index for paths that previously
didn't exist in the index with the notion of updating the content in
the index for paths that did exist already. I think those notions are
generally distinct from the users point of view---the first changes a
file's state in a fundamental way, (from "untracked" to "tracked"),
while the second merely updates its content with no change to its
state.
One way to see the distinction is to imagine two different useful
operations "add all untracked file paths to the index" and "update
content for all tracked paths". If we had separate commands for 'add'
and 'update' then it would be natural to express these two variants
with "git add --all" and "git update --all".
I'm also not so confident about mixing "add NEW files" with "updating
the contents of already known files". I'd prefere to seperate those two
meanings. Having two similarly named files in my workdir, I could easly
misspell the filename and wouldn't even notice that I have added a NEW
file inspite of refreshing the contents of an already existing file.
As things stand now, the first operation is available already with
"git add .", (and oddly, with "git add", and I agree that should be
removed). Meanwhile the second operation is not currently available in
git, (but I recently proposed it as "git add -a|--all" in response to
a request). As pointed out in that thread, there's a bit of a problem
in that "git add --all" is really easy to mistake for a command that
would add all untracked files to the index, (since it's when adding
new paths that people will most often use "git add" so it will
naturally be associated with adding new paths). It's less likely for
users to establish the "update content" notion of "git add" since it
often won't be needed at all, (tutorials and the git-commit
documentation recommend "commit -a" to avoid the need to use "git add"
in its updating sense).
So, to summarize, I think it's good to have a much shorter command to
type than "update-index" for the update-content-of-path-in-index
operation. So using "add" for this is better than "update-index"
already. And if that's how it stays, I can certainly live with it.
But I think it might be even better if the updating notion were on a
separate command name (update ? stage ?), and this in spite of the
fact that fewer commands is generally better for learnability.
What about 'refresh'?
It's not a major issue---and it's nothing that I would make a big fuss
over, so feel free to ignore it if it appears a non-issue to you.
--pgp-sign-Multipart_Wed_Dec_20_22:55:50_2006-1
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit
--pgp-sign-Multipart_Wed_Dec_20_22:55:50_2006-1--
Junio C Hamano
2006-12-22 00:52:51 UTC
Permalink
Post by Peter Baumann
I'm also not so confident about mixing "add NEW files" with "updating
the contents of already known files".
File boundaries do not matter ;-) You are adding contents.
Sometimes new contents are contained in a file that git already
knew about. Other times they are contained in a file that git
did not know about.

But that is a phylosophical answer, not a practical one, since
majority of the time (unless you are talking about the first few
weeks of a new project) you will be adding contents that happen
to be in the files git knows about.

I think the operation related but different from "git add ."
Carl talks about would be useful in practice. I do not know
what the option should be called.

"git add --modified"?
"git add --tracked"?
"git add --updated"?

It would work in the same way as the pre-commit step of "git
commit -a".
Carl Worth
2006-12-22 02:32:55 UTC
Permalink
Post by Junio C Hamano
Post by Peter Baumann
I'm also not so confident about mixing "add NEW files" with "updating
the contents of already known files".
File boundaries do not matter ;-) You are adding contents.
I don't follow.

There's more than just content here. The index contains a list of
paths as well, and a command like "commit -a" iterates over that
list. The addition or removal of a path from that list is a conceptual
notion that's very important to the user and the kinds of thing a user
does on a regular basis.
Post by Junio C Hamano
But that is a phylosophical answer, not a practical one, since
majority of the time (unless you are talking about the first few
weeks of a new project) you will be adding contents that happen
to be in the files git knows about.
I don't think it's practical to write off addition of new paths as
unimportant or uncommon except in the beginning of projects. Projects
grow new functionality and files get added. Code gets refactored and
files get renamed. The addition or removal of paths from the index is
just as important an operation as changing content of existing paths.

And I still think there are remaining interface problems that git has
in this area. For example, my most common sequence of operations when
hacking code is as follows:

# edit files
git diff # to review what I've done
git commit -a # to record it

Recently, I did some edits and also added some new files. I did:

# edit files and make new ones
git diff # only edits appear here

Hmm... did I forget to add those new files?

git add new-file.c
git diff # still only shows the edits

At this point I can exercise my git mental muscles and know that "add"
shoves stuff into the index so what I really want is:

git diff HEAD # shows edits and new file contents

Regardless of how hard those git muscles may be to come by---I still
don't like having to exercise them here.

I complained about this when I first encountered git, and back then I
said what I thought I wanted was "git diff HEAD" by default. I was
totally wrong, since diff from the index is so obviously correct for
resolving a conflict. Junio even responded to my complaints by
providing a new "git status -v -a" but frankly I've never used
it. That's awful awkward to use when "git diff" is so easy to type and
_most_ of the time is exactly what I want.

I'd really like "git diff" to be what I want more often. So what I'd
like is to be able to get the index in such a state that typing "git
diff" like I always do would show me everything I just typed,
(regardless of whether it was in files that git had seen before or
not).

So, I think what I really want here is a complete separation in the
interface between adding a path to the index and updating content into
the index.

We've long had a command that updates content to the index, and it
takes a command-line option (--add) to allow it to first do the
necessary path addition as well. The symmetry I would like is if we
had a command, ("git add", say), that just did the path addition and
could accept a command-line option (--update, say) to get it to the
the updating of the content as well.

And I think that any talk about "git cannot accept a file name without
content" is misplaced. The proposal here does not change any internal
models of git. I'm talking about an interface issue, and if the
interface isn't helping the user then it's wrong. That "git diff"
usually shows me what I've just typed but I can't (easily[*]) get it
to do that when I'm adding a new file is really annoying.

[*] Well, I could get it to do that by carefully creating the file,
running "git add" immediately, and only _then_ going on to type
content into the file. But that's not how I work. I do a bunch of file
manipulations without thinking about git at all, and then when I'm
happy with that, only then do I want to turn to git and use "git add",
"git diff", and "git commit" to get the results I want.

So I suppose I could implement the "add path without updating content"
I want by doing something like:

mv file file.tmp
touch file
git update-index --add file
mv file.tmp file

There. That gives me the result I want without breaking any git
internals, (since I'm just building a new operation on top of existing
git primitives).
Post by Junio C Hamano
Carl talks about would be useful in practice. I do not know
what the option should be called.
"git add --modified"?
"git add --tracked"?
"git add --updated"?
It would work in the same way as the pre-commit step of "git
commit -a".
I think the best would be:

git update-index --all

which would still allow room for:

git add --all

as a consistent way to get at the current behavior of "git add .".

So here I'm arguing against "git add" being a more convenient synonym
for "git update-index". I still think it would be nice to have a more
convenient synonym. I've proposed "stage" before but that wasn't well
accepted. Just shortening "update-index" to "update" would be
problematic as many other RCSs use "update" as a way of picking up new
content that has become available on the remote end. So, the best
suggestion I have at this point is "refresh". So I'd be happy if
either:

git refresh --add
or:
git add --refresh

would provide the behavior that currently is provided by "git add",
(that is, add a new path to the index and update the content of that
path in the index from the content of the named file in the working
tree). But it would be great if "git add" without the --refresh would
add the path without updating the content.

-Carl
Sean
2006-12-22 03:06:32 UTC
Permalink
On Thu, 21 Dec 2006 18:32:55 -0800
Post by Carl Worth
So here I'm arguing against "git add" being a more convenient synonym
for "git update-index". I still think it would be nice to have a more
convenient synonym. I've proposed "stage" before but that wasn't well
accepted. Just shortening "update-index" to "update" would be
problematic as many other RCSs use "update" as a way of picking up new
content that has become available on the remote end. So, the best
suggestion I have at this point is "refresh". So I'd be happy if
git refresh --add
git add --refresh
would provide the behavior that currently is provided by "git add",
(that is, add a new path to the index and update the content of that
path in the index from the content of the named file in the working
tree). But it would be great if "git add" without the --refresh would
add the path without updating the content.
The end result you're trying to achieve is worthwhile, but it seems the
new git add capabilities have already taken root. What do you think
about accepting the new behavior of add, but offer a new command, say:

$ git track-file <file>

Which would do exactly as you propose in your email, add the path to
the index with empty content?

Sean
Nicolas Pitre
2006-12-22 05:06:32 UTC
Permalink
Post by Carl Worth
So, I think what I really want here is a complete separation in the
interface between adding a path to the index and updating content into
the index.
Strangely enough I think this separation is unnecessary and redundent.
Post by Carl Worth
We've long had a command that updates content to the index, and it
takes a command-line option (--add) to allow it to first do the
necessary path addition as well.
And it is still there.
Post by Carl Worth
The symmetry I would like is if we
had a command, ("git add", say), that just did the path addition and
could accept a command-line option (--update, say) to get it to the
the updating of the content as well.
And you can do just that with git-update-index.
Post by Carl Worth
And I think that any talk about "git cannot accept a file name without
content" is misplaced. The proposal here does not change any internal
models of git. I'm talking about an interface issue, and if the
interface isn't helping the user then it's wrong. That "git diff"
usually shows me what I've just typed but I can't (easily[*]) get it
to do that when I'm adding a new file is really annoying.
The problem lies with the git-diff interface then, not git-add.
Post by Carl Worth
[*] Well, I could get it to do that by carefully creating the file,
running "git add" immediately, and only _then_ going on to type
content into the file. But that's not how I work. I do a bunch of file
manipulations without thinking about git at all, and then when I'm
happy with that, only then do I want to turn to git and use "git add",
"git diff", and "git commit" to get the results I want.
So I suppose I could implement the "add path without updating content"
mv file file.tmp
touch file
git update-index --add file
mv file.tmp file
There. That gives me the result I want without breaking any git
internals, (since I'm just building a new operation on top of existing
git primitives).
Post by Junio C Hamano
Carl talks about would be useful in practice. I do not know
what the option should be called.
"git add --modified"?
"git add --tracked"?
"git add --updated"?
It would work in the same way as the pre-commit step of "git
commit -a".
git update-index --all
git add --all
as a consistent way to get at the current behavior of "git add .".
There is no consistency needed between git-add and git-update-index.
The first is for users while the second is more suited for scripting
your own interface.
Post by Carl Worth
So here I'm arguing against "git add" being a more convenient synonym
for "git update-index". I still think it would be nice to have a more
convenient synonym. I've proposed "stage" before but that wasn't well
accepted. Just shortening "update-index" to "update" would be
problematic as many other RCSs use "update" as a way of picking up new
content that has become available on the remote end. So, the best
suggestion I have at this point is "refresh". So I'd be happy if
git refresh --add
git add --refresh
would provide the behavior that currently is provided by "git add",
(that is, add a new path to the index and update the content of that
path in the index from the content of the named file in the working
tree). But it would be great if "git add" without the --refresh would
add the path without updating the content.
I think you are trying to solve the wrong problem, or at least solve a
problem the wrong way. The problem is that git-diff doesn't give you
the output you expect because of the index interfering in your work
flow. And I understand that.

But the best solution is really for git-diff to have a mode where you
could display a diff between the work tree and the index, _or_ the index
and HEAD, for each file listed in the index while giving priority to the
former.

This would let you see a diff of everything that would be committed,
including new files, if you were to do commit -a. Maybe -a/--all should
be used with git-diff for such a mode by symetry with git-commit -a. (OK
-a is already taken but I doubt it is really used and it already has a
longer equivalent so changing it would not do real harm).

With this, for users acustomed to "commit -a", the natural and pretty
consistent way to see a diff for such a commit before actually
performing it would bi "diff -a". Isn't it logical?


Nicolas
Carl Worth
2006-12-22 21:57:19 UTC
Permalink
Post by Nicolas Pitre
Post by Carl Worth
So, I think what I really want here is a complete separation in the
interface between adding a path to the index and updating content into
the index.
Strangely enough I think this separation is unnecessary and redundent.
One argument I would make in favor of the separation is that the two
operations are conceptually distinct from the user point-of-view. But
that's really hard to nail down since all users have different points
of view and different conceptual models, (though I think the recent
post about similar file names and accidentally adding a file meant to
be untracked is evidence in favor of this argument).

There's a much less fuzzy, and strictly technical argument that can be
made. Right now, we document "git add" as being useful for two
purposes, ("adding new files" and adding "modified files...to the set
of changes"). These two operations can be described as:

1. Add new path to the index, and update the content

2. Update the content for an existing path

The technical argument for separating the notions of "add path" and
"update content" comes from looking at how to specify path names to
these operations, (and recursive names in particular).

By definition, the first operation, ("add new paths"), must accept
path names from the working tree as it exists in the filesystem.
Since without this operation there's no way to get paths into the
index in the first place. So, any recursive operation for this
operation should traverse the tree of files as they exist in the file
system. This is quite useful in the case of creating a new directory
in a project and wanting to add all of the files in that directory:

git add new-directory

However, the second operation ("update content") need not be defined
in terms of the tree in the filesystem, and is in fact quite useful
when it operates on the tree that exists "within" git. For example, if
I have been hacking on a feature change in a 'source' directory that's
not quite finished yet, and also a new test for that feature in a
'test' directory, (that I do consider ready), then it would be
convenient to be able to stage all the content in that directory be
similarly specifying just the directory name. For example, I'd like to
be able to do:

git update-index test

(which doesn't actually work right now). But doing "git add test"
would be wrong, since it would also add any untracked files, and I
don't want that. This "update content for known files" operation
should recurse on the tree that git knows about, and not the tree of
files in my filesystem.
Post by Nicolas Pitre
Post by Carl Worth
We've long had a command that updates content to the index, and it
takes a command-line option (--add) to allow it to first do the
necessary path addition as well.
And it is still there.
Yes, update-index still exists. But we're relegating that to
plumbing. What I'm proposing is that we should have a porcelain
command that just does the "update content for known files part" and
that merging this with something that makes files "become known" to
git for the first time is a mistake.
Post by Nicolas Pitre
The problem lies with the git-diff interface then, not git-add.
I don't think so. I'm quite convinced that the fact that "git diff"
shows the difference from the index to the working tree is correct and
can't really be changed. The issue I'm talking about here is that for
"tracked" files git currently provides a way for me to have my edits
of I can
Post by Nicolas Pitre
Post by Carl Worth
git update-index --all
git add --all
...
Post by Nicolas Pitre
There is no consistency needed between git-add and git-update-index.
The first is for users while the second is more suited for scripting
your own interface.
But it's not actually update-index that I want. I agree that it's a
plumbing thing that users shouldn't use. What I want is two different
pieces of porcelain here, each focusing one one simple task. One to
add the path to the index, and one to update content in the index for
a path that exists.
Post by Nicolas Pitre
Post by Carl Worth
git refresh --add
git add --refresh
would provide the behavior that currently is provided by "git add",
That was actually a bad idea, and I'll retract that part. Neither of
these options should exist. We already have an all-singing,
all-dancing git-update-index that can do anything we want. We really
don't need two new pieces of porcelain that also do everything
update-index does but just have different defaults.

Much better would be for "git add" and "git refresh" to each just
stick to a single task and to do it well, (git has UNIX philosophy,
right?). So "git add" should just add paths to the index, "git
refresh" should just update content for existing paths in the index,
and we don't need a lot of options for either command for users to
have to wade through.

With those simple commands, we could have nice, separate behavior for:

git add some-dir
and:
git refresh some-dir

and if someone wants the existing "add path and update content"
behavior of git add then it should be a simple matter of aliasing to
the combination of "git add" followed by "git refresh".
Post by Nicolas Pitre
I think you are trying to solve the wrong problem, or at least solve a
problem the wrong way. The problem is that git-diff doesn't give you
the output you expect because of the index interfering in your work
flow. And I understand that.
I don't think that's the right characterization. I like that "git
diff" works from the index, and I take advantage of that by
intentionally putting content into the index. The problem is that "git
add" currently forces content into the index even if I consciously do
not want it there yet. I just want a way to tell "git diff", (and
commit -a), to start looking at new files, but without staging the
current content of those files into the index.
Post by Nicolas Pitre
But the best solution is really for git-diff to have a mode where you
could display a diff between the work tree and the index, _or_ the index
and HEAD, for each file listed in the index while giving priority to the
former.
I don't understand what you are proposing here. What would this mode
display? How would it decide?
Post by Nicolas Pitre
With this, for users acustomed to "commit -a", the natural and pretty
consistent way to see a diff for such a commit before actually
performing it would bi "diff -a". Isn't it logical?
A new option ("git diff -a") doesn't help much. There's already "git
diff HEAD" and I understand what it does. The problem is having "git
diff" usually work, and then having to remember to do something else
when it doesn't do the right thing.

[Though a command-line option would have one advantage over HEAD which
is that it's easier to document command-line options than a magic
name like HEAD. This "hard to document" bug is something that affects
all of the magic names, (HEAD, ORIG_HEAD, MERGE_HEAD, etc.), and
keeps their functionality quite hidden from new users of git.]

-Carl
Nicolas Pitre
2006-12-23 05:27:16 UTC
Permalink
Post by Carl Worth
Post by Nicolas Pitre
Post by Carl Worth
So, I think what I really want here is a complete separation in the
interface between adding a path to the index and updating content into
the index.
Strangely enough I think this separation is unnecessary and redundent.
One argument I would make in favor of the separation is that the two
operations are conceptually distinct from the user point-of-view. But
that's really hard to nail down since all users have different points
of view and different conceptual models,
... and if we want to break the CVS model and give people a better
chance of ever grasping the git index concept I think they should not be
different.
Post by Carl Worth
(though I think the recent
post about similar file names and accidentally adding a file meant to
be untracked is evidence in favor of this argument).
This could be used as evidence for anything. "Oh I wanted to delete
this file but that file had a similar name and I deleted the wrong
one."
Post by Carl Worth
There's a much less fuzzy, and strictly technical argument that can be
made. Right now, we document "git add" as being useful for two
purposes, ("adding new files" and adding "modified files...to the set
of changes").
[...]
Post by Carl Worth
The technical argument for separating the notions of "add path" and
"update content" comes from looking at how to specify path names to
these operations, (and recursive names in particular).
Sometimes pure _technical_ arguments don't make good _user_ interfaces.
The "git add" changes are about _usability_, not _technicality_. It is
much easier to learn about one concept which is "you add stuff to your
commit" with no other distinction to make.
Post by Carl Worth
Yes, update-index still exists. But we're relegating that to
plumbing.
But plumbing is there for you to use with your own enhancements when
they are sophisticated enough like your workflow description seem to
imply.
Post by Carl Worth
Post by Nicolas Pitre
The problem lies with the git-diff interface then, not git-add.
I don't think so. I'm quite convinced that the fact that "git diff"
shows the difference from the index to the working tree is correct and
can't really be changed.
I'm not proposing to change existing output either.
Post by Carl Worth
Post by Nicolas Pitre
There is no consistency needed between git-add and git-update-index.
The first is for users while the second is more suited for scripting
your own interface.
But it's not actually update-index that I want. I agree that it's a
plumbing thing that users shouldn't use. What I want is two different
pieces of porcelain here, each focusing one one simple task. One to
add the path to the index, and one to update content in the index for
a path that exists.
Much better would be for "git add" and "git refresh" to each just
stick to a single task and to do it well, (git has UNIX philosophy,
right?). So "git add" should just add paths to the index, "git
refresh" should just update content for existing paths in the index,
and we don't need a lot of options for either command for users to
have to wade through.
I'm still unconvinced this is useful distinction to make in the majority
of all cases for the majority of people.
Post by Carl Worth
git add some-dir
git refresh some-dir
and if someone wants the existing "add path and update content"
behavior of git add then it should be a simple matter of aliasing to
the combination of "git add" followed by "git refresh".
I think that if you want that behavior it might be a better idea for you
to alias those behaviors with a combination of git-ls-files and
git-update-index.
Post by Carl Worth
Post by Nicolas Pitre
But the best solution is really for git-diff to have a mode where you
could display a diff between the work tree and the index, _or_ the index
and HEAD, for each file listed in the index while giving priority to the
former.
I don't understand what you are proposing here. What would this mode
display? How would it decide?
This is something that you might not need after all. but for people
using git-commit -a they might benefit from a git-diff -a that would
output the equivalent of what will be committed, including newly added
files (already in the index) and modified files (not yet in the index).
It is easy to do: for each index entry, generate a diff against the
corresponding file in the work tree, but if there is no difference then
generate the diff against HEAD. Modified files will be in the first
case while added files will be in the second case.


Nicolas
Daniel Barkalow
2006-12-24 21:38:17 UTC
Permalink
Post by Nicolas Pitre
Post by Carl Worth
Post by Nicolas Pitre
Post by Carl Worth
So, I think what I really want here is a complete separation in the
interface between adding a path to the index and updating content into
the index.
Strangely enough I think this separation is unnecessary and redundent.
One argument I would make in favor of the separation is that the two
operations are conceptually distinct from the user point-of-view. But
that's really hard to nail down since all users have different points
of view and different conceptual models,
... and if we want to break the CVS model and give people a better
chance of ever grasping the git index concept I think they should not be
different.
I don't think the misunderstanding (if there is one) of the git index
model is due to CVS. If I'm using a staging area for wrapping Christmas
presents, I may assign space to items I haven't got yet: this is where I
put the tape so I can reach it, this is where the roll of wrapping paper
goes, here is where the wrapping paper will be spread out, but I can't
spread out the wrapping paper until I have the present (it just rolls back
up), so there's nothing in the spot allocated to actual wrapping. Git
reminds me of people who have to put a trash can in their parking spaces
when their cars aren't there to keep them from being deallocated simply
because they're empty.

The allocation of empty space before anything is put in it is a
fundamental operation available in the general concept of a staging
area. Someone coming from an index-based version-control system that
doesn't lack this feature would expect to have a possible status:

# Changed but not updated:
# (use git-update-index to mark for commit)
#
# new file: new-test-file
#

(And note that it can't be CVS-damage, because "Changed but not updated"
isn't supported by CVS. This is a way in which git sort of has CVS-damage,
because the "new file" operation goes straight to "Updated but not checked
in", unlike everything else.)

-Daniel
*This .sig left intentionally blank*

Junio C Hamano
2006-12-22 05:10:51 UTC
Permalink
Post by Carl Worth
I complained about this when I first encountered git, and back then I
said what I thought I wanted was "git diff HEAD" by default. I was
totally wrong, since diff from the index is so obviously correct for
resolving a conflict. Junio even responded to my complaints by
providing a new "git status -v -a" but frankly I've never used
it.
I guess my responding to whatever you said was wasted effort,
and if you do not like "git add" this time, I should not be
surprised. That's kind of sad ;-).

Jokes aside.

I do not remember who advocated for making "git status" the
preview of "git commit" to happen. Was that also you? I wonder
how many people use this form:

git status -v path1 path2...

Because if even somebody who wanted to have "commit preview" in
"git status" does not use it for that intended purpose, I think
we can reuse the good command name for something more useful,
such as "git explain".
Post by Carl Worth
I'd really like "git diff" to be what I want more often.
Running diff with index is what I do almost all the time. I
think "more often" is different from person to person, but if
"git diff" says nothing on a file that I know I added (and you
cannot argue you do not remember it was a new file here --- you
know you added it and that is why you are complaining about not
seeing it), I'd be happy that I did not accidentally edited it
to munge what I added -- because I add a file only when it is in
a presentable, good state, in a good enough shape to take a
snapshot (not necessarily good enough to commit, though).

And it is not just limited to adding the contents of a path that
happened to be told git for the first time. Adding the contents
of a path that was known to git also happens only when it is in
a presentable good state. So running "git diff" and not seeing
what I added before is a GOOD THING.
Post by Carl Worth
So I suppose I could implement the "add path without updating content"
mv file file.tmp
touch file
git update-index --add file
mv file.tmp file
There. That gives me the result I want without breaking any git
internals, (since I'm just building a new operation on top of existing
git primitives).
Sure, what you want is "git add --no-add newfile", and I can
understand that mode of operation if you are always going to
commit with "git commit -a". Maybe we can have a config
variable that makes "commit -a" and "add --no-add" the default
for these two commands, and we do not have to change anything
else.

One minor detail I wonder about is what mode bits would you give
to that placeholder entry.
Post by Carl Worth
git update-index --all
git add --all
Wasn't it you who said "all" is ambiguous (all known to git vs
all in this directory)?
Shawn Pearce
2006-12-22 05:21:56 UTC
Permalink
Post by Junio C Hamano
And it is not just limited to adding the contents of a path that
happened to be told git for the first time. Adding the contents
of a path that was known to git also happens only when it is in
a presentable good state. So running "git diff" and not seeing
what I added before is a GOOD THING.
Yes!

Sadly it has taken me 12 months of working with Git to get
comfortable enough with that concept.

Actually it clicked once I realized that 'update-index' was actually
creating the blobs in the ODB and not 'write-tree'. Prior to that
"click" going off in my grey matter I always felt that Git screwed
up when I did:

$ vi foo.c
$ git update-index foo.c
$ git diff
# what the ? where are my changes?

I now make quite heavy use of the index even when hacking on code,
and not just during merges. But I wasn't like that just 5 months
ago...
--
Shawn.
Jakub Narebski
2006-12-22 08:24:36 UTC
Permalink
Post by Junio C Hamano
And it is not just limited to adding the contents of a path that
happened to be told git for the first time. =A0Adding the contents
of a path that was known to git also happens only when it is in
a presentable good state. =A0So running "git diff" and not seeing
what I added before is a GOOD THING.
If I remember correctly the idea behind "intent to add" was to show
only that file was added (e.g. the "new file" line from extended diff
header) in "git diff" when file was added and not modified
(and no changes to "git diff HEAD").

Although I'm not sure if this wouldn't screw some use cases which
include something like "git diff > some-temporary-file"...
--=20
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Carl Worth
2006-12-22 16:18:23 UTC
Permalink
Post by Junio C Hamano
I guess my responding to whatever you said was wasted effort,
and if you do not like "git add" this time, I should not be
surprised. That's kind of sad ;-).
I hope I'm not coming across as always just complaining. I do think
the new "git add" thing is an improvement. So if nothing else changes,
I still think git's better than it was before this recent round of
improvements.
Post by Junio C Hamano
I do not remember who advocated for making "git status" the
preview of "git commit" to happen. Was that also you? I wonder
git status -v path1 path2...
I was involved in the discussions that led to "status -v", yes. As a
new user I was surprised that "git diff" didn't give a commit preview
and you replied with the "status -v" idea. As things have turned out,
I've never used "status -v".
Post by Junio C Hamano
Sure, what you want is "git add --no-add newfile", and I can
understand that mode of operation if you are always going to
commit with "git commit -a". Maybe we can have a config
variable that makes "commit -a" and "add --no-add" the default
for these two commands, and we do not have to change anything
else.
Yes, you could add the "don't update content" as an option to git-add,
and then all that would be left would be a discussion about which
modes get the default and which require configuration options, (and
those discussions generally don't go anywhere).

But don't you see how odd the command "git add --no-add" looks? What
does it mean to add something without adding it? This is just
reinforcing my position that using "add" to mean "update content"
rather muddles things.
Post by Junio C Hamano
One minor detail I wonder about is what mode bits would you give
to that placeholder entry.
You could certainly grab them from the named file if it exists. If the
user is going to "commit -a" it won't matter much, right?
Post by Junio C Hamano
Post by Carl Worth
git update-index --all
git add --all
Wasn't it you who said "all" is ambiguous (all known to git vs
all in this directory)?
Yes. Having "--all" is ambiguous while "git add" is used for both
adding new paths to the index _and_ updating index content. But if
"git add" were restricted to just adding paths to the index as I am
suggesting, then there's no ambiguity at all.

-Carl
Nicolas Pitre
2006-12-22 17:28:46 UTC
Permalink
Post by Carl Worth
I was involved in the discussions that led to "status -v", yes. As a
new user I was surprised that "git diff" didn't give a commit preview
and you replied with the "status -v" idea. As things have turned out,
I've never used "status -v".
What about my diff -a proposal? Did you miss it?


Nicolas
Carl Worth
2006-12-22 16:55:08 UTC
Permalink
Post by Junio C Hamano
Running diff with index is what I do almost all the time.
Yes, me too. As I said, months ago I had complained about "git diff"
meaning diff from index. But I was wrong. It really is the right thing
Post by Junio C Hamano
And it is not just limited to adding the contents of a path that
happened to be told git for the first time. Adding the contents
of a path that was known to git also happens only when it is in
a presentable good state. So running "git diff" and not seeing
what I added before is a GOOD THING.
Yes. Whenever consciously using the index, being able to stash stuff
there and not see it in "git diff" is definitely a good thing.

After a thread not so long ago, someone told me privately that they
really wished they could see more examples of when using the index is
obviously a net win to the user. He mentioned that the oft-cited
"split commit along file boundaries" isn't compelling since the same
behavior can be achieved with "commit file1 file2".

So here's another example that I was using just yesterday:

I implemented an optimization and started testing it. It had the
performance characteristics I wanted, but also introduced a couple
few regressions noticed by the test suite.

So this code wasn't ready to commit, but I stashed it all into the
index. Then I went through an iterative process of fixing the
little regressions (off-by-one bugs, etc.), using "git diff" to
see _only_ the incremental fix, and then stashing the whole result
into the index again.

Then I only committed once all the regressions were fixed.

Note that in the above scenario, the command I've been proposing
recently, ("update the index with the content of all tracked files"),
would have been quite useful.

Also note that with "git commit --amend" one could get a very similar
result by simply using the HEAD commit as the staging area instead of
the index. (And with reflogs, some might like that even better.)

So yes, "git diff" showing the difference from the index is definitely
the right thing. And it's useful whenever I'm consciously using the
index to stash some content, (as in this example), or when git does
that on my behalf (as in a conflicted merge).

My point is that I'm not always interested in stashing content just
because I want to add a new path to the index. For example, let's say
I sit down with my working tree and I just want to remember what I had
been in the middle of doing. I examine the state of things with "git
diff". It doesn't show me the content of any newly-created files, but
I want to see those as well. So I'd love to be able to easily get the
index into a state where "git diff" shows me that content.

And I'm definitely not ready to stash the content of these new
files---I haven't even looked at them yet---that's what I'd like "git
diff" to help me do at this point.

Anyway, you already said you did understand this mode of operation. So
I won't explain it over and over anymore. I really just wanted to
throw out that index-staging example for people.

-Carl
Daniel Barkalow
2006-12-23 02:56:23 UTC
Permalink
Post by Junio C Hamano
Sure, what you want is "git add --no-add newfile", and I can
understand that mode of operation if you are always going to
commit with "git commit -a". Maybe we can have a config
variable that makes "commit -a" and "add --no-add" the default
for these two commands, and we do not have to change anything
else.
I think there's value to a command to add an empty space with a given name
to the staging area. If you commit without -a, I don't see any reason to
think that you couldn't want the sequence "add-empty-space <new-file>",
"modify <old-file>", "update-index <old-file>", "commit", "update-index
<new-file>", "commit". It can be useful to make sure the file isn't going
to be forgotten, but also not get it into the next commit.
Post by Junio C Hamano
One minor detail I wonder about is what mode bits would you give
to that placeholder entry.
I looked into this at one point. It should probably use 000000 for the
mode, because it shouldn't read the working directory at all (you might
actually want to add the space before creating a file at all, for
instance, and then make a symlink when you provide anything, surprising
any reasonable guess at a mode). Also, this is going to show up in the
diff listing, and all-zero SHA1 with a mode is used there for "read the
working directory".

-Daniel
*This .sig left intentionally blank*
Loading...