{"thread":{"id":"2126","subject":"git-checkout-index, flag ordering and --prefix kludgy handling","startedAt":"2005-10-16T19:14:26Z","lastAt":"2005-10-18T08:34:58Z","messageCount":10,"participants":["Blaisorblade","Linus Torvalds","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"10184","messageId":"200510162114.27429.blaisorblade@yahoo.it","threadId":"2126","inReplyTo":null,"subject":"git-checkout-index, flag ordering and --prefix kludgy handling","fromName":"Blaisorblade","fromEmail":"blaisorblade@yahoo.it","sentAt":"2005-10-16T19:14:26Z","receivedAt":"2005-10-16T19:14:26Z","isPatch":false,"sender":{"key":"blaisorblade@yahoo.it","avatar":null},"body":"I already knew that git-checkout-cache -a -f is wrong. But I didn't know that \n\ngit-checkout-index -a --prefix=/home/paolo/Uml/space.mnt/paolo/Linux-2.6.git/\n\nis. It checks out the files in the cwd, then parses --prefix and does nothing \nthere, as no name is specified.\n\nAlso, the SYNOPSIS of the man page is rather misleading:\n\ngit-checkout-index [-u] [-q] [-a] [-f] [-n] [--prefix=<string>] [--] <file>...\n\nseems to suggest that prefix can go after -f, how it's reasonable to do.\n\nAt least, this should be documented in the man page; but I think that fixing \nthis (via two getopt() invocations rather than one, the first for flags like \n--prefix and the rest for actions) is probably a better thing to do.\n\nActually, given the audience, saying that \"-a\" and \"filename\" are both actions \n(which are executed when seen on the command line) would be a better \nexplaination - and a reference to the \"find\" command (which behaves \nsimilarly) would be worth.\n\nHowever, find *does* accept \"options\" (like -maxdepth) in any cmd line place.\n-- \nInform me of my mistakes, so I can keep imitating Homer Simpson's \"Doh!\".\nPaolo Giarrusso, aka Blaisorblade (Skype ID \"PaoloGiarrusso\", ICQ 215621894)\nhttp://www.user-mode-linux.org/~blaisorblade\n\n\n\t\t\n___________________________________ \nYahoo! Messenger: chiamate gratuite in tutto il mondo \nhttp://it.messenger.yahoo.com\n"},{"id":"10189","messageId":"7voe5nycmk.fsf@assigned-by-dhcp.cox.net","threadId":"2126","inReplyTo":"200510162114.27429.blaisorblade@yahoo.it","subject":"Re: git-checkout-index, flag ordering and --prefix kludgy handling","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-10-17T22:58:27Z","receivedAt":"2005-10-17T22:58:27Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Blaisorblade <blaisorblade@yahoo.it> writes:\n\n> I already knew that git-checkout-cache -a -f is wrong. But I\n> didn't know that\n>\n> git-checkout-index -a --prefix=/home/paolo/Uml/space.mnt/paolo/Linux-2.6.git/\n>\n> is.\n\n> At least, this should be documented in the man page;...\n\n\nHow about a bit further clarification on top of what is there,\nlike this?\n\n ------------\n[PATCH] clarify that '-a' is really special in checkout-index.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\ndiff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt\nindex 1ba6fb2..838059f 100644\n--- a/Documentation/git-checkout-index.txt\n+++ b/Documentation/git-checkout-index.txt\n@@ -44,13 +44,15 @@ OPTIONS\n --::\n \tDo not interpret any more arguments as options.\n \n-Note that the order of the flags matters:\n+Note that the order of the flags matters for `-a` flag:\n \n      git-checkout-index -a -f file.c\n \n will first check out all files listed in the cache (but not overwrite\n any old ones), and then force-checkout `file.c` a second time (ie that\n one *will* overwrite any old contents with the same filename).\n+In other words, `-a` means \"operate as if names of all files were\n+given here, with the flags given up to this point.\"\n \n Also, just doing \"git-checkout-index\" does nothing. You probably meant\n \"git-checkout-index -a\". And if you want to force it, you want\n"},{"id":"10188","messageId":"Pine.LNX.4.64.0510171546580.3369@g5.osdl.org","threadId":"2126","inReplyTo":"200510162114.27429.blaisorblade@yahoo.it","subject":"Re: git-checkout-index, flag ordering and --prefix kludgy handling","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-17T22:58:38Z","receivedAt":"2005-10-17T22:58:38Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 16 Oct 2005, Blaisorblade wrote:\n>\n> I already knew that git-checkout-cache -a -f is wrong. But I didn't know that \n> \n> git-checkout-index -a --prefix=/home/paolo/Uml/space.mnt/paolo/Linux-2.6.git/\n> \n> is. It checks out the files in the cwd, then parses --prefix and does nothing \n> there, as no name is specified.\n\nYeah, somebody should really fix the command line parsing. \n\nI think it's only git-checkout-index that _really_ needs fixing, since it \nhas such a fragile thing right now.\n\nHere's a totally untested patch. Do you want to test it?\n\nIt also makes it illegal to mix \"-a\" and explicit filenames, since the \nsemantics of that has now changed (before, the order of the filename and \nthe \"-a\" mattered. Now it no longer does. Better disallow it, than let \npeople maybe think they get something else that they do).\n\nDanger, Will Robinson! Untested!\n\n\t\tLinus\n\n---\ndiff --git a/checkout-index.c b/checkout-index.c\nindex 9784532..dab3778 100644\n--- a/checkout-index.c\n+++ b/checkout-index.c\n@@ -87,8 +87,9 @@ static struct cache_file cache_file;\n \n int main(int argc, char **argv)\n {\n-\tint i, force_filename = 0;\n+\tint i;\n \tint newfd = -1;\n+\tint all = 0;\n \n \tif (read_cache() < 0) {\n \t\tdie(\"invalid cache\");\n@@ -96,58 +97,70 @@ int main(int argc, char **argv)\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n-\t\tif (!force_filename) {\n-\t\t\tif (!strcmp(arg, \"-a\")) {\n-\t\t\t\tcheckout_all();\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"--\")) {\n-\t\t\t\tforce_filename = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-f\")) {\n-\t\t\t\tstate.force = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-q\")) {\n-\t\t\t\tstate.quiet = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-n\")) {\n-\t\t\t\tstate.not_new = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(arg, \"-u\")) {\n-\t\t\t\tstate.refresh_cache = 1;\n-\t\t\t\tif (newfd < 0)\n-\t\t\t\t\tnewfd = hold_index_file_for_update\n-\t\t\t\t\t\t(&cache_file,\n-\t\t\t\t\t\t get_index_file());\n-\t\t\t\tif (newfd < 0)\n-\t\t\t\t\tdie(\"cannot open index.lock file.\");\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!memcmp(arg, \"--prefix=\", 9)) {\n-\t\t\t\tstate.base_dir = arg+9;\n-\t\t\t\tstate.base_dir_len = strlen(state.base_dir);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (arg[0] == '-')\n-\t\t\t\tusage(checkout_cache_usage);\n-\t\t}\n-\t\tif (state.base_dir_len) {\n-\t\t\t/* when --prefix is specified we do not\n-\t\t\t * want to update cache.\n-\t\t\t */\n-\t\t\tif (state.refresh_cache) {\n-\t\t\t\tclose(newfd); newfd = -1;\n-\t\t\t\trollback_index_file(&cache_file);\n-\t\t\t}\n-\t\t\tstate.refresh_cache = 0;\n+\n+\t\tif (!strcmp(arg, \"--\")) {\n+\t\t\ti++;\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-a\") || !strcmp(arg, \"--all\")) {\n+\t\t\tall = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-f\") || !strcmp(arg, \"--force\")) {\n+\t\t\tstate.force = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-q\") || !strcmp(arg, \"--quiet\")) {\n+\t\t\tstate.quiet = 1;\n+\t\t\tcontinue;\n \t\t}\n+\t\tif (!strcmp(arg, \"-n\") || !strcmp(arg, \"--no-create\")) {\n+\t\t\tstate.not_new = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-u\") || !strcmp(arg, \"--index\")) {\n+\t\t\tstate.refresh_cache = 1;\n+\t\t\tif (newfd < 0)\n+\t\t\t\tnewfd = hold_index_file_for_update\n+\t\t\t\t\t(&cache_file,\n+\t\t\t\t\t get_index_file());\n+\t\t\tif (newfd < 0)\n+\t\t\t\tdie(\"cannot open index.lock file.\");\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!memcmp(arg, \"--prefix=\", 9)) {\n+\t\t\tstate.base_dir = arg+9;\n+\t\t\tstate.base_dir_len = strlen(state.base_dir);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (arg[0] == '-')\n+\t\t\tusage(checkout_cache_usage);\n+\t\tbreak;\n+\t}\n+\n+\tif (state.base_dir_len) {\n+\t\t/* when --prefix is specified we do not\n+\t\t * want to update cache.\n+\t\t */\n+\t\tif (state.refresh_cache) {\n+\t\t\tclose(newfd); newfd = -1;\n+\t\t\trollback_index_file(&cache_file);\n+\t\t}\n+\t\tstate.refresh_cache = 0;\n+\t}\n+\n+\t/* Check out named files first */\n+\tfor ( ; i < argc; i++) {\n+\t\tconst char *arg = argv[i];\n+\n+\t\tif (all)\n+\t\t\tdie(\"git-checkout-index: don't mix '--all' and explicit filenames\");\n \t\tcheckout_file(arg);\n \t}\n \n+\tif (all)\n+\t\tcheckout_all();\n+\n \tif (0 <= newfd &&\n \t    (write_cache(newfd, active_cache, active_nr) ||\n \t     commit_index_file(&cache_file)))\n"},{"id":"10192","messageId":"7v8xwry88u.fsf@assigned-by-dhcp.cox.net","threadId":"2126","inReplyTo":"Pine.LNX.4.64.0510171546580.3369@g5.osdl.org","subject":"Re: git-checkout-index, flag ordering and --prefix kludgy handling","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-10-18T00:33:05Z","receivedAt":"2005-10-18T00:33:05Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Yeah, somebody should really fix the command line parsing. \n>\n> I think it's only git-checkout-index that _really_ needs fixing, since it \n> has such a fragile thing right now.\n\nGood to hear that you finally said it.\n\nThe patch looks good.  Thanks.\n"},{"id":"10193","messageId":"Pine.LNX.4.64.0510171814430.3369@g5.osdl.org","threadId":"2126","inReplyTo":"7v8xwry88u.fsf@assigned-by-dhcp.cox.net","subject":"Re: git-checkout-index, flag ordering and --prefix kludgy handling","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-18T01:28:05Z","receivedAt":"2005-10-18T01:28:05Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 17 Oct 2005, Junio C Hamano wrote:\n>\n> The patch looks good.  Thanks.\n\nBtw, I'd really like a \"git checkout\" that can do the per-file thing, \ninstead of always using the equivalent of git-checkout-index with \"-a\".\n\nIt's actually one of the few places where I still use the raw git \ncommands, doing things like\n\n\tgit-checkout-index -u -f filename\n\nand I suspect that a lot of people would prefer that\n\n\tgit checkout filename\n\nwould just do that. Instead, we error out (\"no such branch\"). Which \nisn't even what I want, and almost certainly not what most CVS users want \n(they're used to checking out individual files).\n\nOf course, in the generic case, that would require git-read-tree to take a \nlist of filenames (which would act as a \"mask\" for any activity against \nthe old index if one was loaded), but that's a pretty big thing. Even if \nit's admittedly also potentially very useful too..\n\nBut even just a total special case (giving a filename would force the \ncheckout, no read-tree, no nothing, just force the old index contents) \nmight be acceptable and would only require some script hackery.\n\n\t\tLinus\n"},{"id":"10194","messageId":"7vmzl7tv89.fsf@assigned-by-dhcp.cox.net","threadId":"2126","inReplyTo":"Pine.LNX.4.64.0510171814430.3369@g5.osdl.org","subject":"Re: git-checkout-index, flag ordering and --prefix kludgy handling","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-10-18T02:27:50Z","receivedAt":"2005-10-18T02:27:50Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> Btw, I'd really like a \"git checkout\" that can do the per-file thing, \n> instead of always using the equivalent of git-checkout-index with \"-a\".\n>\n> It's actually one of the few places where I still use the raw git \n> commands, doing things like\n>\n> \tgit-checkout-index -u -f filename\n>\n> and I suspect that a lot of people would prefer that\n>\n> \tgit checkout filename\n>\n> would just do that. Instead, we error out (\"no such branch\"). Which \n> isn't even what I want, and almost certainly not what most CVS users want \n> (they're used to checking out individual files).\n\nYes, it has been on the TODO list for quite some time.\n\nOne reason I have not done nor said much about this was because\nI've been thinking about making the branch/refname more explicit\non our command line.\n\nCurrently, we tell 'git-rev-parse' to tell refnames and other\nnon-flag parameters apart, which in practice does not result in\nmuch confusion, but I think it is not quite right.\n\nI used to have a local branch, only to fetch updates from\npaulus, and naturally the branch was called 'gitk'.  But we have\na file called gitk sitting at the top level of the tree, and\n'git diff gitk gitk' was not really working as well as I would\nhave liked ('git diff heads/gitk gitk' should have worked, but I\ndo not think it did).  Since then this forced me to rename the\nbranch to 'paulus' X-<.\n\nOn the other hand, if there is no ambiguity, I do not think\nforcing people to always spell out '-r' like CVS or SVN do\nis not necessary:\n\n        $ git diff -r master^^ -r master ;# two commits\n        $ git diff -r v0.99.8\t\t ;# changes since that tag\n\t$ git checkout -r master\n        $ git checkout -r master $filename\n\nThis checkout optionally taking filename is introducing one more\nambiguity, and I was reluctant to do so before deciding what to\ndo about other commands.\n\nAnother thing I was thinking was that this might be better\nimplemented as a separate command that can revert the working\ntree file to an artibtrary tree-ish as well.  So:\n\n\t$ git xxxxxx --index file1 file2...\n\nwould do your 'git-checkout-index -f -u file1 file2...', while\n\n\t$ git xxxxxx file1 file2...\n\nwould do an equivalent of:\n\n\tgit ls-tree HEAD file1 file2... |\n        sed -e 's/^\\([0-7]*\\) [^ ]* /\\1 /' |\n        git-update-index --index-info\n        git-checkout-index -f -u file1 file2...\n\nor even:\n\n\t$ git xxxxxx HEAD^^ file1 file2...\n\nwould give you back file1 and file2 from two revs back.  Of\ncourse, to avoid ambiguities, the last one will be spelled as \n\n\t$ git xxxxxx -r HEAD^^ file1 file2...\n\nif people find that a separate command is cleaner.\n\nAnyway, in the meantime...\n\n ------------\n[PATCH] checking out individual files from index.\n\n'git checkout filename1 filename2...' can be used to revert the\nchanges you made to files in the working tree to the version\nrecorded in the index file.\n\nSigned-off-by: Signed-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 2c053a3..6af71a2 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -6,6 +6,7 @@ new=\n force=\n branch=\n newbranch=\n+\n while [ \"$#\" != \"0\" ]; do\n     arg=\"$1\"\n     shift\n@@ -24,19 +25,28 @@ while [ \"$#\" != \"0\" ]; do\n \t\tforce=1\n \t\t;;\n \t*)\n-\t\trev=$(git-rev-parse --verify \"$arg^0\" 2>/dev/null) ||\n-\t\t\tdie \"I don't know any '$arg'.\"\n-\t\tif [ -z \"$rev\" ]; then\n-\t\t\techo \"unknown flag $arg\"\n-\t\t\texit 1\n-\t\tfi\n-\t\tif [ \"$new\" ]; then\n-\t\t\techo \"Multiple revisions?\"\n-\t\t\texit 1\n-\t\tfi\n-\t\tnew=\"$rev\"\n-\t\tif [ -f \"$GIT_DIR/refs/heads/$arg\" ]; then\n-\t\t\tbranch=\"$arg\"\n+\t\tif rev=$(git-rev-parse --verify \"$arg^0\" 2>/dev/null)\n+\t\tthen\n+\t\t\tif [ -z \"$rev\" ]; then\n+\t\t\t\techo \"unknown flag $arg\"\n+\t\t\t\texit 1\n+\t\t\tfi\n+\t\t\tif [ \"$new\" ]; then\n+\t\t\t\techo \"Multiple revisions?\"\n+\t\t\t\texit 1\n+\t\t\tfi\n+\t\t\tnew=\"$rev\"\n+\t\t\tif [ -f \"$GIT_DIR/refs/heads/$arg\" ]; then\n+\t\t\t\tbranch=\"$arg\"\n+\t\t\tfi\n+\t\telse\n+\t\t\t# check out individual files from index\n+\t\t\tif test \"$new\" || test \"$newbranch\"\n+\t\t\tthen\n+\t\t\t\tdie \"checkout and switch tree?\"\n+\t\t\tfi\n+\t\t\tgit-checkout-index -f -u \"$arg\" \"$@\"\n+\t\t\texit $?\n \t\tfi\n \t\t;;\n     esac\n\nCompilation finished at Mon Oct 17 19:08:29\n"},{"id":"10196","messageId":"Pine.LNX.4.64.0510171933200.3369@g5.osdl.org","threadId":"2126","inReplyTo":"7vmzl7tv89.fsf@assigned-by-dhcp.cox.net","subject":"Re: git-checkout-index, flag ordering and --prefix kludgy handling","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-18T02:48:07Z","receivedAt":"2005-10-18T02:48:07Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Mon, 17 Oct 2005, Junio C Hamano wrote:\n> \n> One reason I have not done nor said much about this was because\n> I've been thinking about making the branch/refname more explicit\n> on our command line.\n\nYes, I know it's ambigious at times, but it really is very convenient. \nUsually we allow a \"--\" to say where a filename starts when it _is_ \nambiguous.\n\nHowever, you're right, we fail that at times. In particular, git-rev-parse \nfails it.\n\nSomething like this?\n\n\t\tLinus\n---\ndiff --git a/rev-parse.c b/rev-parse.c\nindex 41b9dae..85230df 100644\n--- a/rev-parse.c\n+++ b/rev-parse.c\n@@ -151,6 +151,12 @@ static void show_datestring(const char *\n \tshow(buffer);\n }\n \n+static void show_file(const char *arg)\n+{\n+\tif ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV))\n+\t\tshow(arg);\n+}\n+\n int main(int argc, char **argv)\n {\n \tint i, as_is = 0, verify = 0;\n@@ -162,7 +168,7 @@ int main(int argc, char **argv)\n \t\tchar *dotdot;\n \t\n \t\tif (as_is) {\n-\t\t\tshow(arg);\n+\t\t\tshow_file(arg);\n \t\t\tcontinue;\n \t\t}\n \t\tif (*arg == '-') {\n@@ -282,9 +288,7 @@ int main(int argc, char **argv)\n \t\t}\n \t\tif (verify)\n \t\t\tdie(\"Needed a single revision\");\n-\t\tif ((filter & (DO_NONFLAGS|DO_NOREV)) ==\n-\t\t    (DO_NONFLAGS|DO_NOREV))\n-\t\t\tshow(arg);\n+\t\tshow_file(arg);\n \t}\n \tshow_default();\n \tif (verify && revs_count != 1)\n"},{"id":"10199","messageId":"Pine.LNX.4.64.0510172243560.3369@g5.osdl.org","threadId":"2126","inReplyTo":"Pine.LNX.4.64.0510171933200.3369@g5.osdl.org","subject":"Teach \"git diff\" to handle filenames startign with '-'","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-18T05:49:27Z","receivedAt":"2005-10-18T05:49:27Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nIt adds \"--\" to the git-diff.sh scripts, to keep any filenames that start \nwith a \"-\" from being confused with an option.\n\nBut in order to do that, it needs to teach git-diff-files to honor \"--\".\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\nOn Mon, 17 Oct 2005, Linus Torvalds wrote:\n> \n> Yes, I know it's ambigious at times, but it really is very convenient. \n> Usually we allow a \"--\" to say where a filename starts when it _is_ \n> ambiguous.\n\nThis is on top of the rev-parse.c diff (it's strictly independent, but it \nneeds the rev-parse.c one to make any sense, since without the rev-parse.c \nfix for -- handling, \"git diff\" won't work regardless).\n\ndiff --git a/diff-files.c b/diff-files.c\nindex 8a8f9b6..1789939 100644\n--- a/diff-files.c\n+++ b/diff-files.c\n@@ -41,6 +41,11 @@ int main(int argc, const char **argv)\n \tgit_config(git_default_config);\n \tdiff_setup(&diff_options);\n \twhile (1 < argc && argv[1][0] == '-') {\n+\t\tif (!strcmp(argv[1], \"--\")) {\n+\t\t\targv++;\n+\t\t\targc--;\n+\t\t\tbreak;\n+\t\t}\n \t\tif (!strcmp(argv[1], \"-q\"))\n \t\t\tsilent = 1;\n \t\telse if (!strcmp(argv[1], \"-r\"))\ndiff --git a/git-diff.sh b/git-diff.sh\nindex 84a152a..b3ec84b 100755\n--- a/git-diff.sh\n+++ b/git-diff.sh\n@@ -28,16 +28,16 @@ case \"$rev\" in\n ?*' '^?*)\n \tbegin=$(expr \"$rev\" : '.*^.\\([0-9a-f]*\\).*') &&\n \tend=$(expr \"$rev\" : '.\\([0-9a-f]*\\). .*') || exit\n-\tcmd=\"git-diff-tree $flags $begin $end $files\"\n+\tcmd=\"git-diff-tree $flags $begin $end -- $files\"\n \t;;\n ?*' '?*)\n-\tcmd=\"git-diff-tree $flags $rev $files\"\n+\tcmd=\"git-diff-tree $flags $rev -- $files\"\n \t;;\n ?*' ')\n-\tcmd=\"git-diff-index $flags $rev $files\"\n+\tcmd=\"git-diff-index $flags $rev -- $files\"\n \t;;\n '')\n-\tcmd=\"git-diff-files $flags $files\"\n+\tcmd=\"git-diff-files $flags -- $files\"\n \t;;\n *)\n \tdie \"I don't understand $*\"\n"},{"id":"10201","messageId":"Pine.LNX.4.64.0510172251340.3369@g5.osdl.org","threadId":"2126","inReplyTo":"Pine.LNX.4.64.0510172243560.3369@g5.osdl.org","subject":"Handle \"-\" at beginning of filenames, part 3","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-10-18T05:57:53Z","receivedAt":"2005-10-18T05:57:53Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nThis fixes the default built-in exec() of \"diff\" to add a \"--\" before the \nfilenames, so that if a filename starts with a \"-\", the diff program won't \nthink it's an option.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\nThis should complete the series. Now all the parts should be safe and pass \non \"--\" properly. Knock wood.\n\n\nOn Mon, 17 Oct 2005, Linus Torvalds wrote:\n> \n> It adds \"--\" to the git-diff.sh scripts, to keep any filenames that start \n> with a \"-\" from being confused with an option.\n\ndiff --git a/diff.c b/diff.c\nindex cbb8632..d6b5086 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -134,7 +134,7 @@ static void builtin_diff(const char *nam\n {\n \tint i, next_at, cmd_size;\n \tconst char *const diff_cmd = \"diff -L%s%s -L%s%s\";\n-\tconst char *const diff_arg  = \"%s %s||:\"; /* \"||:\" is to return 0 */\n+\tconst char *const diff_arg  = \"-- %s %s||:\"; /* \"||:\" is to return 0 */\n \tconst char *input_name_sq[2];\n \tconst char *path0[2];\n \tconst char *path1[2];\n"},{"id":"10202","messageId":"7vu0ffrznx.fsf_-_@assigned-by-dhcp.cox.net","threadId":"2126","inReplyTo":"7vmzl7tv89.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] git-checkout: revert specific paths to either index or a given tree-ish.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-10-18T08:34:58Z","receivedAt":"2005-10-18T08:34:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"When extra paths arguments are given, git-checkout reverts only those\npaths to either the version recorded in the index or the version\nrecorded in the given tree-ish.\n\nThis has been on the TODO list for quite a while.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n\n---\n\n    Junio C Hamano <junkio@cox.net> writes:\n\n    > Linus Torvalds <torvalds@osdl.org> writes:\n    >\n    >> Btw, I'd really like a \"git checkout\" that can do the per-file thing, \n    >> instead of always using the equivalent of git-checkout-index with \"-a\".\n    >>\n    >> and I suspect that a lot of people would prefer that\n    >>\n    >> \tgit checkout filename\n    >>\n    >> would just do that. Instead, we error out (\"no such branch\"). Which \n    >> isn't even what I want, and almost certainly not what most CVS users want \n    >> (they're used to checking out individual files).\n\n    I've redone this a bit differently since last night's \"in\n    the meantime...\" patch, so that we can pull selected paths\n    out of arbitrary tree-ish.\n\n git-checkout.sh                |   79 ++++++++++++++++++++++++++++++++--------\n Documentation/git-checkout.txt |   42 ++++++++++++++++++++-\n 2 files changed, 103 insertions(+), 18 deletions(-)\n\napplies-to: f7e1a8387657c4da9991861ae44347813b67bc46\n4aaa702794447d9b281dd22fe532fd61e02434e1\ndiff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt\nindex f753c14..b7bb1b4 100644\n--- a/Documentation/git-checkout.txt\n+++ b/Documentation/git-checkout.txt\n@@ -7,12 +7,24 @@ git-checkout - Checkout and switch to a \n \n SYNOPSIS\n --------\n-'git-checkout' [-f] [-b <new_branch>] [<branch>]\n+'git-checkout' [-f] [-b <new_branch>] [<branch>] [<paths>...]\n \n DESCRIPTION\n -----------\n-Updates the index and working tree to reflect the specified branch,\n-<branch>. Updates HEAD to be <branch> or, if specified, <new_branch>.\n+\n+When <paths> are not given, this command switches branches, by\n+updating the index and working tree to reflect the specified\n+branch, <branch>, and updating HEAD to be <branch> or, if\n+specified, <new_branch>.\n+\n+When <paths> are given, this command does *not* switch\n+branches.  It updates the named paths in the working tree from\n+the index file (i.e. it runs `git-checkout-index -f -u`).  In\n+this case, `-f` and `-b` options are meaningless and giving\n+either of them results in an error.  <branch> argument can be\n+used to specify a specific tree-ish to update the index for the\n+given paths before updating the working tree.\n+\n \n OPTIONS\n -------\n@@ -29,6 +41,30 @@ OPTIONS\n \tBranch to checkout; may be any object ID that resolves to a\n \tcommit. Defaults to HEAD.\n \n+\n+EXAMPLE\n+-------\n+\n+The following sequence checks out the `master` branch, reverts\n+the `Makefile` to two revisions back, deletes hello.c by\n+mistake, and gets it back from the index.\n+\n+------------\n+$ git checkout master\n+$ git checkout master~2 Makefile\n+$ rm -f hello.c\n+$ git checkout hello.c\n+------------\n+\n+If you have an unfortunate branch that is named `hello.c`, the\n+last step above would be confused as an instruction to switch to\n+that branch.  You should instead write:\n+\n+------------\n+$ git checkout -- hello.c\n+------------\n+\n+\n Author\n ------\n Written by Linus Torvalds <torvalds@osdl.org>\ndiff --git a/git-checkout.sh b/git-checkout.sh\nindex 2c053a3..73652fa 100755\n--- a/git-checkout.sh\n+++ b/git-checkout.sh\n@@ -23,32 +23,81 @@ while [ \"$#\" != \"0\" ]; do\n \t\"-f\")\n \t\tforce=1\n \t\t;;\n+\t--)\n+\t\tbreak\n+\t\t;;\n \t*)\n-\t\trev=$(git-rev-parse --verify \"$arg^0\" 2>/dev/null) ||\n-\t\t\tdie \"I don't know any '$arg'.\"\n-\t\tif [ -z \"$rev\" ]; then\n-\t\t\techo \"unknown flag $arg\"\n-\t\t\texit 1\n-\t\tfi\n-\t\tif [ \"$new\" ]; then\n-\t\t\techo \"Multiple revisions?\"\n-\t\t\texit 1\n-\t\tfi\n-\t\tnew=\"$rev\"\n-\t\tif [ -f \"$GIT_DIR/refs/heads/$arg\" ]; then\n-\t\t\tbranch=\"$arg\"\n+\t\tif rev=$(git-rev-parse --verify \"$arg^0\" 2>/dev/null)\n+\t\tthen\n+\t\t\tif [ -z \"$rev\" ]; then\n+\t\t\t\techo \"unknown flag $arg\"\n+\t\t\t\texit 1\n+\t\t\tfi\n+\t\t\tnew=\"$rev\"\n+\t\t\tif [ -f \"$GIT_DIR/refs/heads/$arg\" ]; then\n+\t\t\t\tbranch=\"$arg\"\n+\t\t\tfi\n+\t\telif rev=$(git-rev-parse --verify \"$arg^{tree}\" 2>/dev/null)\n+\t\tthen\n+\t\t\t# checking out selected paths from a tree-ish.\n+\t\t\tnew=\"$rev\"\n+\t\t\tbranch=\n+\t\telse\n+\t\t\tnew=\n+\t\t\tbranch=\n+\t\t\tset x \"$arg\" \"$@\"\n+\t\t\tshift\n \t\tfi\n+\t\tbreak\n \t\t;;\n     esac\n done\n-[ -z \"$new\" ] && new=$old\n \n+# The behaviour of the command with and without explicit path\n+# parameters is quite different.\n+#\n+# Without paths, we are checking out everything in the work tree,\n+# possibly switching branches.  This is the traditional behaviour.\n #\n+# With paths, we are _never_ switching branch, but checking out\n+# the named paths from either index (when no rev is given),\n+# or the named tree-ish (when rev is given).\n+\n+if test \"$#\" -ge 1\n+then\n+\tif test '' != \"$newbranch$force\"\n+\tthen\n+\t\tdie \"updating paths and switching branches or forcing are incompatible.\"\n+\tfi\n+\tif test '' != \"$new\"\n+\tthen\n+\t\t# from a specific tree-ish; note that this is for\n+\t\t# rescuing paths and is never meant to remove what\n+\t\t# is not in the named tree-ish.\n+\t\tgit-ls-tree -r \"$new\" \"$@\" |\n+\t\tsed -ne 's/^\\([0-7]*\\) blob \\(.*\\)$/\\1 \\2/p' |\n+\t\tgit-update-index --index-info || exit $?\n+\tfi\n+\tgit-checkout-index -f -u -- \"$@\"\n+\texit $?\n+else\n+\t# Make sure we did not fall back on $arg^{tree} codepath\n+\t# since we are not checking out from an arbitrary tree-ish,\n+\t# but switching branches.\n+\tif test '' != \"$new\"\n+\tthen\n+\t\tgit-rev-parse --verify \"$new^{commit}\" >/dev/null 2>&1 ||\n+\t\tdie \"Cannot switch branch to a non-commit.\"\n+\tfi\n+fi\n+\n+[ -z \"$new\" ] && new=$old\n+\n # If we don't have an old branch that we're switching to,\n # and we don't have a new branch name for the target we\n # are switching to, then we'd better just be checking out\n # what we already had\n-#\n+\n [ -z \"$branch$newbranch\" ] &&\n \t[ \"$new\" != \"$old\" ] &&\n \tdie \"git checkout: you need to specify a new branch name\"\n---\n0.99.8.GIT\n"}]}