{"thread":{"id":"10337","subject":"[PATCH] Teach \"git reflog\" a subcommand to delete single entries","startedAt":"2007-10-17T01:50:45Z","lastAt":"2007-10-17T09:24:50Z","messageCount":2,"participants":["Johannes Schindelin","Wincent Colaiuta"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"56173","messageId":"Pine.LNX.4.64.0710170249260.25221@racer.site","threadId":"10337","inReplyTo":null,"subject":"[PATCH] Teach \"git reflog\" a subcommand to delete single entries","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-10-17T01:50:45Z","receivedAt":"2007-10-17T01:50:45Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis commit implements the \"delete\" subcommand:\n\n\tgit reflog delete master@{2}\n\nwill delete the second reflog entry of the \"master\" branch.\n\nWith this, it should be easy to implement \"git stash pop\" everybody\nseems to want these days.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/git-reflog.txt |    5 +++\n builtin-reflog.c             |   59 ++++++++++++++++++++++++++++++++++++++++++\n t/t1410-reflog.sh            |   26 ++++++++++++++++++\n 3 files changed, 90 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt\nindex 5c7316c..a0c7cee 100644\n--- a/Documentation/git-reflog.txt\n+++ b/Documentation/git-reflog.txt\n@@ -19,6 +19,8 @@ depending on the subcommand:\n git reflog expire [--dry-run] [--stale-fix] [--verbose]\n \t[--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...\n \n+git reflog delete ref@\\{specifier\\}...\n+\n git reflog [show] [log-options]\n \n Reflog is a mechanism to record when the tip of branches are\n@@ -36,6 +38,9 @@ subcommands) will take all the normal log options, and show the log of\n It is basically an alias for 'git log -g --abbrev-commit\n --pretty=oneline', see gitlink:git-log[1].\n \n+To delete single entries from the reflog, use the subcommand \"delete\"\n+and specify the _exact_ entry (e.g. ``git reflog delete master@\\{2\\}'').\n+\n \n OPTIONS\n -------\ndiff --git a/builtin-reflog.c b/builtin-reflog.c\nindex ce093ca..f422693 100644\n--- a/builtin-reflog.c\n+++ b/builtin-reflog.c\n@@ -25,6 +25,7 @@ struct cmd_reflog_expire_cb {\n \tint verbose;\n \tunsigned long expire_total;\n \tunsigned long expire_unreachable;\n+\tint recno;\n };\n \n struct expire_reflog_cb {\n@@ -220,6 +221,9 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,\n \t\t\tgoto prune;\n \t}\n \n+\tif (cb->cmd->recno && --(cb->cmd->recno) == 0)\n+\t\tgoto prune;\n+\n \tif (cb->newlog) {\n \t\tchar sign = (tz < 0) ? '-' : '+';\n \t\tint zone = (tz < 0) ? (-tz) : tz;\n@@ -363,6 +367,58 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)\n \treturn status;\n }\n \n+static int count_reflog_ent(unsigned char *osha1, unsigned char *nsha1,\n+\t\tconst char *email, unsigned long timestamp, int tz,\n+\t\tconst char *message, void *cb_data)\n+{\n+\tstruct cmd_reflog_expire_cb *cb = cb_data;\n+\tif (!cb->expire_total || timestamp < cb->expire_total)\n+\t\tcb->recno++;\n+\treturn 0;\n+}\n+\n+static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)\n+{\n+\tstruct cmd_reflog_expire_cb cb;\n+\tint i, status = 0;\n+\n+\tif (argc < 2)\n+\t\treturn error(\"Nothing to delete?\");\n+\n+\tmemset(&cb, 0, sizeof(cb));\n+\n+\tfor (i = 1; i < argc; i++) {\n+\t\tconst char *spec = strstr(argv[i], \"@{\");\n+\t\tunsigned char sha1[20];\n+\t\tchar *ep, *ref;\n+\t\tint recno;\n+\n+\t\tif (!spec) {\n+\t\t\tstatus |= error(\"Not a reflog: %s\", ref);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!dwim_ref(argv[i], spec - argv[i], sha1, &ref)) {\n+\t\t\tstatus |= error(\"%s points nowhere!\", argv[i]);\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\trecno = strtoul(spec + 2, &ep, 10);\n+\t\tif (*ep == '}') {\n+\t\t\tcb.recno = -recno;\n+\t\t\tfor_each_reflog_ent(ref, count_reflog_ent, &cb);\n+\t\t} else {\n+\t\t\tcb.expire_total = approxidate(spec + 2);\n+\t\t\tfor_each_reflog_ent(ref, count_reflog_ent, &cb);\n+\t\t\tcb.expire_total = 0;\n+\t\t}\n+\n+\t\tstatus |= expire_reflog(ref, sha1, 0, &cb);\n+\t\tfree(ref);\n+\t}\n+\treturn status;\n+}\n+\n /*\n  * main \"reflog\"\n  */\n@@ -382,6 +438,9 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)\n \tif (!strcmp(argv[1], \"expire\"))\n \t\treturn cmd_reflog_expire(argc - 1, argv + 1, prefix);\n \n+\tif (!strcmp(argv[1], \"delete\"))\n+\t\treturn cmd_reflog_delete(argc - 1, argv + 1, prefix);\n+\n \t/* Not a recognized reflog command..*/\n \tusage(reflog_usage);\n }\ndiff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh\nindex e5bbc38..12a53ed 100755\n--- a/t/t1410-reflog.sh\n+++ b/t/t1410-reflog.sh\n@@ -175,4 +175,30 @@ test_expect_success 'recover and check' '\n \n '\n \n+test_expect_success 'delete' '\n+\techo 1 > C &&\n+\ttest_tick &&\n+\tgit commit -m rat C &&\n+\n+\techo 2 > C &&\n+\ttest_tick &&\n+\tgit commit -m ox C &&\n+\n+\techo 3 > C &&\n+\ttest_tick &&\n+\tgit commit -m tiger C &&\n+\n+\ttest 5 = $(git reflog | wc -l) &&\n+\n+\tgit reflog delete master@{1} &&\n+\tgit reflog show master > output &&\n+\ttest 4 = $(wc -l < output) &&\n+\t! grep ox < output &&\n+\n+\tgit reflog delete master@{07.04.2005.15:15:00.-0700} &&\n+\tgit reflog show master > output &&\n+\ttest 3 = $(wc -l < output) &&\n+\t! grep dragon < output\n+'\n+\n test_done\n-- \n1.5.3.4.1223.ga973c\n"},{"id":"56225","messageId":"09CDCBB0-35F1-429C-8470-6020D481F452@wincent.com","threadId":"10337","inReplyTo":"Pine.LNX.4.64.0710170249260.25221@racer.site","subject":"Re: [PATCH] Teach \"git reflog\" a subcommand to delete single entries","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-10-17T09:24:50Z","receivedAt":"2007-10-17T09:24:50Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 17/10/2007, a las 3:50, Johannes Schindelin escribió:\n\n> This commit implements the \"delete\" subcommand:\n>\n> \tgit reflog delete master@{2}\n>\n> will delete the second reflog entry of the \"master\" branch.\n>\n> With this, it should be easy to implement \"git stash pop\" everybody\n> seems to want these days.\n\nLooks good to me. Thanks for taking the initiative, Johannes.\n\nCheers,\nWincent\n"}]}