Re: Cleaning up git user-interface warts

12 messages, 5 authors, 2016-08-11 · open the first message on its own page

Re: Cleaning up git user-interface warts

From: Junio C Hamano <hidden>
Date: 2016-08-11 19:25:03

Han-Wen Nienhuys [off-list ref] writes:

You claim it is _an interface_ issue but it is not.
With GIT, this is what happens

[hanwen@haring y]$ git pull ../x
fatal: Needed a single revision
Pulling into a black hole?
You asked it to fetch from the neighbour repository and merge it
into your current branch which does not exist (I presume that
you omitted to describe what you did in directory y/ and I am
assuming you did "mkdir y && cd y && git initdb" and nothing
else).  You are pulling into a black hole.
[hanwen@haring y]$ git fetch ../x
...
[hanwen@haring y]$ git checkout
You fetched without telling it in which tracking branch to store
what you fetched, and as a result your HEAD is not updated, so
your current branch still does not exist.  A failure from
checking out nothingness is not an interface issue; expectation
for it to work is a concept level issue.
[hanwen@haring y]$ git branch master
fatal: Needed a single revision
You are not at any commit yet and you try to create a branch?

Of course, the "right" (in some sense of the word) thing is to
do "git clone x y" in the parent directory, without creating y
upfront.

If you have an empty y to begin with, then you can do this:

	$ git fetch ../x :origin
        $ git reset --hard origin

which would mirror a part of what "git clone" would have done
for you.  It copies from the other repository, stores the tip in
your tracking branch called "origin", and make your HEAD to be
the same as origin.  After these two commands, you would have
two branches, origin and master, and you will be on master.

You can name 'origin' any way you want.  You might want to name
it 'x' to make it clear (to yourself) that it is used to track
what will happen in the neighboring repository 'x'.  Also, you
would most likely be fetching and merging from the same ../x
from now on, so it might be handy to set up the remotes for it:

	$ cat >.git/remotes/x <<EOF
        URL: ../x
        Pull: master:origin
	EOF

Then subsequent work of yours would be done on 'master' branch
(you have only two branches, and origin is a tracking branch so
you will never make commits on it, which means the above is a
logical consequence), and from time to time you would sync with
whoever is working in ../x

	$ git pull x

Here, 'x' is just a shorthand which looks up the URL: and Pull: line
through .git/remotes/x.  If your .git/remotes/ file was named origin
(not x), you could even have written:

	$ git pull

because pull defaults to 'origin' (without any other configuration).
quoted
Let's face it, you could just alias "merge" to "pull", and it
wouldn't really change ANYTHING.
I don't want ANYTHING to really change, I just want a sane interface to it.
I agree that you do not want to change anything.  You just
needed a bit of handholding, because you deviated from the
cookbook usage, to correct your course.


[PATCH for "next"] pretty-formats: add 'format:<string>'

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:42:56

With this patch,

$ git show -s \
	--pretty=format:'  Ze komit %h woss%n  dunn buy ze great %an'

shows something like

  Ze komit 04c5c88 woss
  dunn buy ze great Junio C Hamano

The supported placeholders are:

	'%H': commit hash
	'%h': abbreviated commit hash
	'%T': tree hash
	'%t': abbreviated tree hash
	'%P': parent hashes
	'%p': abbreviated parent hashes
	'%an': author name
	'%ae': author email
	'%ad': author date
	'%aD': author date, RFC2822 style
	'%ar': author date, relative
	'%at': author date, UNIX timestamp
	'%cn': committer name
	'%ce': committer email
	'%cd': committer date
	'%cD': committer date, RFC2822 style
	'%cr': committer date, relative
	'%ct': committer date, UNIX timestamp
	'%e': encoding
	'%s': subject
	'%b': body
	'%Cred': switch color to red
	'%Cgreen': switch color to green
	'%Cblue': switch color to blue
	'%Creset': reset color
	'%n': newline

Signed-off-by: Johannes Schindelin <redacted>
---

	On Fri, 24 Nov 2006, Han-Wen Nienhuys wrote:

	> The recently posted patch documenting is an improvement, but why 
	> not add an option so you can do
	> 
	>   --format 'committer %c\nauthor %a\n'
	>   
	> this catches all combinations, and is easier for scripting.

	So, I overcame my laziness after 91 days...

	Of course, this is not as efficient as it could be: it _will_ get 
	_all_ variables from the commit, even if not needed. However, I 
	don't think that it matters in reality.

	BTW I have not found any implementation of xstrndup(), so I let it 
	be static.

 Documentation/pretty-formats.txt |   44 +++++++++
 commit.c                         |  195 ++++++++++++++++++++++++++++++++++++++
 commit.h                         |    1 +
 log-tree.c                       |    2 +-
 4 files changed, 241 insertions(+), 1 deletions(-)
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index fb0b0b9..2fe6c31 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -77,9 +77,53 @@ displayed in full, regardless of whether --abbrev or
 true parent commits, without taking grafts nor history
 simplification into account.
 
+	* 'format:'
++
+The 'format:' format allows you to specify which information
+you want to show. It works a little bit like printf format,
+with the notable exception that you get a newline with '%n'
+instead of '\n'.
+
+E.g, 'format:"The author of %h was %an, %ar%nThe title was >>%s<<"'
+would show something like this:
+
+The author of fe6e0ee was Junio C Hamano, 23 hours ago
+The title was >>t4119: test autocomputing -p<n> for traditional diff input.<<
+
+The placeholders are:
+
+- '%H': commit hash
+- '%h': abbreviated commit hash
+- '%T': tree hash
+- '%t': abbreviated tree hash
+- '%P': parent hashes
+- '%p': abbreviated parent hashes
+- '%an': author name
+- '%ae': author email
+- '%ad': author date
+- '%aD': author date, RFC2822 style
+- '%ar': author date, relative
+- '%at': author date, UNIX timestamp
+- '%cn': committer name
+- '%ce': committer email
+- '%cd': committer date
+- '%cD': committer date, RFC2822 style
+- '%cr': committer date, relative
+- '%ct': committer date, UNIX timestamp
+- '%e': encoding
+- '%s': subject
+- '%b': body
+- '%Cred': switch color to red
+- '%Cgreen': switch color to green
+- '%Cblue': switch color to blue
+- '%Creset': reset color
+- '%n': newline
+
+
 --encoding[=<encoding>]::
 	The commit objects record the encoding used for the log message
 	in their encoding header; this option can be used to tell the
 	command to re-code the commit log message in the encoding
 	preferred by the user.  For non plumbing commands this
 	defaults to UTF-8.
+
diff --git a/commit.c b/commit.c
index 8d279b0..a97aef3 100644
--- a/commit.c
+++ b/commit.c
@@ -3,6 +3,7 @@
 #include "commit.h"
 #include "pkt-line.h"
 #include "utf8.h"
+#include "interpolate.h"
 
 int save_commit_buffer = 1;
 
@@ -36,8 +37,11 @@ struct cmt_fmt_map {
 	{ "full",	5,	CMIT_FMT_FULL },
 	{ "fuller",	5,	CMIT_FMT_FULLER },
 	{ "oneline",	1,	CMIT_FMT_ONELINE },
+	{ "format:",	7,	CMIT_FMT_USERFORMAT},
 };
 
+static char *user_format;
+
 enum cmit_fmt get_commit_format(const char *arg)
 {
 	int i;
@@ -46,6 +50,12 @@ enum cmit_fmt get_commit_format(const char *arg)
 		return CMIT_FMT_DEFAULT;
 	if (*arg == '=')
 		arg++;
+	if (!prefixcmp(arg, "format:")) {
+		if (user_format)
+			free(user_format);
+		user_format = xstrdup(arg + 7);
+		return CMIT_FMT_USERFORMAT;
+	}
 	for (i = 0; i < ARRAY_SIZE(cmt_fmts); i++) {
 		if (!strncmp(arg, cmt_fmts[i].n, cmt_fmts[i].cmp_len) &&
 		    !strncmp(arg, cmt_fmts[i].n, strlen(arg)))
@@ -710,6 +720,188 @@ static char *logmsg_reencode(const struct commit *commit,
 	return out;
 }
 
+static char *xstrndup(const char *text, int len)
+{
+	char *result = xmalloc(len + 1);
+	memcpy(result, text, len);
+	result[len] = '\0';
+	return result;
+}
+
+static void fill_person(struct interp *table, const char *msg, int len)
+{
+	int start, end, tz = 0;
+	unsigned long date;
+	char *ep;
+
+	/* parse name */
+	for (end = 0; end < len && msg[end] != '<'; end++)
+		; /* do nothing */
+	start = end + 1;
+	while (end > 0 && isspace(msg[end - 1]))
+		end--;
+	table[0].value = xstrndup(msg, end);
+
+	if (start >= len)
+		return;
+
+	/* parse email */
+	for (end = start + 1; end < len && msg[end] != '>'; end++)
+		; /* do nothing */
+
+	if (end >= len)
+		return;
+
+	table[1].value = xstrndup(msg + start, end - start);
+
+	/* parse date */
+	for (start = end + 1; start < len && isspace(msg[start]); start++)
+		; /* do nothing */
+	if (start >= len)
+		return;
+	date = strtoul(msg + start, &ep, 10);
+	if (msg + start == ep)
+		return;
+
+	table[5].value = xstrndup(msg + start, ep - msg + start);
+
+	/* parse tz */
+	for (start = ep - msg + 1; start < len && isspace(msg[start]); start++)
+		; /* do nothing */
+	if (start + 1 < len) {
+		tz = strtoul(msg + start + 1, NULL, 10);
+		if (msg[start] == '-')
+			tz = -tz;
+	}
+
+	interp_set_entry(table, 2, show_date(date, tz, 0));
+	interp_set_entry(table, 3, show_rfc2822_date(date, tz));
+	interp_set_entry(table, 4, show_date(date, tz, 1));
+}
+
+static long format_commit_message(const struct commit *commit,
+		const char *msg, char *buf, unsigned long space)
+{
+	struct interp table[] = {
+		{ "%H" },	/* commit hash */
+		{ "%h" },	/* abbreviated commit hash */
+		{ "%T" },	/* tree hash */
+		{ "%t" },	/* abbreviated tree hash */
+		{ "%P" },	/* parent hashes */
+		{ "%p" },	/* abbreviated parent hashes */
+		{ "%an" },	/* author name */
+		{ "%ae" },	/* author email */
+		{ "%ad" },	/* author date */
+		{ "%aD" },	/* author date, RFC2822 style */
+		{ "%ar" },	/* author date, relative */
+		{ "%at" },	/* author date, UNIX timestamp */
+		{ "%cn" },	/* committer name */
+		{ "%ce" },	/* committer email */
+		{ "%cd" },	/* committer date */
+		{ "%cD" },	/* committer date, RFC2822 style */
+		{ "%cr" },	/* committer date, relative */
+		{ "%ct" },	/* committer date, UNIX timestamp */
+		{ "%e" },	/* encoding */
+		{ "%s" },	/* subject */
+		{ "%b" },	/* body */
+		{ "%Cred" },	/* red */
+		{ "%Cgreen" },	/* green */
+		{ "%Cblue" },	/* blue */
+		{ "%Creset" },	/* reset color */
+		{ "%n" }	/* newline */
+	};
+	enum interp_index {
+		IHASH = 0, IHASH_ABBREV,
+		ITREE, ITREE_ABBREV,
+		IPARENTS, IPARENTS_ABBREV,
+		IAUTHOR_NAME, IAUTHOR_EMAIL,
+		IAUTHOR_DATE, IAUTHOR_DATE_RFC2822, IAUTHOR_DATE_RELATIVE,
+		IAUTHOR_TIMESTAMP,
+		ICOMMITTER_NAME, ICOMMITTER_EMAIL,
+		ICOMMITTER_DATE, ICOMMITTER_DATE_RFC2822,
+		ICOMMITTER_DATE_RELATIVE, ICOMMITTER_TIMESTAMP,
+		IENCODING,
+		ISUBJECT,
+		IBODY,
+		IRED, IGREEN, IBLUE, IRESET_COLOR,
+		INEWLINE
+	};
+	struct commit_list *p;
+	char parents[1024];
+	int i;
+	enum { HEADER, SUBJECT, BODY } state;
+
+	if (INEWLINE + 1 != ARRAY_SIZE(table))
+		die("invalid interp table!");
+
+	/* these are independent of the commit */
+	interp_set_entry(table, IRED, "\033[31m");
+	interp_set_entry(table, IGREEN, "\033[32m");
+	interp_set_entry(table, IBLUE, "\033[34m");
+	interp_set_entry(table, IRESET_COLOR, "\033[m");
+	interp_set_entry(table, INEWLINE, "\n");
+
+	/* these depend on the commit */
+	if (!commit->object.parsed)
+		parse_object(commit->object.sha1);
+	interp_set_entry(table, IHASH, sha1_to_hex(commit->object.sha1));
+	interp_set_entry(table, IHASH_ABBREV,
+			find_unique_abbrev(commit->object.sha1,
+				DEFAULT_ABBREV));
+	interp_set_entry(table, ITREE, sha1_to_hex(commit->tree->object.sha1));
+	interp_set_entry(table, ITREE_ABBREV,
+			find_unique_abbrev(commit->tree->object.sha1,
+				DEFAULT_ABBREV));
+	for (i = 0, p = commit->parents;
+			p && i < sizeof(parents) - 1;
+			p = p->next)
+		i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ",
+			sha1_to_hex(p->item->object.sha1));
+	interp_set_entry(table, IPARENTS, parents);
+	for (i = 0, p = commit->parents;
+			p && i < sizeof(parents) - 1;
+			p = p->next)
+		i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ",
+			find_unique_abbrev(p->item->object.sha1,
+				DEFAULT_ABBREV));
+	interp_set_entry(table, IPARENTS_ABBREV, parents);
+
+	for (i = 0, state = HEADER; msg[i] && state < BODY; i++) {
+		int eol;
+		for (eol = i; msg[eol] && msg[eol] != '\n'; eol++)
+			; /* do nothing */
+
+		if (state == SUBJECT) {
+			table[ISUBJECT].value = xstrndup(msg + i, eol - i);
+			i = eol;
+		}
+		if (i == eol) {
+			state++;
+			/* strip empty lines */
+			while (msg[eol + 1] == '\n')
+				eol++;
+		} else if (!prefixcmp(msg + i, "author "))
+			fill_person(table + IAUTHOR_NAME,
+					msg + i + 7, eol - i - 7);
+		else if (!prefixcmp(msg + i, "committer "))
+			fill_person(table + ICOMMITTER_NAME,
+					msg + i + 10, eol - i - 10);
+		else if (!prefixcmp(msg + i, "encoding "))
+			table[IENCODING].value = xstrndup(msg + i, eol - i);
+		i = eol;
+	}
+	if (msg[i])
+		table[IBODY].value = xstrdup(msg + i);
+	for (i = 0; i < ARRAY_SIZE(table); i++)
+		if (!table[i].value)
+			interp_set_entry(table, i, "<unknown>");
+
+	interpolate(buf, space, user_format, table, ARRAY_SIZE(table));
+	interp_clear_table(table, ARRAY_SIZE(table));
+
+	return strlen(buf);
+}
+
 unsigned long pretty_print_commit(enum cmit_fmt fmt,
 				  const struct commit *commit,
 				  unsigned long len,
@@ -727,6 +919,9 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
 	char *reencoded;
 	char *encoding;
 
+	if (fmt == CMIT_FMT_USERFORMAT)
+		return format_commit_message(commit, msg, buf, space);
+
 	encoding = (git_log_output_encoding
 		    ? git_log_output_encoding
 		    : git_commit_encoding);
diff --git a/commit.h b/commit.h
index c737444..83507a0 100644
--- a/commit.h
+++ b/commit.h
@@ -47,6 +47,7 @@ enum cmit_fmt {
 	CMIT_FMT_FULLER,
 	CMIT_FMT_ONELINE,
 	CMIT_FMT_EMAIL,
+	CMIT_FMT_USERFORMAT,
 
 	CMIT_FMT_UNSPECIFIED,
 };
diff --git a/log-tree.c b/log-tree.c
index ac86194..6ce239d 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -211,7 +211,7 @@ void show_log(struct rev_info *opt, const char *sep)
 				 sha1, sha1);
 			opt->diffopt.stat_sep = buffer;
 		}
-	} else {
+	} else if (opt->commit_format != CMIT_FMT_USERFORMAT) {
 		fputs(diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT),
 		      stdout);
 		if (opt->commit_format != CMIT_FMT_ONELINE)
-- 
1.5.0.1.620.gac8f

Re: [PATCH for "next"] pretty-formats: add 'format:<string>'

From: Han-Wen Nienhuys <hidden>
Date: 2016-06-15 22:42:56

Johannes Schindelin escreveu:
With this patch,

$ git show -s \
	--pretty=format:'  Ze komit %h woss%n  dunn buy ze great %an'

shows something like

  Ze komit 04c5c88 woss
  dunn buy ze great Junio C Hamano

The supported placeholders are:
nitpick:

  \n

for newline would be nice. Similar for backslash, formfeed, alarm, etc.

 

-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

Re: [PATCH for "next"] pretty-formats: add 'format:<string>'

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:42:56

Hi,

On Fri, 23 Feb 2007, Han-Wen Nienhuys wrote:
nitpick:

  \n

for newline would be nice. Similar for backslash, formfeed, alarm, etc.
Yes, I thought about that. But it would change behaviour (even if I don't 
think it would do serious damage; the only user of interpolate.[ch] I saw 
is git-daemon, and that does not need \n, I guess).

Besides, "%n" is

- more consistent,
- date(1) does it the same way, and
- you can put BS, FF, AL, etc. into the format string before passing 
  it as an option to git; git does not have to help you there.

Ciao,
Dscho

Re: [PATCH for "next"] pretty-formats: add 'format:<string>'

From: Robin Rosenberg <hidden>
Date: 2016-06-15 22:42:56

fredag 23 februari 2007 02:07 skrev Johannes Schindelin:
Hi,

On Fri, 23 Feb 2007, Han-Wen Nienhuys wrote:
quoted
nitpick:

  \n

for newline would be nice. Similar for backslash, formfeed, alarm, etc.
Yes, I thought about that. But it would change behaviour (even if I don't 
think it would do serious damage; the only user of interpolate.[ch] I saw 
is git-daemon, and that does not need \n, I guess).
Other tools that come to mind, rpm and clearcase use \n vfor newline in the
format argument, which is good because I can guess that even without looking 
at the documentation. %n I'd guess would be for a number of some kind, e..g.
the ordinal number of the commit listed (in subset and order of the listed commits)
Besides, "%n" is

- more consistent,
with...?
- date(1) does it the same way, and
Ok, I learnt something. Never fi
- you can put BS, FF, AL, etc. into the format string before passing 
  it as an option to git; git does not have to help you there.
They are hard to type in shells and even harder in gui's.

-- robin

Re: [PATCH for "next"] pretty-formats: add 'format:<string>'

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:42:56

Hi,

On Fri, 23 Feb 2007, Robin Rosenberg wrote:
fredag 23 februari 2007 02:07 skrev Johannes Schindelin:
quoted
On Fri, 23 Feb 2007, Han-Wen Nienhuys wrote:
quoted
nitpick:

  \n

for newline would be nice. Similar for backslash, formfeed, alarm, 
etc.
Yes, I thought about that. But it would change behaviour (even if I 
don't think it would do serious damage; the only user of 
interpolate.[ch] I saw is git-daemon, and that does not need \n, I 
guess).
Other tools that come to mind, rpm and clearcase use \n vfor newline in 
the format argument, which is good because I can guess that even without 
looking at the documentation. %n I'd guess would be for a number of some 
kind, e..g. the ordinal number of the commit listed (in subset and order 
of the listed commits)
Okay. Patch?
quoted
Besides, "%n" is

- more consistent,
with...?
... itself? Why should not _one_ escape character be enough?
quoted
- you can put BS, FF, AL, etc. into the format string before passing
  it as an option to git; git does not have to help you there.
They are hard to type in shells and even harder in gui's.
You would not do that all that often, but rather write a script. Even the 
config format allows for inclusion of special characters, so aliases 
should be fine.

Ciao,
Dscho

Re: Cleaning up git user-interface warts

From: Jakub Narebski <hidden>
Date: 2016-08-11 19:29:34

Han-Wen Nienhuys wrote:
Jakub Narebski escreveu:
quoted
quoted
  - --pretty option with wholly uninformative options full, medium, 
short, raw.  It's not even documented what each option does.
And 'oneline' and undocumented 'email'. True, git lacks documentation (and
this one of main complaints in git survey).
The recently posted patch documenting is an improvement, but why not
add an option so you can do

  --format 'committer %c\nauthor %a\n'
  
this catches all combinations, and is easier for scripting.

Right now, I have some scripts that have to munge log output with
regular expressions to strip out the "author:"  prefixes.
If we ever implemented this, I'd rather to separate what is now of format
parsing in git-for-each-ref (although I'd like to make it more like rpm's
--query-format argument, with %-n{header}, %[array] etc.) into separate
module, and reuse it for git-log and friends --pretty/--format handling.
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

Re: Cleaning up git user-interface warts

From: Johannes Schindelin <hidden>
Date: 2016-08-11 19:48:54

Hi,

On Fri, 24 Nov 2006, Han-Wen Nienhuys wrote:
The recently posted patch documenting is an improvement, but why not
add an option so you can do

  --format 'committer %c\nauthor %a\n'
  
this catches all combinations, and is easier for scripting.
Yes, it would be easier for scripting, and it would probably be relatively 
easy, what with the addition of interpolate.[ch] to git. However, it is 
work, and I am lazy.

What information would you like, anyway? IOW can you provide me with a 
list like this:

%c	committer
%a	author
%d	committer_date
...

Ciao,
Dscho

Re: Cleaning up git user-interface warts

From: Han-Wen Nienhuys <hidden>
Date: 2016-08-11 20:02:36

Jakub Narebski escreveu:
quoted
  - --pretty option with wholly uninformative options full, medium, 
short, raw.  It's not even documented what each option does.
And 'oneline' and undocumented 'email'. True, git lacks documentation (and
this one of main complaints in git survey).
The recently posted patch documenting is an improvement, but why not
add an option so you can do

  --format 'committer %c\nauthor %a\n'
  
this catches all combinations, and is easier for scripting.

Right now, I have some scripts that have to munge log output with
regular expressions to strip out the "author:"  prefixes.


-- 
 Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

Re: Cleaning up git user-interface warts

From: Jakub Narebski <hidden>
Date: 2016-08-11 20:02:59

Han-Wen Nienhuys wrote:
As another example:  annoyances regarding program invocation

  - option handling: -x -f -z != -xfz , "--max-count 1" doesn't work, 
but needs an '='
That's true, and the probable cause is that git tries to first, avoid
dependency on options parsers like getopt/getopt_long/argp or popt for
commands in C, getopt for commands in shell, Getopt::Std/Getopt::Long for
commands in Perl, and something for commands in Python (if there are any
left); second, existing options parsers do not deal (I think) with
distinction between arguments to wrapper and arguments to command, '--' to
separate revisions from pathnames not options from arguments, and the whole
revisions and revision list specifying syntax (where "a --not b" is not
equivalent to "--not a b").

That said, perhaps we should craft our own options parsing (or modify
existing one)...
  - git --help lists an unordered set, which is too long scan quickly. 
It is one page of alphabetically ordered commands.

git(7) gives whole list of commands, divided into categories, by the way.
I'd expect that list to either contain everything or the minimum set for 
daily use. I.e. the set introduced in a first tutorial.  Why are merge, 
prune, verify-tag there?

Try "bzr help" for comparison.
I wonder why "repack" isn't there, if "prune" is.
  - --pretty option with wholly uninformative options full, medium, 
short, raw.  It's not even documented what each option does.
And 'oneline' and undocumented 'email'. True, git lacks documentation (and
this one of main complaints in git survey).
-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

Re: Cleaning up git user-interface warts

From: Han-Wen Nienhuys <hidden>
Date: 2016-08-11 20:38:41

Junio C Hamano escreveu:
You claim it is _an interface_ issue but it is not.
 >> I don't want ANYTHING to really change, I just want a sane interface 
 >> to it.
 >
 > I agree that you do not want to change anything.  You just
 > needed a bit of handholding, because you deviated from the
 > cookbook usage, to correct your course.

Users (well, I do at least) start fiddling with systems to find out how 
they work.   Reading the manual is usually done as a last resort. I 
think this is pretty well documented in usability research.

I'm trying to show how GIT is badly suited to this. Your response is to 
explain to me what I should have done. That's nice, but that approach 
doesn't scale, because you don't reach the dozens of users out there who 
try the same, fail and give up.

If you really want to find out the weaknesses, you'd have to sit someone 
new to git in front of a computer, and let him figure how to operate it, 
while videotaping everything.

Writing a manual for newbies is also an effective (and simpler and 
cheaper) approach of figuring out what needs to be changed.



As another example:  annoyances regarding program invocation

  - option handling: -x -f -z != -xfz , "--max-count 1" doesn't work, 
but needs an '='

  - git --help lists an unordered set, which is too long scan quickly. 
I'd expect that list to either contain everything or the minimum set for 
daily use. I.e. the set introduced in a first tutorial.  Why are merge, 
prune, verify-tag there?

Try "bzr help" for comparison.

  - --pretty option with wholly uninformative options full, medium, 
short, raw.  It's not even documented what each option does.


I can go on with listing idiosyncrasies, but my point is not to get help 
from you, but rather to show how git can be improved.

quoted
With GIT, this is what happens

[hanwen@haring y]$ git pull ../x
fatal: Needed a single revision
Pulling into a black hole?
You asked it to fetch from the neighbour repository and merge it
into your current branch which does not exist (I presume that
you omitted to describe what you did in directory y/ and I am
assuming you did "mkdir y && cd y && git initdb" and nothing
else).  You are pulling into a black hole.
as you remark in the other reply, there is IMO no reason for not having 
an empty 'master' branch. If master + HEAD gets created on the first 
commit, it might as well be created on the init-db.

-- 
  Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen

Re: Cleaning up git user-interface warts

From: Han-Wen Nienhuys <hidden>
Date: 2016-08-11 20:46:57

Han-Wen Nienhuys escreveu:
I can go on with listing idiosyncrasies, but my point is not to get help 
from you, but rather to show how git can be improved.
oh, and another annoying one: git's insistence on firing up a pager if 
there is nothing to page, eg. try

   git-log je-n-existe-pas

-- 
  Han-Wen Nienhuys - hanwen@xs4all.nl - http://www.xs4all.nl/~hanwen
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help