зеркало из https://github.com/microsoft/git.git
Add '...' operator for revisions
'A...B' is a shortcut for 'A B --not $(git-merge-base --all A B)'. This XOR-like operation is called symmetric difference in set theory. The symbol '...' has been chosen because it's rather similar to the existing '..' operator and the somewhat more natural caret ('^') is already taken. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Родитель
31609c1725
Коммит
0d2c9d67d9
|
@ -15,6 +15,7 @@ SYNOPSIS
|
|||
[ \--sparse ]
|
||||
[ \--no-merges ]
|
||||
[ \--remove-empty ]
|
||||
[ \--not ]
|
||||
[ \--all ]
|
||||
[ \--topo-order ]
|
||||
[ \--parents ]
|
||||
|
@ -37,6 +38,14 @@ not in 'baz'".
|
|||
A special notation <commit1>..<commit2> can be used as a
|
||||
short-hand for {caret}<commit1> <commit2>.
|
||||
|
||||
Another special notation is <commit1>...<commit2> which is useful for
|
||||
merges. The resulting set of commits is the symmetric difference
|
||||
between the two operands. The following two commands are equivalent:
|
||||
|
||||
------------
|
||||
$ git-rev-list A B --not $(git-merge-base --all A B)
|
||||
$ git-rev-list A...B
|
||||
------------
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
@ -93,6 +102,11 @@ OPTIONS
|
|||
--remove-empty::
|
||||
Stop when a given path disappears from the tree.
|
||||
|
||||
--not::
|
||||
Reverses the meaning of the '{caret}' prefix (or lack
|
||||
thereof) for all following revision specifiers, up to
|
||||
the next `--not`.
|
||||
|
||||
--all::
|
||||
Pretend as if all the refs in `$GIT_DIR/refs/` are
|
||||
listed on the command line as <commit>.
|
||||
|
|
46
revision.c
46
revision.c
|
@ -536,6 +536,18 @@ void init_revisions(struct rev_info *revs)
|
|||
diff_setup(&revs->diffopt);
|
||||
}
|
||||
|
||||
static void add_pending_commit_list(struct rev_info *revs,
|
||||
struct commit_list *commit_list,
|
||||
unsigned int flags)
|
||||
{
|
||||
while (commit_list) {
|
||||
struct object *object = &commit_list->item->object;
|
||||
object->flags |= flags;
|
||||
add_pending_object(revs, object, sha1_to_hex(object->sha1));
|
||||
commit_list = commit_list->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse revision information, filling in the "rev_info" structure,
|
||||
* and removing the used arguments from the argument list.
|
||||
|
@ -771,27 +783,45 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
|
|||
unsigned char from_sha1[20];
|
||||
const char *next = dotdot + 2;
|
||||
const char *this = arg;
|
||||
int symmetric = *next == '.';
|
||||
unsigned int flags_exclude = flags ^ UNINTERESTING;
|
||||
|
||||
*dotdot = 0;
|
||||
next += symmetric;
|
||||
|
||||
if (!*next)
|
||||
next = "HEAD";
|
||||
if (dotdot == arg)
|
||||
this = "HEAD";
|
||||
if (!get_sha1(this, from_sha1) &&
|
||||
!get_sha1(next, sha1)) {
|
||||
struct object *exclude;
|
||||
struct object *include;
|
||||
struct commit *a, *b;
|
||||
struct commit_list *exclude;
|
||||
|
||||
exclude = get_reference(revs, this, from_sha1, flags ^ UNINTERESTING);
|
||||
include = get_reference(revs, next, sha1, flags);
|
||||
if (!exclude || !include)
|
||||
die("Invalid revision range %s..%s", arg, next);
|
||||
a = lookup_commit_reference(from_sha1);
|
||||
b = lookup_commit_reference(sha1);
|
||||
if (!a || !b) {
|
||||
die(symmetric ?
|
||||
"Invalid symmetric difference expression %s...%s" :
|
||||
"Invalid revision range %s..%s",
|
||||
arg, next);
|
||||
}
|
||||
|
||||
if (!seen_dashdash) {
|
||||
*dotdot = '.';
|
||||
verify_non_filename(revs->prefix, arg);
|
||||
}
|
||||
add_pending_object(revs, exclude, this);
|
||||
add_pending_object(revs, include, next);
|
||||
|
||||
if (symmetric) {
|
||||
exclude = get_merge_bases_clean(a, b);
|
||||
add_pending_commit_list(revs, exclude,
|
||||
flags_exclude);
|
||||
a->object.flags |= flags;
|
||||
} else
|
||||
a->object.flags |= flags_exclude;
|
||||
b->object.flags |= flags;
|
||||
add_pending_object(revs, &a->object, this);
|
||||
add_pending_object(revs, &b->object, next);
|
||||
continue;
|
||||
}
|
||||
*dotdot = '.';
|
||||
|
|
Загрузка…
Ссылка в новой задаче