> How about "git ls-files -o"? doh... hadn't even heard of that command. -- Caleb Cushing --
Hi, Which is good! As ls-files is listed as plumbing. Users should not need to call ls-files, so I like your idea about adding --new, --untracked etc. to "git status" (I do not agree with others that "git status" has to stay that non-existant "git commit --dry-run"). Could you list exactly which options you want implemented? Ciao, Dscho --
Requests for stuff like that keep appearing recently (I'm to blame partially only ;) ). There are 3 issues at hand: - people are used to "svn status [-v]" like output which can include untracked as well as tracked unmodified files; there are other valid reasons why you would want that info - porc can't do it: git status can't show ignored files, doesn't use status letters, can't show files with specific status; git diff --name-status can't show ignored nor untracked files [In fact, the description of "git diff" says "files which you could add", which should include untracked files, but doesn't.] - plumb uses conflicting letters: git ls-files output conflicts with git diff --name-status output So I guess it's time for a usability effort in this area. A few questions before going about that: - I think change of existing behaviour is unavoidable (make ls-files and diff --name-status consistent). Is that something to do now or rather before 1.7? Is porc (diff) supposed to be changed or plumb (ls-files)? - How strong should the tie between git status and git commit be? Current git status is basically git commit -n, with the usual meaning of "-n" (such as for prune etc."), not with the current meaning of git commit -n, sigh... A few radical suggestions might be: 1. make ls-files and diff --name-status use compatible letters 2. rename git commit -n to git commit -b (as in bypass), make git commit -n do what's expected ("--dry-run", n as in duNNo yet) 3. rename git status to git commit -n 4. make git status generate git diff --name-status like output (3+4)'. make git status -l generate git diff --name-status like output (l as in status Letter) as an alternative to 3+4 Michael --
> Could you list exactly which options you want implemented? --new --untracked --modified I believe there are other states as well that I'm not thinking of off the top of my head. Those should probably be included as well. another all way over my head -- Caleb Cushing --
On Thu, Oct 9, 2008 at 9:12 AM, Michael J Gruber <git@drmicha.warpmail.net> wrote: Ouch. Please not -b. I guess I need to get my other suggestions I'd really prefer to be able to get staged vs. unstaged information out of status. And the single-letter output, like what cvs/svn/hg have, is less descriptive here. (Sure, git status could use some cleanup IMO, but a word instead of a letter for modification status is a usability improvement in git over those other systems for new VCS That seems nicer. And another radical suggestion (wasn't this brought up before too?): 5. Allow limiting the status output to a set of paths. diff, log, add, grep, etc. can all take a subdirectory name and limit their operation to files recursively underneath that path, but git status doesn't do so when you run 'git status DIR'. I know why it currently behaves as it does, but it sure seems like unnecessary UI inconsistency. Just my $0.02, Elijah --
Hi, ls-files and diff (at least partially) are plumbing. Breaking backwards compatibility in these is out of the question. Ciao, Dscho --
A week or two ago I came across yet another git-status annoyance: it
needs write access to the repository to run (I was helping somebody with
a task on a shared box, and I wanted to run status in their repository
using my account).
I considered submitting a patch to fix this, but I think it is really
more fundamental. I use status to get an overview of what's going on in
a repo, but it is intimately related to a potential commit.
And this bleeds into other areas, too. Why should the "what's going on
in this repo" command prefix all lines with "#"? We would have more
freedom to change the format if it weren't required to be a comment
line in a commit message.
So I think it is probably reasonable to think about a new command (which
would not be called status) that shows this information. What do people
want to see? And in what format? Some things I would want or have seen
requested are:
- staged and unstaged changes in --name-status format
- files without changes (with a -v flag).
- untracked files
- current branch / detached HEAD (with relationship to tracked branch,
if any)
And maybe after hashing it out, it turns out it's not that different
from "git status" and we should just stick with that. But I would be
I don't think you would want to just change the default; you would
probably add a new option to ls-files to use the --name-status letters,
I think the theoretical tool I mentioned would benefit from breaking
this connection. But I don't know whether it is prudent to take the
"status" name in doing so. Even if we decided to do so, it would
probably happen something like:
1. Introduce git-wtf, a new status-like tool. Deprecate git-status in
its current form.
2. Wait a really long time.
3. Rename git-wtf to git-status.
So either way, the first step is an alternative replacement command.
-Peff
--
I was going to suggest the same. "git st" for people who come from "svn st" so that "git status" can be kept as traditional "preview of 'git commit'". And just make it mimic whatever folks accustomed to "svn st" would expect, modulo we would need two status letters to signal difference between (HEAD, index), and (index, worktree). Perhaps three if you want to show difference between (HEAD, worktree) while at it. And no, I have not seen any argument good enough to change ls-files nor diff-$lowlevel output and break people's existing scripts. --
I remember a long time ago you started on a parallel diff walker that could diff the working tree, the index, and a tree at once. Do you remember the issues with it? I think that would be the right tool here to show each file only once, but with multiple status flags. Something like: A M foo to show that "foo" has been added since the last commit, but there are modifications in the working tree that have not yet been staged. -Peff --
One thing to keep in mind is what to do when you would want to detect
renames. The parallel walk would be Ok but between HEAD and index there
could be renames involved, and at that point it would get quite tricky.
Once the index is in-core, I think it hurts us much to walk HEAD vs index
and index vs working tree in separate passes.
I think it is perfectly fine to run the diff-index first, and keep the
result from it in a string_list, and then run "diff-files" and annotate
the string_list with the output from it.
Something like...
struct git_st_data {
const char *head_path;
char head_to_index_status;
char index_to_worktree_status;
};
static int cmp_head_path(const void *a_, const void *b_)
{
struct git_st_data *a = (struct git_st_data *)a_;
struct git_st_data *b = (struct git_st_data *)b_;
return strcmp(a->head_path, b->head_path);
}
static void git_st_inspect_index_cb(struct diff_queue_struct *q,
struct diff_options *opts, void *data)
{
struct string_list *git_st_list = data;
int i;
for (i = 0; i < q->nr; i++) {
struct git_st_data *d;
struct string_list_item *e;
struct diff_filepair *fp = &q->queue[i];
d = xcalloc(1, sizeof(*d));
d->head_path = xstrdup(fp->one->path);
e = string_list_insert(fp->two->path, git_st_list);
e->util = d;
d->head_to_index_status = fp->status;
}
}
static void git_st_inspect_file_cb(struct diff_queue_struct *q,
struct diff_options *opts, void *data)
{
struct string_list *git_st_list = data;
int i;
for (i = 0; i < q->nr; i++) {
struct git_st_data *d;
struct string_list_item *e;
struct diff_filepair *fp = &q->queue[i];
e = string_list_lookup(fp->one->path, git_st_list);
if (!e)
die("Oops -- shouldn't ...Assuming you meant "I _don't_ think it hurts us much" then OK, that makes sense. I was just thinking it would be more elegant than holding each list in memory and comparing, but really that is not all that Thanks, I think that is a sane direction to go in. And I agree that any solution should be totally split from the actual output format, so we can reuse it in "git status" if desired. However, now that Shawn has revealed the existence of his super-secret status replacement, I am going to wait to see that before moving any further. :) -Peff --
I'll talk about it more at the GitTogether. I expect the sources to be published and available for download between now and then. I'll post a pointer to it here on the Git ML once the sources go live. So you shouldn't have to wait too much longer. But as I said, it really is just a trivial redisplay of what diff-files and diff-index produces. Anyone could probably code up the same result in 15 minutes in Perl or Python; or slightly longer in C. -- Shawn. --
Because I was bored thinking about what to talk about in Gittogether and
lacked enough concentration to do anything productive, I did this that:
(1) introduces the "find and summarize changes in a single string list"
infrastructure;
(2) rewrites wt_status_print_{updated,changed} to use it; and
(3) adds "git shortstatus" that does not take any parameter (so it is not
about "preview of commit with the same paths arguments" anymore) to
give the status in:
XsssY PATH1 -> PATH2
format, where X is the diff status between HEAD and the index, sss is the
rename/copy score of the change (if X is rename or copy --- otherwise
it is blank), Y is the diff status between the index and the worktree.
PATH1 is the path in the HEAD, and " -> PATH2" part is shown only when
PATH1 corresponds to a different path in the index/worktree.
This was done primarily for fun and killing-time, so I won't be committing
it to my tree, but it seems to pass all the existing tests.
If you apply this patch with "git apply" (no --index) and then
$ git mv COPYING RENAMING
then you would see:
$ ./git-shortstatus
M Makefile
R100 COPYING -> RENAMING
M builtin-commit.c
M builtin-revert.c
M builtin.h
M git.c
M wt-status.c
M wt-status.h
It is very much welcomed if somebody wants to build on top of this. A few
obvious things, aside from bikeshedding to drop the score value (which I
just did as a sanity check measure and for nothing else --- I won't feel
hurt if we lost that field from the output) and such are:
* We can also rewrite wt_status_print_untracked() using the collected
data by making the collector pay attention to untracked files quite
easily;
* I did not bouther touching wt_status_print_initial() but I think it
should be straightforward to produce its output from the collected
data, as the collector ...I just skimmed the code, but it looks reasonably done. I don't have time to work on this at the moment, but I think you have done most of the work that requires a lot of git knowledge. Maybe somebody new can pick this up as a nice starter project to get more involved in git. -Peff --
I have a tool that I'll be open-sourcing later this year, but it does something like that: project foo/ branch master Am foo M- bar R- orig => dest ( 95%) Line coloring is red on lines with unstaged stuff in the working directory (3rd column, lower case letters) and green on lines that are fully staged (3rd column is a '-'). The tool is in Python, but I'm just scraping the output of `diff-index -M --cached HEAD` and diff-files to get that display. The status letters are exactly those given out by diff-index/diff-files, but the diff-files output is lowercased. Scott Chacon has seen the tool output and likes it; there's a tech talk that will be posted on YouTube soon where he and I are sort of talking about it. Sorry I can't say too much more about it yet. But I'm trying to say that both Scott and I like a denser display like this. -- Shawn. --
I like what I saw, and I think a "denser" format is what I was trying to suggest in my earlier message (I just didn't think of nearly as clear a word). So count me in for your list of people who would like to see this thing (and would even work on doing a pure-C version). -Peff --
One of the first aliases I set up when I started using git was "st" for status, and I'd imagine that's a pretty common thing for people coming from other SCMs like svn and cvs. But I very quickly became used to git's notion of what "status" means and I wouldn't want "git st" to start giving me a different behaviour. I think if you're introducing a different command then you should make sure it doesn't happen to be an abbreviation of an existing one. It would be better to give it some other name (info, foo, whatever). If svn people then want to make an "st" alias pointing to it they're free to do so. Just my 2c. Cheers, Wincent --
In Subversion and Bazaar "info" command gives mostly information about the repository itself. They don't talk about individual files at all. "status" is the command (also in Mercurial) for getting information about the current state of files in the tree. I think it would be really sad if "git status" can't be extended to match people's needs. I don't like the idea of a new name for such status command. It's a kind of "why git people always invent new names for familiar commands?" thing. --
Well, the solution is fairly simple then. Just make it configurable and set it in your ~/.gitconfig. It's not my itch to scratch though. I loathe the sparse output from cvs/svn/whatnot and would be just as happy if I never had to look at it again. I can understand its usefulness for scripting, but 'git status' is porcelain so for that purpose it really belongs somewhere else. -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 --
BTW, in case anybody is interested, here is the patch. Like I said, I
think we are better off with an alternative to "status", but maybe this
is useful to somebody anyway.
---
diff --git a/builtin-commit.c b/builtin-commit.c
index b01ad9f..8951364 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -217,7 +217,8 @@ static void create_base_index(void)
exit(128); /* We've already reported the error, finish dying */
}
-static char *prepare_index(int argc, const char **argv, const char *prefix)
+static char *prepare_index(int argc, const char **argv, const char *prefix,
+ int status_only)
{
int fd;
struct string_list partial;
@@ -270,7 +271,13 @@ static char *prepare_index(int argc, const char **argv, const char *prefix)
* We still need to refresh the index here.
*/
if (!pathspec || !*pathspec) {
- fd = hold_locked_index(&index_lock, 1);
+ fd = hold_locked_index(&index_lock, 0);
+ if (fd < 0) {
+ if (!status_only)
+ die("unable to lock index: %s",
+ strerror(errno));
+ return get_index_file();
+ }
refresh_cache(REFRESH_QUIET);
if (write_cache(fd, active_cache, active_nr) ||
commit_locked_index(&index_lock))
@@ -869,7 +876,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
argc = parse_and_validate_options(argc, argv, builtin_status_usage, prefix);
- index_file = prepare_index(argc, argv, prefix);
+ index_file = prepare_index(argc, argv, prefix, 1);
commitable = run_status(stdout, index_file, prefix, 0);
@@ -953,7 +960,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
argc = parse_and_validate_options(argc, argv, builtin_commit_usage, prefix);
- index_file = prepare_index(argc, argv, prefix);
+ index_file = prepare_index(argc, argv, prefix, 0);
/* Set up everything for writing the commit object. This includes
running hooks, writing the trees, and interacting with the user. */
--
You would probably want to refresh_cache() here even if you are not going to write the resulting index out, so that you won't show the stat-only differences to the end user. Other than that, I think this is a good change. --
That is a good point. However, I think this change is still not a good one, because it is only halfway there. It makes "git status" work, but not "git status path", which wants to write out the resulting cache. I don't know what complications are involved with making that work. Probably there is a way, but I haven't looked too closely, as I think a better path forward is a new tool that is not so closely tied to commit. -Peff --
Johannes> Which is good! As ls-files is listed as plumbing. Johannes> Users should not need to call ls-files, That is a bug, then. ls-files is one of the more important user-level commands in git. It is vastly more efficient than find(1) or a --recursive call to grep(1). Searching through a repository to find which file(s) define or use some function, struct, class or similar is a common occurance. Or to find which dir(s) contain(s) file(s) matching a given regexp. Or a number of other uses. (Tags might be useful if one does a lot of searching in a given repo, but grep is quicker for infrequent searches and the tags utils do not support all file types.) ls-files is definitely dual-use. -JimC -- James Cloos <cloos@jhcloos.com> OpenPGP: 1024D/ED7DAEA6 --
How about using "git grep" then? No need for ls-files... -- Shawn. --
I use git-grep for searching the contents of files in the repo, but it seems to me that git ls-files is necessary for quickly parsing the --
Shawn> How about using "git grep" then? No need for ls-files... I often filter the list of files before passing them to xargs, so git grep helps for some use cases, but not all. Also, (at least as of 1.6.0.2.307.gc427), git grep does not support -P (Perl compatible regexps) or --color. -JimC -- James Cloos <cloos@jhcloos.com> OpenPGP: 1024D/ED7DAEA6 --
