git part 5910 |
2010-12-01
|
I still can't get over how obtuse and error-prone git's command line UI is.
Today I was trying really hard to checkout a tag of some project to try and fix a bug.
Are there tags ? Why, yes.
$ git tag -l
redland-bindings_0_9_17_1
redland-bindings_0_9_18_1
redland-bindings_0_9_19_1
redland-bindings_1_0_0_1
redland-bindings_1_0_0_2
redland-bindings_1_0_10_1
redland-bindings_1_0_1_1
redland-bindings_1_0_2_1
redland-bindings_1_0_3_1
redland-bindings_1_0_4_1
redland-bindings_1_0_5_1
redland-bindings_1_0_6_1
redland-bindings_1_0_7_1
redland-bindings_1_0_8_1
redland-bindings_license_lgpl_apache2
redland-bindings_license_lgpl_mpl
redland_bindings
start
Here are my attempts and its responses:
$ git checkout redland_bindings_1_0_7_1
error: pathspec 'redland_bindings_1_0_7_1' did not match any file(s) known to git.
$ git checkout -b redland_bindings_1_0_7_1 redland_bindings_1_0_7_1
fatal: git checkout: updating paths is incompatible with switching branches.
Did you intend to checkout 'redland_bindings_1_0_7_1' which can not be resolved as commit?
Can you spot my error ? It took me a good thirty minutes to figure out what exactly I was doing wrong. Git could have just told me. Suggestions to improve these obtuse error messages?
The first error suggests that git thinks I'm trying to check out a file. Strangely enough git checkout -h says:
usage: git checkout [options]
or: git checkout [options] [
so why does it even think I'm trying to check out a file ? The usage suggests the only way to check out a file is to list them after -- which I didn't specify. Isn't the more logical thing to assume I was trying to check out a branch ? And while on the subject, you have to somehow understand or assume that, even though a tag is not a branch, you can actually check out a tag this way.
Instead the error should probably say something like:
git doesn't know about a branch or tag named '...'
Check with git tag -l or git branch -a to see all tags and branches.
If you wanted to specify a file instead, use -- to separate branch or tag from file names.
Now the second one. I am sorry git that I crossed the flux capacitators to reverse the coagulation of the ninth-dimensional positrons. But could you please try and insult me in English ? All I can get from this message, *after* understanding what my problem was, is that you think I want to switch branches (is that the same as checking out a tag ? Maybe, how can I tell ?) at the same time as updating a path. I'm pretty sure I'm only trying to do one of those two things, although I'm not too sure. And I think the proper English for that second sentence would be something like
"Did you intend to checkout the tag or branch '...', which does not exist in the repository ?
Use git tag -l or git branch -a to see a list of tags and branches.
I can't *wait* for the comments to pour in telling me I'm stupid because I can't automatically read 'cannot be resolved as a commit' is gitese for 'the tag does not exist'.
I'm only writing this post because git in this particular instance caused me to waste less time than average with obtuse UI, so I had some time to spare to complain.
I’d recommend to check your spelling: you tried to checkout redland_bindings_1_0_7_1 while the tag name is redland-bindings_1_0_7_1. Notice how the dash between redland and bindings suddenly became an underscore ?
Comment by pipomolo — 2010-12-01 @ 15:34
I know, I figured that out after butting my head against the wall. That was not the point of this post though – the point is that git made it really hard to figure out this was the problem.
Any other vcs would have told me that the thing I’m trying to get does not exist.
Comment by Thomas — 2010-12-01 @ 16:18
Oh and, you can checkout a file directly, you only need the — separator when you’re explicitely asking to checkout from a given commit.
Comment by pipomolo — 2010-12-01 @ 15:38
I feel your pain, brother… :-(
Comment by Søren Hauberg — 2010-12-01 @ 15:46
The — is actually optional, “git checkout filename” is just perfect, and that’s what’s stated in the manual page. Maybe “error: pathspec ‘…’ did not match any file(s) known to git.” should be changed to “error: pathspec or revspec ‘…’ did not match any file(s) or revisions known to git.” or similar.
In the end it is fairly obvious that the specific tag is not available, as git checkout tries file names if revisions are not found, and if it tells you it cannot find the file, this means that no such revision exists.
Comment by Julian Andres Klode — 2010-12-01 @ 15:56
The — is actually optional, “git checkout filename” is just perfect, and that’s what’s stated in the manual page. Maybe “error: pathspec ‘…’ did not match any file(s) known to git.” should be changed to “error: pathspec or revspec ‘…’ did not match any file(s) or revisions known to git.” or similar.
In the end it is fairly obvious that the specific tag is not available, as git checkout tries file names if revisions are not found, and if it tells you it cannot find the file, this means that no such revision exists.
Comment by Julian Andres Klode — 2010-12-01 @ 15:56
Git’s help is a bit misleading. “git checkout” allows you to checkout *any* commit in your history, not just tags and branches. The expression you pass can be a tag name, a branch name, HEAD~4, abcdef1234, master^2, etc. In short, any expression that “resolves to a commit”. Hence the message…
Also, the ‘–‘ is interpreted by the shell to tell it to stop interpreting what follows as options. Git as no idea you typed ‘–‘ in your command line.
Comment by amx — 2010-12-01 @ 16:02
Antoine, indeed, I know about the double dash – but the help suggests it is required instead of optional. It marks all optional arguments with [] clearly.
Comment by Thomas — 2010-12-01 @ 16:17
You are right, the error message could be improved. But “tag doesn’t exist” is not a proper error message, since you can give more than a tag to the git checkout command ( ie, you can give revisions and file and likely other objects ).
Comment by Michael — 2010-12-01 @ 16:04
You’re not stupid, it is obtuse, though you don’t need the ‘–‘ in front of a file – ‘git checkout ‘ works just fine (at least in 1.7.3.2), and is the fastest way I know of to revert changes in a single file. That would make your desired error message be more like this:
“git doesn’t know about the branch, tag or file named ‘…’
Check the filename if it’s supposed to be a file, check the tag name against ‘git tag -l’ if it’s supposed to be a tag or check the branch name against ‘git branch -a’ if it’s supposed to be a branch.”
Then again, it could use simple spell-check algorithms to show this error message instead:
“git doesn’t know about the branch, tag or file named ‘…’
Did you mean the tag ‘…’?”
Comment by Ted Wise — 2010-12-01 @ 16:04
Ted, I know I don’t need the double dash, but that’s not what the help says. The help clearly does not make it optional.
Comment by Thomas — 2010-12-01 @ 16:17
More unix commands need friendly error messages … +1 for adding more of this sort of thing :)
Comment by Stu — 2010-12-01 @ 16:15
The message displayed by ‘git checkout -h’ is in error, and does not match the manpage (‘git checkout –help’). The double dash is optional, except in cases where it is needed to disambiguate (e.g. when a filename and a branch/tag/commit have the same name). Definitely a bug.
I agree that the error message for the first command you typed is obtuse. The problem appears to be that builtin/checkout.c:cmd_checkout(), if it fails to find a branch/tag/commit named by the string you provide, it calls builtin/checkout.c:checkout_paths(), which in turn if it fails to find a file named by the string you provide, calls builtin/ls-files.c:report_path_error(); that seems suboptimal, since the error message really ought to say that it can’t find a branch/tag/commit/file with the name you specified rather than just saying it can’t find a file with the name you gave (although, if you had specified the double dash, then it could limit to just saying it couldn’t find the relevant file).
What wording would you suggest for changing the second error message? Changing ‘cannot be resolved as a commit’ to ‘does not name a tag’ would be wrong for cases when people misspell a branch (e.g. “git checkout masterr”) or mis-references a commit (e.g. “git checkout mastr~3”) or other reference (e.g. “git checkout refs/stash”, odd or unusual though that may be).
Comment by Elijah Newren — 2010-12-01 @ 18:38
“Any other vcs would have told me that the thing I’m trying to get does not exist.”
Sounds like it would have sufficed to change the original error:
error: pathspec ‘redland_bindings_1_0_7_1’ did not match any file(s) known to git.
to something more general:
error: ‘redland_bindings_1_0_7_1’ did not match any branch, tag, commit, or file known to git.
Comment by Anonymous — 2010-12-01 @ 19:20
There’s a lot of defensiveness among git’s userbase, but having lurked the development list for awhile, I can honestly say that patches for issues like this get written, and they get taken. Especially for an error message tweak I’d say if its worth ranting about its probably worth sending a patch, or even just a “wouldn’t it be better if git did x instead of y” mail.
Again, with the way so many of the users get so defensive about git I understand why most developers feel like they shouldn’t bother just offering up quick patches or suggestions when git frustrates them, but when you look at the actual core git developers the situation is a lot friendlier.
Comment by Casey Dahlin — 2010-12-01 @ 19:59
I do agree with you 100%.
It’s a bug that I believe is due to history, git checkout started out as a tool to checkout files, but then merged into what it is now: A tool to switch branches. And in that process, someone forgot to fix the error messages. I suspect it’s because everyone close to git knows what the message means, so we just resolve that text to “you made a typo” automatically.
PS: git has a tool to figure out typos (try running “git difff”), it should use it here. So if you file a bug about it, please include that.
Comment by Benjamin Otte — 2010-12-01 @ 20:01
My git does say that the — is optional (git version 1.7.0.4):
git checkout [-q] [-f] [-m] []
git checkout [-q] [-f] [-m] [-b ] []
git checkout [-f|–ours|–theirs|-m|–conflict=] [] [–] …
git checkout –patch [] [–] […]
Comment by Jeremie — 2010-12-01 @ 20:04
I don’t know you, but I love the tab-completion feature.
Comment by Claudio — 2010-12-01 @ 22:43
I think you’re an idiot! For completely unrelated reasons though *nod*
Comment by Jan Schmidt — 2010-12-01 @ 23:23
amx, the shell does not interpret ‘–‘, programs interpret that themselves.
Comment by Marius Gedminas — 2010-12-01 @ 23:51
git is an elaborate plot to redefine every possible word. It is designed to insult the users intelligence by showing them how unworthy they are because they clearly do not understand most of the things that git is doing. Git should be used mainly when version control is more important than coding on the project that you are trying to version control. Its priorities are completely screwed up.
Another example is when you do a “git pull” … git will spew a bunch of technical nonsense that is entirely useless for your work, such as technical details of how it transferred things, while at the same time it does NOT tell you something useful such as which files it updated and which you should go look at.
I pine for the days of cvs. CVS sucked, but it sucked in a simple, well defined way, that was rather easy to grasp. CVS was stupid, but it didn’t feel the need keep telling me how much smarter it is than whatever I am coding on.
Comment by Jiri Lebl — 2010-12-02 @ 11:35
I have a love-hate relationship with git. On the one hand it’s better than the competition. On the other hand it’s completely frustrating to use. Learning each operation always seem to be fraught with pitfalls. Until you have had a lot of practice, you think you are doing one thing and find, after viewing the changes with some kind of visualization tool that you have done something else entirely. There’s something fundamentally counter-intuitive about git.
Comment by Brandon (dotsony) — 2010-12-02 @ 13:16
@marius, thanks, I just learned something… It looks like it’s just standard POSIX usage for programs to do that.
Comment by amx — 2010-12-02 @ 13:43