зеркало из https://github.com/microsoft/git.git
Teach "git reflog" a subcommand to delete single entries
This commit implements the "delete" subcommand: git reflog delete master@{2} will delete the second reflog entry of the "master" branch. With this, it should be easy to implement "git stash pop" everybody seems to want these days. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
Родитель
207f1a75e7
Коммит
552cecc214
|
@ -19,6 +19,8 @@ depending on the subcommand:
|
|||
git reflog expire [--dry-run] [--stale-fix] [--verbose]
|
||||
[--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...
|
||||
|
||||
git reflog delete ref@\{specifier\}...
|
||||
|
||||
git reflog [show] [log-options]
|
||||
|
||||
Reflog is a mechanism to record when the tip of branches are
|
||||
|
@ -36,6 +38,9 @@ subcommands) will take all the normal log options, and show the log of
|
|||
It is basically an alias for 'git log -g --abbrev-commit
|
||||
--pretty=oneline', see gitlink:git-log[1].
|
||||
|
||||
To delete single entries from the reflog, use the subcommand "delete"
|
||||
and specify the _exact_ entry (e.g. ``git reflog delete master@\{2\}'').
|
||||
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
|
|
@ -25,6 +25,7 @@ struct cmd_reflog_expire_cb {
|
|||
int verbose;
|
||||
unsigned long expire_total;
|
||||
unsigned long expire_unreachable;
|
||||
int recno;
|
||||
};
|
||||
|
||||
struct expire_reflog_cb {
|
||||
|
@ -220,6 +221,9 @@ static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
|||
goto prune;
|
||||
}
|
||||
|
||||
if (cb->cmd->recno && --(cb->cmd->recno) == 0)
|
||||
goto prune;
|
||||
|
||||
if (cb->newlog) {
|
||||
char sign = (tz < 0) ? '-' : '+';
|
||||
int zone = (tz < 0) ? (-tz) : tz;
|
||||
|
@ -363,6 +367,58 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
|
|||
return status;
|
||||
}
|
||||
|
||||
static int count_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
|
||||
const char *email, unsigned long timestamp, int tz,
|
||||
const char *message, void *cb_data)
|
||||
{
|
||||
struct cmd_reflog_expire_cb *cb = cb_data;
|
||||
if (!cb->expire_total || timestamp < cb->expire_total)
|
||||
cb->recno++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct cmd_reflog_expire_cb cb;
|
||||
int i, status = 0;
|
||||
|
||||
if (argc < 2)
|
||||
return error("Nothing to delete?");
|
||||
|
||||
memset(&cb, 0, sizeof(cb));
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *spec = strstr(argv[i], "@{");
|
||||
unsigned char sha1[20];
|
||||
char *ep, *ref;
|
||||
int recno;
|
||||
|
||||
if (!spec) {
|
||||
status |= error("Not a reflog: %s", ref);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dwim_ref(argv[i], spec - argv[i], sha1, &ref)) {
|
||||
status |= error("%s points nowhere!", argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
recno = strtoul(spec + 2, &ep, 10);
|
||||
if (*ep == '}') {
|
||||
cb.recno = -recno;
|
||||
for_each_reflog_ent(ref, count_reflog_ent, &cb);
|
||||
} else {
|
||||
cb.expire_total = approxidate(spec + 2);
|
||||
for_each_reflog_ent(ref, count_reflog_ent, &cb);
|
||||
cb.expire_total = 0;
|
||||
}
|
||||
|
||||
status |= expire_reflog(ref, sha1, 0, &cb);
|
||||
free(ref);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* main "reflog"
|
||||
*/
|
||||
|
@ -382,6 +438,9 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)
|
|||
if (!strcmp(argv[1], "expire"))
|
||||
return cmd_reflog_expire(argc - 1, argv + 1, prefix);
|
||||
|
||||
if (!strcmp(argv[1], "delete"))
|
||||
return cmd_reflog_delete(argc - 1, argv + 1, prefix);
|
||||
|
||||
/* Not a recognized reflog command..*/
|
||||
usage(reflog_usage);
|
||||
}
|
||||
|
|
|
@ -175,4 +175,30 @@ test_expect_success 'recover and check' '
|
|||
|
||||
'
|
||||
|
||||
test_expect_success 'delete' '
|
||||
echo 1 > C &&
|
||||
test_tick &&
|
||||
git commit -m rat C &&
|
||||
|
||||
echo 2 > C &&
|
||||
test_tick &&
|
||||
git commit -m ox C &&
|
||||
|
||||
echo 3 > C &&
|
||||
test_tick &&
|
||||
git commit -m tiger C &&
|
||||
|
||||
test 5 = $(git reflog | wc -l) &&
|
||||
|
||||
git reflog delete master@{1} &&
|
||||
git reflog show master > output &&
|
||||
test 4 = $(wc -l < output) &&
|
||||
! grep ox < output &&
|
||||
|
||||
git reflog delete master@{07.04.2005.15:15:00.-0700} &&
|
||||
git reflog show master > output &&
|
||||
test 3 = $(wc -l < output) &&
|
||||
! grep dragon < output
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Загрузка…
Ссылка в новой задаче