{"thread":{"id":"20399","subject":"[PATCH 1/6] Teach --id/-d to \"git status\"","startedAt":"2009-08-05T09:51:40Z","lastAt":"2009-08-05T20:01:20Z","messageCount":17,"participants":["Nazri Ramliy","Andreas Ericsson","Matthieu Moy","Alex Riesen","Sverre Rabbelier","Junio C Hamano","Jeff King","Nicolas Pitre"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"119601","messageId":"1249465906-3940-1-git-send-email-ayiehere@gmail.com","threadId":"20399","inReplyTo":null,"subject":"[PATCH] RFC - Say goodbye to the rodent","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2009-08-05T09:51:40Z","receivedAt":"2009-08-05T09:51:40Z","isPatch":true,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"Hello list,\n\nGit status provides a list of modified/staged files etc.\n\nNormally I use the mouse to cut and paste the filenames in subsequent git\noperations.\n\nOftentimes I get tired of moving my hand away from the comfort of the home rows\nof my keybard in order to grab the mouse to highlight the files that I'd like\nto operate on.\n\nThis patch is my attempt at scratching this itch.  It is, at best, works fine;\nalbeit a little bit experimental.  I may have overlooked a dozen things -\nvariable names, places where I define the variables etc. If people find this useful\nI'll look into polishing the code. All seem to work well. Running make test\ndoes not break anything. I have not written test case for them.\n\nThe idea is that \"git status --id\" shows a unique id for each file in its output\n(modified/staged/unknown/etc). The ids and the corresponding filenames are\nstored in .git/FILE_IDS. This file gets overwritten everytime you run \"git\nstatus --id\"\n\nSubsequent git operations can be taught to accept the --id command line option\nto tell them what files to operate on. They will read the FILE_IDS to find out\nwhich file to operate based on the given id.  In the patch series I have taught\nthe add, checkout, commit, rm and reset commands the --id option.\n\nExample:\n\n$ git status --id\n# On branch local\n# Changed but not updated:\n#   (use \"git add <file>...\" to update what will be committed)\n#   (use \"git checkout -- <file>...\" to discard changes in working directory)\n#\n#       modified:   builtin-write-tree.c (m1)\n#\n# Untracked files:\n#   (use \"git add <file>...\" to include in what will be committed)\n#\n#       file1.c (x1)\n#       file2.c (x2)\n\n\nNote the id at the end of the files.\n\nNow we can do the following:\n\n$ git add --id m1\n\nIds are specified via the --id command line option, and can be separated with\ncommas if you want to specify more than one of them:\n\n$ git add --id m1,x2\n\nYou get the idea ...\n\nWhat do you guys think about this new approach of \"cut-and-paste\" from the\ncommand line?\n\nWhere would be the best place to put the file id? end? beginning? before ':'?\nThe argument to --id could be improved so that it understand regexes for file ids.\n\nComments are welcomed.\n\nNazri.\n\n-- \n\n builtin-add.c      |   19 +++++--\n builtin-checkout.c |   26 ++++++---\n builtin-commit.c   |    4 +-\n builtin-reset.c    |   32 +++++++----\n builtin-rm.c       |   11 ++++-\n cache.h            |    1 +\n path.c             |   44 ++++++++++++++++\n wt-status.c        |  146 ++++++++++++++++++++++++++++++++++++++++++++++++----\n wt-status.h        |    1 +\n 9 files changed, 245 insertions(+), 39 deletions(-)\n"},{"id":"119594","messageId":"1249465906-3940-2-git-send-email-ayiehere@gmail.com","threadId":"20399","inReplyTo":"1249465906-3940-1-git-send-email-ayiehere@gmail.com","subject":"[PATCH 1/6] Teach --id/-d to \"git status\"","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2009-08-05T09:51:41Z","receivedAt":"2009-08-05T09:51:41Z","isPatch":true,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"This patch adds a unique identifier for each file shown by \"git status\".\n\nSubsequent operation (add/rm/checkout/commit/reset) may use these ids\nto simplify specifying the files, provided that they are taught about\nthe --id option as well.\n\nExample:\n\n  $ git status --id\n  # On branch local\n  # Changed but not updated:\n  #   (use \"git add <file>...\" to update what will be committed)\n  #   (use \"git checkout -- <file>...\" to discard changes in working directory)\n  #\n  #\tmodified:   builtin-add.c (m1)\n  #\tmodified:   builtin-checkout.c (m2)\n  #\tmodified:   builtin-commit.c (m3)\n  #\tmodified:   builtin-reset.c (m4)\n  #\tmodified:   builtin-rm.c (m5)\n  #\n  # Untracked files:\n  #   (use \"git add <file>...\" to include in what will be committed)\n  #\n  #\tmakefile.debug (x1)\n  #\tnazri.sh (x2)\n  no changes added to commit (use \"git add\" and/or \"git commit -a\")\n\n  $ git add --id m1\n  # Short for \"git add builtin-add.c\n\n  $ git add --id m3,m5\n  # Short for \"git add builtin-commit.c builtin-rm.c\"\n\n  # Even shorter: -d is equivalent to --id\n  $ git add -d m3,m5\n\nSigned-off-by: Nazri Ramliy <ayiehere@gmail.com>\n---\n cache.h     |    1 +\n path.c      |   44 ++++++++++++++++++\n wt-status.c |  146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----\n wt-status.h |    1 +\n 4 files changed, 181 insertions(+), 11 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex e6c7f33..05817e3 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -649,6 +649,7 @@ const char *make_relative_path(const char *abs, const char *base);\n int normalize_path_copy(char *dst, const char *src);\n int longest_ancestor_length(const char *path, const char *prefix_list);\n char *strip_path_suffix(const char *path, const char *suffix);\n+char ** expand_file_ids(const char *file_id, int *argc, char **argv);\n \n /* Read and unpack a sha1 file into memory, write memory to a sha1 file */\n extern int sha1_object_info(const unsigned char *, unsigned long *);\ndiff --git a/path.c b/path.c\nindex 047fdb0..7824c4a 100644\n--- a/path.c\n+++ b/path.c\n@@ -564,3 +564,47 @@ char *strip_path_suffix(const char *path, const char *suffix)\n \t\treturn NULL;\n \treturn xstrndup(path, chomp_trailing_dir_sep(path, path_len));\n }\n+\n+char ** expand_file_ids(const char *file_id, int *argc, char **argv)\n+{\n+\tFILE *fp;\n+\tconst char *filename = git_path(\"FILE_IDS\");\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tint i;\n+\n+\tchar **new_argv;\n+\n+\tnew_argv = (char **) xmalloc(*argc * sizeof(char *));\n+\tfor (i = 0; i < *argc; i++) {\n+\t\tnew_argv[i] = (char *) argv[i];\n+\t}\n+\n+\tfp = fopen(filename, \"r\");\n+\tif (!fp)\n+\t\tdie(\"cannot open %s: %s\\n\", filename, strerror(errno));\n+\n+\twhile (strbuf_getline(&sb, fp, '\\n') == 0) {\n+\t\tchar *b, *e;\n+\t\tif (sb.len == 0)\n+\t\t\tcontinue;\n+\t\tb = e = sb.buf;\n+\t\twhile(*e && *e != ' ')\n+\t\t\te++;\n+\t\t*e = '\\0';\n+\t\tif(strstr(file_id, b)) {\n+\t\t\t (*argc)++;\n+\t\t\t new_argv = xrealloc(new_argv, (*argc) * sizeof(char *));\n+\t\t\t new_argv[*argc - 1] = xstrdup(e+1);\n+\t\t}\n+\t}\n+\tstrbuf_release(&sb);\n+\n+\t/* \n+\t * parse_options adds a NULL terminator at end of argv. Do the same for\n+\t * new_argv.\n+\t */\n+\tnew_argv = xrealloc(new_argv, *argc + 1 * sizeof(char *));\n+\tnew_argv[*argc] = NULL;\n+\n+\treturn new_argv;\n+}\ndiff --git a/wt-status.c b/wt-status.c\nindex 47735d8..6013fbd 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -96,6 +96,106 @@ static void wt_status_print_trailer(struct wt_status *s)\n \tcolor_fprintf_ln(s->fp, color(WT_STATUS_HEADER), \"#\");\n }\n \n+struct id_list {\n+\tstruct id_list *next;\n+\tchar status;\n+\tint nr;\n+\tchar *name;\n+};\n+\n+static struct id_list *wt_files = NULL;\n+static struct id_list *wt_files_last = NULL;\n+static int n_id_list = 0;\n+\n+static int get_id_list_id(char status)\n+{\n+\tstatic int added = 0;\n+\tstatic int copied = 0;\n+\tstatic int deleted = 0;\n+\tstatic int modified = 0;\n+\tstatic int renamed = 0;\n+\tstatic int type_changed = 0;\n+\tstatic int unknown = 0;\n+\tstatic int unmerged = 0;\n+\n+\tswitch(status) {\n+\tcase DIFF_STATUS_ADDED:\n+\t\treturn ++added;\n+\tcase DIFF_STATUS_COPIED:\n+\t\treturn ++copied;\n+\tcase DIFF_STATUS_DELETED:\n+\t\treturn ++deleted;\n+\tcase DIFF_STATUS_MODIFIED:\n+\t\treturn ++modified;\n+\tcase DIFF_STATUS_RENAMED:\n+\t\treturn ++renamed;\n+\tcase DIFF_STATUS_TYPE_CHANGED:\n+\t\treturn ++type_changed;\n+\tcase DIFF_STATUS_UNKNOWN:\n+\t\treturn ++unknown;\n+\tcase DIFF_STATUS_UNMERGED:\n+\t\treturn ++unmerged;\n+\t}\n+\tdie(\"bug: unhandled diff status %c\", status);\n+}\n+\n+static int add_to_id_list(char status, const char *name)\n+{\n+\tstruct id_list *new_entry;\n+\tif(wt_files_last == NULL) {\n+\t\twt_files = xcalloc(1, sizeof(*wt_files));\n+\t\twt_files_last = wt_files;\n+\t\tnew_entry = wt_files_last;\n+\t} else {\n+\t\twt_files_last->next = xcalloc(1, sizeof(*wt_files));\n+\t\tnew_entry = wt_files_last->next;\n+\t\twt_files_last = wt_files_last->next;\n+\t}\n+\tnew_entry->name = xstrdup(name);\n+\tnew_entry->nr = get_id_list_id(status);\n+\tnew_entry->status = status;\n+\tnew_entry->next = NULL;\n+\n+\tn_id_list++;\n+\n+\treturn new_entry->nr;\n+}\n+\n+static void store_id_list()\n+{\n+\tFILE *fp;\n+\tstruct id_list *p = wt_files;\n+\tconst char *filename = git_path(\"FILE_IDS\");\n+\n+\tfp = fopen(filename, \"w\");\n+\tif (!fp)\n+\t\tdie(\"cannot open %s: %s\\n\", filename, strerror(errno));\n+\n+\twhile (p) {\n+\t\tfprintf(fp, \"%c%d %s\\n\",tolower(p->status), p->nr, p->name);\n+\t\tp = p->next;\n+\t}\n+\tfclose(fp);\n+}\n+\n+static void free_id_list()\n+{\n+  struct id_list *p = wt_files;\n+  struct id_list *next = p;\n+  while (p) {\n+    next = p->next;\n+    free(p->name);\n+    free(p);\n+    p = next;\n+  }\n+  wt_files = NULL;\n+}\n+\n+static void format_id(char *buf, char status, int nr)\n+{\n+\tsprintf(buf, \" (%c%d)\", tolower(status), nr);\n+}\n+\n #define quote_path quote_path_relative\n \n static void wt_status_print_filepair(struct wt_status *s,\n@@ -104,35 +204,48 @@ static void wt_status_print_filepair(struct wt_status *s,\n \tconst char *c = color(t);\n \tconst char *one, *two;\n \tstruct strbuf onebuf = STRBUF_INIT, twobuf = STRBUF_INIT;\n+\tchar id[64] = \"\"; /* arbitrary limit, 64 should be enough for everybody ... */\n+\tint nr;\n \n \tone = quote_path(p->one->path, -1, &onebuf, s->prefix);\n \ttwo = quote_path(p->two->path, -1, &twobuf, s->prefix);\n \n+\tif (s->show_file_id) {\n+\t\tif ( p->status == DIFF_STATUS_RENAMED \n+\t\t     || p->status == DIFF_STATUS_COPIED)\n+\t\t\tnr = add_to_id_list(p->status, two);\n+\t\telse\n+\t\t\tnr = add_to_id_list(p->status, one);\n+\t\tformat_id(id, p->status, nr);\n+\t}\n+\n+\n \tcolor_fprintf(s->fp, color(WT_STATUS_HEADER), \"#\\t\");\n \tswitch (p->status) {\n \tcase DIFF_STATUS_ADDED:\n-\t\tcolor_fprintf(s->fp, c, \"new file:   %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"new file:   %s%s\", one, id);\n \t\tbreak;\n \tcase DIFF_STATUS_COPIED:\n-\t\tcolor_fprintf(s->fp, c, \"copied:     %s -> %s\", one, two);\n+\t\tcolor_fprintf(s->fp, c, \"copied:     %s -> %s%s\", one, two, id);\n \t\tbreak;\n \tcase DIFF_STATUS_DELETED:\n-\t\tcolor_fprintf(s->fp, c, \"deleted:    %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"deleted:    %s%s\", one, id);\n \t\tbreak;\n \tcase DIFF_STATUS_MODIFIED:\n-\t\tcolor_fprintf(s->fp, c, \"modified:   %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"modified:   %s%s\", one, id);\n+\n \t\tbreak;\n \tcase DIFF_STATUS_RENAMED:\n-\t\tcolor_fprintf(s->fp, c, \"renamed:    %s -> %s\", one, two);\n+\t\tcolor_fprintf(s->fp, c, \"renamed:    %s -> %s%s\", one, two, id);\n \t\tbreak;\n \tcase DIFF_STATUS_TYPE_CHANGED:\n-\t\tcolor_fprintf(s->fp, c, \"typechange: %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"typechange: %s%s\", one, id);\n \t\tbreak;\n \tcase DIFF_STATUS_UNKNOWN:\n-\t\tcolor_fprintf(s->fp, c, \"unknown:    %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"unknown:    %s%s\", one, id);\n \t\tbreak;\n \tcase DIFF_STATUS_UNMERGED:\n-\t\tcolor_fprintf(s->fp, c, \"unmerged:   %s\", one);\n+\t\tcolor_fprintf(s->fp, c, \"unmerged:   %s%s\", one, id);\n \t\tbreak;\n \tdefault:\n \t\tdie(\"bug: unhandled diff status %c\", p->status);\n@@ -247,6 +360,9 @@ static void wt_status_print_untracked(struct wt_status *s)\n \tint i;\n \tint shown_header = 0;\n \tstruct strbuf buf = STRBUF_INIT;\n+\tchar id[64] = \"\"; /* arbitrary limit, 64 should be enough for everybody ... */\n+\tchar *quoted;\n+\tint nr;\n \n \tmemset(&dir, 0, sizeof(dir));\n \n@@ -266,9 +382,13 @@ static void wt_status_print_untracked(struct wt_status *s)\n \t\t\tshown_header = 1;\n \t\t}\n \t\tcolor_fprintf(s->fp, color(WT_STATUS_HEADER), \"#\\t\");\n-\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), \"%s\",\n-\t\t\t\tquote_path(ent->name, ent->len,\n-\t\t\t\t\t&buf, s->prefix));\n+\t\tquoted = quote_path(ent->name, ent->len, &buf, s->prefix);\n+\t\tif (s->show_file_id) {\n+\t\t\tnr = add_to_id_list(DIFF_STATUS_UNKNOWN, quoted);\n+\t\t\tformat_id(id, DIFF_STATUS_UNKNOWN, nr);\n+\t\t}\n+\t\tcolor_fprintf_ln(s->fp, color(WT_STATUS_UNTRACKED), \"%s%s\",\n+\t\t\t\tquoted, id);\n \t}\n \tstrbuf_release(&buf);\n }\n@@ -370,6 +490,10 @@ void wt_status_print(struct wt_status *s)\n \t\telse\n \t\t\tprintf(\"nothing to commit (working directory clean)\\n\");\n \t}\n+\tif (s->show_file_id) {\n+\t\tstore_id_list();\n+\t\tfree_id_list();\n+\t}\n }\n \n int git_status_config(const char *k, const char *v, void *cb)\ndiff --git a/wt-status.h b/wt-status.h\nindex 78add09..efcb566 100644\n--- a/wt-status.h\n+++ b/wt-status.h\n@@ -23,6 +23,7 @@ struct wt_status {\n \tchar *branch;\n \tconst char *reference;\n \tint verbose;\n+\tint show_file_id;\n \tint amend;\n \tint untracked;\n \tint nowarn;\n-- \n1.6.4.13.ge6580\n"},{"id":"119595","messageId":"1249465906-3940-3-git-send-email-ayiehere@gmail.com","threadId":"20399","inReplyTo":"1249465906-3940-2-git-send-email-ayiehere@gmail.com","subject":"[PATCH 2/6] Teach --id to \"git add\"","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2009-08-05T09:51:42Z","receivedAt":"2009-08-05T09:51:42Z","isPatch":true,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"---\n builtin-add.c |   19 ++++++++++++++-----\n 1 files changed, 14 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin-add.c b/builtin-add.c\nindex 581a2a1..1ed95d5 100644\n--- a/builtin-add.c\n+++ b/builtin-add.c\n@@ -212,6 +212,7 @@ static const char ignore_error[] =\n \n static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;\n static int ignore_add_errors, addremove, intent_to_add;\n+static const char *file_id;\n \n static struct option builtin_add_options[] = {\n \tOPT__DRY_RUN(&show_only),\n@@ -226,6 +227,7 @@ static struct option builtin_add_options[] = {\n \tOPT_BOOLEAN('A', \"all\", &addremove, \"add all, noticing removal of tracked files\"),\n \tOPT_BOOLEAN( 0 , \"refresh\", &refresh_only, \"don't add, only refresh the index\"),\n \tOPT_BOOLEAN( 0 , \"ignore-errors\", &ignore_add_errors, \"just skip files which cannot be added because of errors\"),\n+\tOPT_STRING('d', \"id\", &file_id, \"FILE_ID\", \"file id\"),\n \tOPT_END(),\n };\n \n@@ -268,27 +270,34 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \tint flags;\n \tint add_new_files;\n \tint require_pathspec;\n+\tchar **new_argv;\n \n \tgit_config(add_config, NULL);\n \n \targc = parse_options(argc, argv, prefix, builtin_add_options,\n \t\t\t  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);\n+\n+\tif (file_id)\n+\t\tnew_argv = (char **) expand_file_ids(file_id, &argc, (char **) argv);\n+\telse\n+\t\tnew_argv = (char **) argv;\n+\n \tif (patch_interactive)\n \t\tadd_interactive = 1;\n \tif (add_interactive)\n-\t\texit(interactive_add(argc - 1, argv + 1, prefix));\n+\t\texit(interactive_add(argc - 1, (const char **) (new_argv + 1), prefix));\n \n \tif (edit_interactive)\n-\t\treturn(edit_patch(argc, argv, prefix));\n+\t\treturn(edit_patch(argc, (const char **) new_argv, prefix));\n \targc--;\n-\targv++;\n+\tnew_argv++;\n \n \tif (addremove && take_worktree_changes)\n \t\tdie(\"-A and -u are mutually incompatible\");\n \tif ((addremove || take_worktree_changes) && !argc) {\n \t\tstatic const char *here[2] = { \".\", NULL };\n \t\targc = 1;\n-\t\targv = here;\n+\t\tnew_argv = (char **) here;\n \t}\n \n \tadd_new_files = !take_worktree_changes && !refresh_only;\n@@ -308,7 +317,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)\n \t\tfprintf(stderr, \"Maybe you wanted to say 'git add .'?\\n\");\n \t\treturn 0;\n \t}\n-\tpathspec = validate_pathspec(argc, argv, prefix);\n+\tpathspec = validate_pathspec(argc, (const char **) new_argv, prefix);\n \n \tif (read_cache() < 0)\n \t\tdie(\"index file corrupt\");\n-- \n1.6.4.13.ge6580\n"},{"id":"119598","messageId":"1249465906-3940-4-git-send-email-ayiehere@gmail.com","threadId":"20399","inReplyTo":"1249465906-3940-3-git-send-email-ayiehere@gmail.com","subject":"[PATCH 3/6] Teach --id to \"git checkout\"","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2009-08-05T09:51:43Z","receivedAt":"2009-08-05T09:51:43Z","isPatch":true,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"---\n builtin-checkout.c |   26 +++++++++++++++++---------\n 1 files changed, 17 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 8a9a474..94ef419 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -32,6 +32,7 @@ struct checkout_opts {\n \tint writeout_error;\n \n \tconst char *new_branch;\n+\tconst char *file_id;\n \tint new_branch_log;\n \tenum branch_track track;\n };\n@@ -583,6 +584,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \tstruct option options[] = {\n \t\tOPT__QUIET(&opts.quiet),\n \t\tOPT_STRING('b', NULL, &opts.new_branch, \"new branch\", \"branch\"),\n+\t\tOPT_STRING('d', \"id\", &opts.file_id, \"FILE_ID\", \"file id\"),\n \t\tOPT_BOOLEAN('l', NULL, &opts.new_branch_log, \"log for new branch\"),\n \t\tOPT_SET_INT('t', \"track\",  &opts.track, \"track\",\n \t\t\tBRANCH_TRACK_EXPLICIT),\n@@ -597,6 +599,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\tOPT_END(),\n \t};\n \tint has_dash_dash;\n+\tchar **new_argv;\n \n \tmemset(&opts, 0, sizeof(opts));\n \tmemset(&new, 0, sizeof(new));\n@@ -608,9 +611,14 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \targc = parse_options(argc, argv, prefix, options, checkout_usage,\n \t\t\t     PARSE_OPT_KEEP_DASHDASH);\n \n+\tif (opts.file_id)\n+\t\tnew_argv = (char **) expand_file_ids(opts.file_id, &argc, (char **) argv);\n+\telse\n+\t\tnew_argv = (char **) argv;\n+\n \t/* --track without -b should DWIM */\n \tif (0 < opts.track && !opts.new_branch) {\n-\t\tconst char *argv0 = argv[0];\n+\t\tconst char *argv0 = new_argv[0];\n \t\tif (!argc || !strcmp(argv0, \"--\"))\n \t\t\tdie (\"--track needs a branch name\");\n \t\tif (!prefixcmp(argv0, \"refs/\"))\n@@ -655,14 +663,14 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t *\n \t */\n \tif (argc) {\n-\t\tif (!strcmp(argv[0], \"--\")) {       /* case (2) */\n-\t\t\targv++;\n+\t\tif (!strcmp(new_argv[0], \"--\")) {       /* case (2) */\n+\t\t\tnew_argv++;\n \t\t\targc--;\n \t\t\tgoto no_reference;\n \t\t}\n \n-\t\targ = argv[0];\n-\t\thas_dash_dash = (argc > 1) && !strcmp(argv[1], \"--\");\n+\t\targ = new_argv[0];\n+\t\thas_dash_dash = (argc > 1) && !strcmp(new_argv[1], \"--\");\n \n \t\tif (!strcmp(arg, \"-\"))\n \t\t\targ = \"@{-1}\";\n@@ -674,7 +682,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\t}\n \n \t\t/* we can't end up being in (2) anymore, eat the argument */\n-\t\targv++;\n+\t\tnew_argv++;\n \t\targc--;\n \n \t\tnew.name = arg;\n@@ -702,14 +710,14 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\t\t\tverify_non_filename(NULL, arg);\n \t\t}\n \t\telse {\n-\t\t\targv++;\n+\t\t\tnew_argv++;\n \t\t\targc--;\n \t\t}\n \t}\n \n no_reference:\n \tif (argc) {\n-\t\tconst char **pathspec = get_pathspec(prefix, argv);\n+\t\tconst char **pathspec = get_pathspec(prefix, (const char **) new_argv);\n \n \t\tif (!pathspec)\n \t\t\tdie(\"invalid path specification\");\n@@ -717,7 +725,7 @@ no_reference:\n \t\t/* Checkout paths */\n \t\tif (opts.new_branch) {\n \t\t\tif (argc == 1) {\n-\t\t\t\tdie(\"git checkout: updating paths is incompatible with switching branches.\\nDid you intend to checkout '%s' which can not be resolved as commit?\", argv[0]);\n+\t\t\t\tdie(\"git checkout: updating paths is incompatible with switching branches.\\nDid you intend to checkout '%s' which can not be resolved as commit?\", new_argv[0]);\n \t\t\t} else {\n \t\t\t\tdie(\"git checkout: updating paths is incompatible with switching branches.\");\n \t\t\t}\n-- \n1.6.4.13.ge6580\n"},{"id":"119599","messageId":"1249465906-3940-5-git-send-email-ayiehere@gmail.com","threadId":"20399","inReplyTo":"1249465906-3940-4-git-send-email-ayiehere@gmail.com","subject":"[PATCH 4/6] Teach --d to \"git commit\"","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2009-08-05T09:51:44Z","receivedAt":"2009-08-05T09:51:44Z","isPatch":true,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"---\n builtin-commit.c |    4 +++-\n 1 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 4bcce06..a0bda66 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -50,7 +50,7 @@ static const char *logfile, *force_author;\n static const char *template_file;\n static char *edit_message, *use_message;\n static char *author_name, *author_email, *author_date;\n-static int all, edit_flag, also, interactive, only, amend, signoff;\n+static int all, edit_flag, also, interactive, only, amend, signoff, id_flag;\n static int quiet, verbose, no_verify, allow_empty;\n static char *untracked_files_arg;\n /*\n@@ -96,6 +96,7 @@ static struct option builtin_commit_options[] = {\n \tOPT_BOOLEAN('s', \"signoff\", &signoff, \"add Signed-off-by:\"),\n \tOPT_FILENAME('t', \"template\", &template_file, \"use specified template file\"),\n \tOPT_BOOLEAN('e', \"edit\", &edit_flag, \"force edit of commit\"),\n+\tOPT_BOOLEAN('d', \"id\", &id_flag, \"show file id\"),\n \n \tOPT_GROUP(\"Commit contents options\"),\n \tOPT_BOOLEAN('a', \"all\", &all, \"commit all changed files\"),\n@@ -352,6 +353,7 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int\n \t\ts.reference = \"HEAD^1\";\n \t}\n \ts.verbose = verbose;\n+\ts.show_file_id = id_flag;\n \ts.untracked = (show_untracked_files == SHOW_ALL_UNTRACKED_FILES);\n \ts.index_file = index_file;\n \ts.fp = fp;\n-- \n1.6.4.13.ge6580\n"},{"id":"119596","messageId":"1249465906-3940-6-git-send-email-ayiehere@gmail.com","threadId":"20399","inReplyTo":"1249465906-3940-5-git-send-email-ayiehere@gmail.com","subject":"[PATCH 5/6] Teach --id to \"git rm\"","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2009-08-05T09:51:45Z","receivedAt":"2009-08-05T09:51:45Z","isPatch":true,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"---\n builtin-rm.c |   11 ++++++++++-\n 1 files changed, 10 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin-rm.c b/builtin-rm.c\nindex 57975db..d2982a0 100644\n--- a/builtin-rm.c\n+++ b/builtin-rm.c\n@@ -137,6 +137,7 @@ static struct lock_file lock_file;\n \n static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;\n static int ignore_unmatch = 0;\n+static const char *file_id;\n \n static struct option builtin_rm_options[] = {\n \tOPT__DRY_RUN(&show_only),\n@@ -146,6 +147,7 @@ static struct option builtin_rm_options[] = {\n \tOPT_BOOLEAN('r', NULL,             &recursive,  \"allow recursive removal\"),\n \tOPT_BOOLEAN( 0 , \"ignore-unmatch\", &ignore_unmatch,\n \t\t\t\t\"exit with a zero status even if nothing matched\"),\n+\tOPT_STRING('d', \"id\", &file_id, \"FILE_ID\", \"file id\"),\n \tOPT_END(),\n };\n \n@@ -154,11 +156,18 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \tint i, newfd;\n \tconst char **pathspec;\n \tchar *seen;\n+\tchar **new_argv;\n \n \tgit_config(git_default_config, NULL);\n \n \targc = parse_options(argc, argv, prefix, builtin_rm_options,\n \t\t\t     builtin_rm_usage, 0);\n+\n+\tif (file_id)\n+\t\tnew_argv = (char **) expand_file_ids(file_id, &argc, (char **) argv);\n+\telse\n+\t\tnew_argv = (char **) argv;\n+\n \tif (!argc)\n \t\tusage_with_options(builtin_rm_usage, builtin_rm_options);\n \n@@ -171,7 +180,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \t\tdie(\"index file corrupt\");\n \trefresh_cache(REFRESH_QUIET);\n \n-\tpathspec = get_pathspec(prefix, argv);\n+\tpathspec = get_pathspec(prefix, (const char **) new_argv);\n \tseen = NULL;\n \tfor (i = 0; pathspec[i] ; i++)\n \t\t/* nothing */;\n-- \n1.6.4.13.ge6580\n"},{"id":"119597","messageId":"1249465906-3940-7-git-send-email-ayiehere@gmail.com","threadId":"20399","inReplyTo":"1249465906-3940-6-git-send-email-ayiehere@gmail.com","subject":"[PATCH 6/6] Teach --id to \"git reset\"","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2009-08-05T09:51:46Z","receivedAt":"2009-08-05T09:51:46Z","isPatch":true,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"---\n builtin-reset.c |   32 ++++++++++++++++++++------------\n 1 files changed, 20 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin-reset.c b/builtin-reset.c\nindex 5fa1789..cad5cf5 100644\n--- a/builtin-reset.c\n+++ b/builtin-reset.c\n@@ -183,6 +183,8 @@ static void prepend_reflog_action(const char *action, char *buf, size_t size)\n int cmd_reset(int argc, const char **argv, const char *prefix)\n {\n \tint i = 0, reset_type = NONE, update_ref_status = 0, quiet = 0;\n+\tchar *file_id;\n+\tchar **new_argv;\n \tconst char *rev = \"HEAD\";\n \tunsigned char sha1[20], *orig = NULL, sha1_orig[20],\n \t\t\t\t*old_orig = NULL, sha1_old_orig[20];\n@@ -198,6 +200,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\t\t\t\"reset HEAD, index and working tree\", MERGE),\n \t\tOPT_BOOLEAN('q', NULL, &quiet,\n \t\t\t\t\"disable showing new HEAD in hard reset and progress message\"),\n+\t\tOPT_STRING('d', \"id\", &file_id, \"FILE_ID\", \"file id\"),\n \t\tOPT_END()\n \t};\n \n@@ -205,7 +208,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \n \targc = parse_options(argc, argv, prefix, options, git_reset_usage,\n \t\t\t\t\t\tPARSE_OPT_KEEP_DASHDASH);\n-\treflog_action = args_to_str(argv);\n+\tif (file_id)\n+\t\tnew_argv = (char **) expand_file_ids(file_id, &argc, (char **) argv);\n+\telse\n+\t\tnew_argv = (char **) argv;\n+\n+\treflog_action = args_to_str((const char **) new_argv);\n \tsetenv(\"GIT_REFLOG_ACTION\", reflog_action, 0);\n \n \t/*\n@@ -216,30 +224,30 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t * git reset [-opts] -- <paths>...\n \t * git reset [-opts] <paths>...\n \t *\n-\t * At this point, argv[i] points immediately after [-opts].\n+\t * At this point, new_argv[i] points immediately after [-opts].\n \t */\n \n \tif (i < argc) {\n-\t\tif (!strcmp(argv[i], \"--\")) {\n+\t\tif (!strcmp(new_argv[i], \"--\")) {\n \t\t\ti++; /* reset to HEAD, possibly with paths */\n-\t\t} else if (i + 1 < argc && !strcmp(argv[i+1], \"--\")) {\n-\t\t\trev = argv[i];\n+\t\t} else if (i + 1 < argc && !strcmp(new_argv[i+1], \"--\")) {\n+\t\t\trev = new_argv[i];\n \t\t\ti += 2;\n \t\t}\n \t\t/*\n-\t\t * Otherwise, argv[i] could be either <rev> or <paths> and\n+\t\t * Otherwise, new_argv[i] could be either <rev> or <paths> and\n \t\t * has to be unambiguous.\n \t\t */\n-\t\telse if (!get_sha1(argv[i], sha1)) {\n+\t\telse if (!get_sha1(new_argv[i], sha1)) {\n \t\t\t/*\n-\t\t\t * Ok, argv[i] looks like a rev; it should not\n+\t\t\t * Ok, new_argv[i] looks like a rev; it should not\n \t\t\t * be a filename.\n \t\t\t */\n-\t\t\tverify_non_filename(prefix, argv[i]);\n-\t\t\trev = argv[i++];\n+\t\t\tverify_non_filename(prefix, new_argv[i]);\n+\t\t\trev = new_argv[i++];\n \t\t} else {\n \t\t\t/* Otherwise we treat this as a filename */\n-\t\t\tverify_filename(prefix, argv[i]);\n+\t\t\tverify_filename(prefix, new_argv[i]);\n \t\t}\n \t}\n \n@@ -260,7 +268,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)\n \t\telse if (reset_type != NONE)\n \t\t\tdie(\"Cannot do %s reset with paths.\",\n \t\t\t\t\treset_type_names[reset_type]);\n-\t\treturn read_from_tree(prefix, argv + i, sha1,\n+\t\treturn read_from_tree(prefix, (const char **) argv + i, sha1,\n \t\t\t\tquiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED);\n \t}\n \tif (reset_type == NONE)\n-- \n1.6.4.13.ge6580\n"},{"id":"119604","messageId":"4A795922.6090908@op5.se","threadId":"20399","inReplyTo":"1249465906-3940-1-git-send-email-ayiehere@gmail.com","subject":"Re: [PATCH] RFC - Say goodbye to the rodent","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2009-08-05T10:04:18Z","receivedAt":"2009-08-05T10:04:18Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Nazri Ramliy wrote:\n> \n> What do you guys think about this new approach of \"cut-and-paste\" from the\n> command line?\n> \n\nDunno, really. Tab-completion's working just fine for me, so I doubt I'll\nuse it. It's definitely novel, but how much aggravation will it cause if\nnot all file-managing programs support it?\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n\nConsidering the successes of the wars on alcohol, poverty, drugs and\nterror, I think we should give some serious thought to declaring war\non peace.\n"},{"id":"119608","messageId":"vpqljlycw77.fsf@bauges.imag.fr","threadId":"20399","inReplyTo":"1249465906-3940-1-git-send-email-ayiehere@gmail.com","subject":"Re: [PATCH] RFC - Say goodbye to the rodent","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2009-08-05T11:54:36Z","receivedAt":"2009-08-05T11:54:36Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Nazri Ramliy <ayiehere@gmail.com> writes:\n\n> Oftentimes I get tired of moving my hand away from the comfort of the home rows\n> of my keybard in order to grab the mouse to highlight the files that I'd like\n> to operate on.\n\nUsually, when you cut-and-paste from $(git status), it's to run a\nstaging/unstaging command, or to view a diff.\n\nActually, \"git add -i\" is already a pretty good way of doing this,\nwith few keystrokes.\n> Example:\n>\n> $ git status --id\n> # On branch local\n> # Changed but not updated:\n> #   (use \"git add <file>...\" to update what will be committed)\n> #   (use \"git checkout -- <file>...\" to discard changes in working directory)\n> #\n> #       modified:   builtin-write-tree.c (m1)\n> #\n> # Untracked files:\n> #   (use \"git add <file>...\" to include in what will be committed)\n> #\n> #       file1.c (x1)\n> #       file2.c (x2)\n\n$ git add -i\n           staged     unstaged path\n  1:    unchanged        +1/-0 builtin-write-tree.c\n\n*** Commands ***\n  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked\n  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp\n\n> Now we can do the following:\n>\n> $ git add --id m1\n\nWhat now> u\n           staged     unstaged path\n  1:    unchanged        +1/-0 [b]uiltin-write-tree.c\nUpdate>> 1\n           staged     unstaged path\n* 1:    unchanged        +1/-0 [b]uiltin-write-tree.c\nUpdate>> \nupdated one path\n\n*** Commands ***\n  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked\n  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp\n\n> Ids are specified via the --id command line option, and can be separated with\n> commas if you want to specify more than one of them:\n>\n> $ git add --id m1,x2\n\nWhat now> a\n  1: file1.c\n  2: file2.c\nAdd untracked>> 1\n* 1: file1.c\n  2: file2.c\nAdd untracked>> 2\n* 1: file1.c\n* 2: file2.c\nAdd untracked>> \nadded 2 paths\n\nfor these examples, I have far fewer keystrokes with \"git add -i\" than\nyou have. I don't think it's worth adding yet-another-option to most\nGit commands since it doesn't really bring much IMHO.\n\n-- \nMatthieu\n"},{"id":"119646","messageId":"81b0412b0908051111g4433e12epa540e0a2f07b62b@mail.gmail.com","threadId":"20399","inReplyTo":"1249465906-3940-2-git-send-email-ayiehere@gmail.com","subject":"Re: [PATCH 1/6] Teach --id/-d to \"git status\"","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2009-08-05T18:11:59Z","receivedAt":"2009-08-05T18:11:59Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Wed, Aug 5, 2009 at 11:51, Nazri Ramliy<ayiehere@gmail.com> wrote:\n> This patch adds a unique identifier for each file shown by \"git status\".\n>\n> Subsequent operation (add/rm/checkout/commit/reset) may use these ids\n> to simplify specifying the files, provided that they are taught about\n> the --id option as well.\n\nWhat is it for?\n"},{"id":"119652","messageId":"fabb9a1e0908051125m3eecb065m5fb4ea2b55f69b91@mail.gmail.com","threadId":"20399","inReplyTo":"81b0412b0908051111g4433e12epa540e0a2f07b62b@mail.gmail.com","subject":"Re: [PATCH 1/6] Teach --id/-d to \"git status\"","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-05T18:25:43Z","receivedAt":"2009-08-05T18:25:43Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Wed, Aug 5, 2009 at 11:11, Alex Riesen<raa.lkml@gmail.com> wrote:\n> What is it for?\n\nSee [PATCH 0/6].\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"119653","messageId":"7vtz0m5d61.fsf@alter.siamese.dyndns.org","threadId":"20399","inReplyTo":"fabb9a1e0908051125m3eecb065m5fb4ea2b55f69b91@mail.gmail.com","subject":"Re: [PATCH 1/6] Teach --id/-d to \"git status\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-08-05T18:27:34Z","receivedAt":"2009-08-05T18:27:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sverre Rabbelier <srabbelier@gmail.com> writes:\n\n> On Wed, Aug 5, 2009 at 11:11, Alex Riesen<raa.lkml@gmail.com> wrote:\n>> What is it for?\n>\n> See [PATCH 0/6].\n\nSounds useless.\n"},{"id":"119654","messageId":"fabb9a1e0908051130s3cd0965cy4a5b5430ffb2b0a8@mail.gmail.com","threadId":"20399","inReplyTo":"7vtz0m5d61.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/6] Teach --id/-d to \"git status\"","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-05T18:30:05Z","receivedAt":"2009-08-05T18:30:05Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Wed, Aug 5, 2009 at 11:27, Junio C Hamano<gitster@pobox.com> wrote:\n> Sounds useless.\n\nIt's actually called \"[PATCH] RFC - Say goodbye to the rodent\"; can't\nfind it on GMane though.\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"119657","messageId":"20090805183313.GB13166@blimp.localdomain","threadId":"20399","inReplyTo":"fabb9a1e0908051125m3eecb065m5fb4ea2b55f69b91@mail.gmail.com","subject":"Re: [PATCH 1/6] Teach --id/-d to \"git status\"","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2009-08-05T18:33:13Z","receivedAt":"2009-08-05T18:33:13Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Sverre Rabbelier, Wed, Aug 05, 2009 20:25:43 +0200:\n> Heya,\n> \n> On Wed, Aug 5, 2009 at 11:11, Alex Riesen<raa.lkml@gmail.com> wrote:\n> > What is it for?\n> \n> See [PATCH 0/6].\n> \n\nComplicated solution to a non-existing problem.\n\nNazri, have you ever tried \"git gui\"? (or tig, for console?)\n"},{"id":"119658","messageId":"fabb9a1e0908051135g1f34de4ds64800aac93f2f4ac@mail.gmail.com","threadId":"20399","inReplyTo":"20090805183313.GB13166@blimp.localdomain","subject":"Re: [PATCH 1/6] Teach --id/-d to \"git status\"","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-05T18:35:53Z","receivedAt":"2009-08-05T18:35:53Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Wed, Aug 5, 2009 at 11:33, Alex Riesen<raa.lkml@gmail.com> wrote:\n> Complicated solution to a non-existing problem.\n\nThat's harsh; obviously it is an existing problem for Nazri, or they\nwouldn't have spent the time writing these patches. So at worst it's a\ncomplicated solution for an _already solved_ problem (tig, git add -i,\netc), but definitely not non-existing ;).\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"119661","messageId":"20090805190256.GA9004@coredump.intra.peff.net","threadId":"20399","inReplyTo":"1249465906-3940-1-git-send-email-ayiehere@gmail.com","subject":"Re: [PATCH] RFC - Say goodbye to the rodent","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-08-05T19:02:56Z","receivedAt":"2009-08-05T19:02:56Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Aug 05, 2009 at 05:51:40PM +0800, Nazri Ramliy wrote:\n\n> The idea is that \"git status --id\" shows a unique id for each file in\n> its output (modified/staged/unknown/etc). The ids and the\n> corresponding filenames are stored in .git/FILE_IDS. This file gets\n> overwritten everytime you run \"git status --id\"\n\nBut files _already_ have a unique id: the filename. You never say why\nthose unique ids must be cut-and-pasted using the mouse when your unique\nids would be suitable for typing, but I'll assume it's because your\nunique ids are much shorter than your filenames.\n\nThere are already two classes of solutions to this problem:\n\n  1. Make typing the filenames easier. Generally, this is accomplished\n     by tab completion. Even stock bash (and other shells) should\n     complete filenames easily, but you can also complete much more\n     using the programmable bash completion included with git.\n\n     The main advantage of this approach is that it is totally\n     generalizable. Anytime you have to input a filename, you can use\n     it.\n\n  2. Structure your workflow to iterate over the list of items to be\n     acted on, and then select actions for each item. This is what \"git\n     add -i\" does, as well as \"git mergetool\" and \"git difftool\".\n\n     This can save a lot of typing over (1), but requires a new script\n     for every such workflow (e.g., the scripts above cover only adding,\n     resolving merges, and diffing; you would need a new script to\n     iterate over files, doing \"git checkout\" on each one, for example).\n\nI think your solution is a third class, which is to assign a mapping of\nshorter ids to items that persists over multiple commands. But it's not\nclear to me where it has an advantage over the existing two solutions.\nIt is actually less general than (1), because you have to have assigned\nthe mappings beforehand. But it is not nearly as convenient as (2).\n\nIn addition, it's more complicated to implement and use, because you\nhave to care about the persistence of the mapping (i.e., how long does\nit last, which commands reset it, etc).\n\nSo while it is somewhat clever, I don't think it is worth merging to\nmainline git; it introduces complexity to solve a problem that already\nhas overlapping solutions.\n\n-Peff\n"},{"id":"119668","messageId":"alpine.LFD.2.00.0908051558220.16073@xanadu.home","threadId":"20399","inReplyTo":"20090805190256.GA9004@coredump.intra.peff.net","subject":"Re: [PATCH] RFC - Say goodbye to the rodent","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2009-08-05T20:01:20Z","receivedAt":"2009-08-05T20:01:20Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Wed, 5 Aug 2009, Jeff King wrote:\n\n> On Wed, Aug 05, 2009 at 05:51:40PM +0800, Nazri Ramliy wrote:\n> \n> > The idea is that \"git status --id\" shows a unique id for each file in\n> > its output (modified/staged/unknown/etc). The ids and the\n> > corresponding filenames are stored in .git/FILE_IDS. This file gets\n> > overwritten everytime you run \"git status --id\"\n> \n> But files _already_ have a unique id: the filename. You never say why\n> those unique ids must be cut-and-pasted using the mouse when your unique\n> ids would be suitable for typing, but I'll assume it's because your\n> unique ids are much shorter than your filenames.\n> \n> There are already two classes of solutions to this problem:\n> \n>   1. Make typing the filenames easier. Generally, this is accomplished\n>      by tab completion. Even stock bash (and other shells) should\n>      complete filenames easily, but you can also complete much more\n>      using the programmable bash completion included with git.\n> \n>      The main advantage of this approach is that it is totally\n>      generalizable. Anytime you have to input a filename, you can use\n>      it.\n> \n>   2. Structure your workflow to iterate over the list of items to be\n>      acted on, and then select actions for each item. This is what \"git\n>      add -i\" does, as well as \"git mergetool\" and \"git difftool\".\n> \n>      This can save a lot of typing over (1), but requires a new script\n>      for every such workflow (e.g., the scripts above cover only adding,\n>      resolving merges, and diffing; you would need a new script to\n>      iterate over files, doing \"git checkout\" on each one, for example).\n\nBTW I often use this incantation:\n\n\txargs git add\n\t[paste list of files obtained from git status output]\n\t^D\n\n\nNicolas\n"}]}