Introduce a new revision set operator <rev>^!

This is a shorthand for "<rev> --not <rev>^@", i.e. "include
this commit but exclude any of its parents".

When a new file $F is introduced by revision $R, this notation
can be used to find a copy-and-paste from existing file in the
parents of that revision without annotating the ancestry of the
lines that were copied from:

	git pickaxe -f -C $R^! -- $F

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2006-10-31 14:22:34 -08:00
Родитель 0d981c67d8
Коммит 62476c8e33
3 изменённых файлов: 55 добавлений и 3 удалений

Просмотреть файл

@ -111,6 +111,44 @@ The contents of the actual line is output after the above
header, prefixed by a TAB. This is to allow adding more header, prefixed by a TAB. This is to allow adding more
header elements later. header elements later.
SPECIFIYING RANGES
------------------
Unlike `git-blame` and `git-annotate` in older git, the extent
of annotation can be limited to both line ranges and revision
ranges. When you are interested in finding the origin for
ll. 40-60 for file `foo`, you can use `-L` option like this:
git pickaxe -L 40,60 foo
When you are not interested in changes older than the version
v2.6.18, or changes older than 3 weeks, you can use revision
range specifiers similar to `git-rev-list`:
git pickaxe v2.6.18.. -- foo
git pickaxe --since=3.weeks -- foo
When revision range specifiers are used to limit the annotation,
lines that have not changed since the range boundary (either the
commit v2.6.18 or the most recent commit that is more than 3
weeks old in the above example) are blamed for that range
boundary commit.
A particularly useful way is to see if an added file have lines
created by copy-and-paste from existing files. Sometimes this
indicates that the developer was being sloppy and did not
refactor the code properly. You can first find the commit that
introduced the file with:
git log --diff-filter=A --pretty=short -- foo
and then annotate the change between the commit and its
parents, using `commit{caret}!` notation:
git pickaxe -C -C -f $commit^! -- foo
SEE ALSO SEE ALSO
-------- --------
gitlink:git-blame[1] gitlink:git-blame[1]

Просмотреть файл

@ -222,14 +222,21 @@ of `r1` and `r2` and is defined as
It it the set of commits that are reachable from either one of It it the set of commits that are reachable from either one of
`r1` or `r2` but not from both. `r1` or `r2` but not from both.
Here are a few examples: Two other shorthands for naming a set that is formed by a commit
and its parent commits exists. `r1{caret}@` notation means all
parents of `r1`. `r1{caret}!` includes commit `r1` but excludes
its all parents.
Here are a handful examples:
D A B D D A B D
D F A B C D F D F A B C D F
^A G B D ^A G B D
^A F B C F ^A F B C F
G...I C D F G I G...I C D F G I
^B G I C D F G I ^B G I C D F G I
F^@ A B C
F^! H D F H
Author Author
------ ------

Просмотреть файл

@ -660,6 +660,13 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
return 0; return 0;
*dotdot = '^'; *dotdot = '^';
} }
dotdot = strstr(arg, "^!");
if (dotdot && !dotdot[2]) {
*dotdot = 0;
if (!add_parents_only(revs, arg, flags ^ UNINTERESTING))
*dotdot = '^';
}
local_flags = 0; local_flags = 0;
if (*arg == '^') { if (*arg == '^') {
local_flags = UNINTERESTING; local_flags = UNINTERESTING;