summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <junkio@cox.net>2006-03-05 22:38:22 -0800
committerLibravatar Junio C Hamano <junkio@cox.net>2006-03-05 22:38:22 -0800
commit3bcd59a546333ae355c87577ba63f8dccd50a519 (patch)
tree8a097c34b5a520ebe1189bdb2398c599148ffeb5
parentMerge part of 'jc/pack' into 'next' (diff)
parentTweak asciidoc output to work with broken docbook-xsl (diff)
downloadtgif-3bcd59a546333ae355c87577ba63f8dccd50a519.tar.xz
Merge branch 'fd/asciidoc' into next
* fd/asciidoc: Tweak asciidoc output to work with broken docbook-xsl annotate-blame test: add evil merge. annotate-blame test: don't "source", but say "." annotate/blame tests updates. annotate: Support annotation of files on other revisions. git/Documentation: fix SYNOPSIS style bugs blame: avoid "diff -u0". git-blame: Use the same tests for git-blame as for git-annotate blame and annotate: show localtime with timezone. blame: avoid -lm by not using log(). git-blame: Make the output human readable get_revision(): do not dig deeper when we know we are at the end. documentation: add 'see also' sections to git-rm and git-add contrib/emacs/Makefile: Provide tool for byte-compiling files. gitignore: Ignore some more boring things.
-rw-r--r--.gitignore1
-rw-r--r--Documentation/asciidoc.conf10
-rw-r--r--Documentation/git-add.txt3
-rw-r--r--Documentation/git-archimport.txt2
-rw-r--r--Documentation/git-fetch-pack.txt2
-rw-r--r--Documentation/git-pack-redundant.txt2
-rw-r--r--Documentation/git-rm.txt3
-rw-r--r--Documentation/git-shell.txt2
-rw-r--r--Documentation/git-shortlog.txt2
-rw-r--r--Documentation/git-show-branch.txt6
-rw-r--r--Documentation/git-update-ref.txt2
-rw-r--r--Documentation/git-var.txt2
-rw-r--r--blame.c175
-rw-r--r--contrib/emacs/.gitignore1
-rw-r--r--contrib/emacs/Makefile20
-rwxr-xr-xgit-annotate.perl14
-rw-r--r--revision.c18
-rw-r--r--t/.gitignore1
-rw-r--r--t/annotate-tests.sh102
-rwxr-xr-xt/t8001-annotate.sh85
-rwxr-xr-xt/t8002-blame.sh9
21 files changed, 340 insertions, 122 deletions
diff --git a/.gitignore b/.gitignore
index 5be239a4aa..abbc509e13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -130,3 +130,4 @@ libgit.a
*.o
*.py[co]
config.mak
+git-blame
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index fa0877d483..7ce71510de 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -18,6 +18,16 @@ ifdef::backend-docbook[]
{0#</citerefentry>}
endif::backend-docbook[]
+ifdef::backend-docbook[]
+# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
+[listingblock]
+<example><title>{title}</title>
+<literallayout>
+|
+</literallayout>
+{title#}</example>
+endif::backend-docbook[]
+
ifdef::backend-xhtml11[]
[gitlink-inlinemacro]
<a href="{target}.html">{target}{0?({0})}</a>
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 7e293834d1..5b7c354554 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -65,6 +65,9 @@ git-add git-*.sh::
(i.e. you are listing the files explicitly), it does not
add `subdir/git-foo.sh` to the index.
+See Also
+--------
+gitlink:git-rm[1]
Author
------
diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt
index 023d3ae7b9..5a13187a87 100644
--- a/Documentation/git-archimport.txt
+++ b/Documentation/git-archimport.txt
@@ -9,7 +9,7 @@ git-archimport - Import an Arch repository into git
SYNOPSIS
--------
[verse]
-`git-archimport` [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
+'git-archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
<archive/branch> [ <archive/branch> ]
DESCRIPTION
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
index b507e9b648..913b75bb8d 100644
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository.
SYNOPSIS
--------
-git-fetch-pack [-q] [-k] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
+'git-fetch-pack' [-q] [-k] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
DESCRIPTION
-----------
diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt
index 2f4cc46510..a81cb97814 100644
--- a/Documentation/git-pack-redundant.txt
+++ b/Documentation/git-pack-redundant.txt
@@ -8,7 +8,7 @@ git-pack-redundant - Program used to find redundant pack files.
SYNOPSIS
--------
-'git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >'
+'git-pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >
DESCRIPTION
-----------
diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt
index 401bfb2d9c..d8a5afae03 100644
--- a/Documentation/git-rm.txt
+++ b/Documentation/git-rm.txt
@@ -74,6 +74,9 @@ git-rm -f git-*.sh::
shell expand the asterisk (i.e. you are listing the files
explicitly), it does not remove `subdir/git-foo.sh`.
+See Also
+--------
+gitlink:git-add[1]
Author
------
diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt
index 3f4d804cca..cc4266d83b 100644
--- a/Documentation/git-shell.txt
+++ b/Documentation/git-shell.txt
@@ -8,7 +8,7 @@ git-shell - Restricted login shell for GIT over SSH only
SYNOPSIS
--------
-'git-shell -c <command> <argument>'
+'git-shell' -c <command> <argument>
DESCRIPTION
-----------
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index 65ca77fbf6..bf8db8bac6 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -8,7 +8,7 @@ git-shortlog - Summarize 'git log' output.
SYNOPSIS
--------
-'git-log --pretty=short | git shortlog'
+git-log --pretty=short | 'git-shortlog'
DESCRIPTION
-----------
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index 7b1a9c9875..e474cd0ba7 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -8,9 +8,9 @@ git-show-branch - Show branches and their commits.
SYNOPSIS
--------
[verse]
-git-show-branch [--all] [--heads] [--tags] [--topo-order] [--current]
- [--more=<n> | --list | --independent | --merge-base]
- [--no-name | --sha1-name] [<rev> | <glob>]...
+'git-show-branch' [--all] [--heads] [--tags] [--topo-order] [--current]
+ [--more=<n> | --list | --independent | --merge-base]
+ [--no-name | --sha1-name] [<rev> | <glob>]...
DESCRIPTION
-----------
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 69715aa061..475237f19e 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -7,7 +7,7 @@ git-update-ref - update the object name stored in a ref safely
SYNOPSIS
--------
-`git-update-ref` <ref> <newvalue> [<oldvalue>]
+'git-update-ref' <ref> <newvalue> [<oldvalue>]
DESCRIPTION
-----------
diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt
index c22d34f5fb..90cb157be5 100644
--- a/Documentation/git-var.txt
+++ b/Documentation/git-var.txt
@@ -8,7 +8,7 @@ git-var - Print the git users identity
SYNOPSIS
--------
-git-var [ -l | <variable> ]
+'git-var' [ -l | <variable> ]
DESCRIPTION
-----------
diff --git a/blame.c b/blame.c
index 562940eced..fca22f9000 100644
--- a/blame.c
+++ b/blame.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <time.h>
#include <sys/time.h>
+#include <math.h>
#include "cache.h"
#include "refs.h"
@@ -17,8 +18,15 @@
#define DEBUG 0
-struct commit **blame_lines;
-int num_blame_lines;
+static const char blame_usage[] = "[-c] [-l] [--] file [commit]\n"
+ " -c, --compability Use the same output mode as git-annotate (Default: off)\n"
+ " -l, --long Show long commit SHA1 (Default: off)\n"
+ " -h, --help This message";
+
+static struct commit **blame_lines;
+static int num_blame_lines;
+static char* blame_contents;
+static int blame_len;
struct util_info {
int *line_map;
@@ -84,7 +92,7 @@ static struct patch *get_patch(struct commit *commit, struct commit *other)
die("write failed: %s", strerror(errno));
close(fd);
- sprintf(diff_cmd, "diff -u0 %s %s", tmp_path1, tmp_path2);
+ sprintf(diff_cmd, "diff -u -U 0 %s %s", tmp_path1, tmp_path2);
fin = popen(diff_cmd, "r");
if (!fin)
die("popen failed: %s", strerror(errno));
@@ -390,9 +398,8 @@ static void init_first_commit(struct commit* commit, const char* filename)
alloc_line_map(commit);
util = commit->object.util;
- num_blame_lines = util->num_lines;
- for (i = 0; i < num_blame_lines; i++)
+ for (i = 0; i < util->num_lines; i++)
util->line_map[i] = i;
}
@@ -414,6 +421,9 @@ static void process_commits(struct rev_info *rev, const char *path,
util = commit->object.util;
num_blame_lines = util->num_lines;
blame_lines = xmalloc(sizeof(struct commit *) * num_blame_lines);
+ blame_contents = util->buf;
+ blame_len = util->size;
+
for (i = 0; i < num_blame_lines; i++)
blame_lines[i] = NULL;
@@ -501,32 +511,137 @@ static void process_commits(struct rev_info *rev, const char *path,
} while ((commit = get_revision(rev)) != NULL);
}
+struct commit_info
+{
+ char* author;
+ char* author_mail;
+ unsigned long author_time;
+ char* author_tz;
+};
+
+static void get_commit_info(struct commit* commit, struct commit_info* ret)
+{
+ int len;
+ char* tmp;
+ static char author_buf[1024];
+
+ tmp = strstr(commit->buffer, "\nauthor ") + 8;
+ len = index(tmp, '\n') - tmp;
+ ret->author = author_buf;
+ memcpy(ret->author, tmp, len);
+
+ tmp = ret->author;
+ tmp += len;
+ *tmp = 0;
+ while(*tmp != ' ')
+ tmp--;
+ ret->author_tz = tmp+1;
+
+ *tmp = 0;
+ while(*tmp != ' ')
+ tmp--;
+ ret->author_time = strtoul(tmp, NULL, 10);
+
+ *tmp = 0;
+ while(*tmp != ' ')
+ tmp--;
+ ret->author_mail = tmp + 1;
+
+ *tmp = 0;
+}
+
+static const char* format_time(unsigned long time, const char* tz_str)
+{
+ static char time_buf[128];
+ time_t t = time;
+ int minutes, tz;
+ struct tm *tm;
+
+ tz = atoi(tz_str);
+ minutes = tz < 0 ? -tz : tz;
+ minutes = (minutes / 100)*60 + (minutes % 100);
+ minutes = tz < 0 ? -minutes : minutes;
+ t = time + minutes * 60;
+ tm = gmtime(&t);
+
+ strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm);
+ strcat(time_buf, tz_str);
+ return time_buf;
+}
+
int main(int argc, const char **argv)
{
int i;
struct commit *initial = NULL;
unsigned char sha1[20];
- const char* filename;
+
+ const char *filename = NULL, *commit = NULL;
+ char filename_buf[256];
+ int sha1_len = 8;
+ int compability = 0;
+ int options = 1;
+
int num_args;
const char* args[10];
struct rev_info rev;
- setup_git_directory();
+ struct commit_info ci;
+ const char *buf;
+ int max_digits;
- if (argc != 3)
- die("Usage: blame commit-ish file");
+ const char* prefix = setup_git_directory();
+ for(i = 1; i < argc; i++) {
+ if(options) {
+ if(!strcmp(argv[i], "-h") ||
+ !strcmp(argv[i], "--help"))
+ usage(blame_usage);
+ else if(!strcmp(argv[i], "-l") ||
+ !strcmp(argv[i], "--long")) {
+ sha1_len = 40;
+ continue;
+ } else if(!strcmp(argv[i], "-c") ||
+ !strcmp(argv[i], "--compability")) {
+ compability = 1;
+ continue;
+ } else if(!strcmp(argv[i], "--")) {
+ options = 0;
+ continue;
+ } else if(argv[i][0] == '-')
+ usage(blame_usage);
+ else
+ options = 0;
+ }
- filename = argv[2];
+ if(!options) {
+ if(!filename)
+ filename = argv[i];
+ else if(!commit)
+ commit = argv[i];
+ else
+ usage(blame_usage);
+ }
+ }
+
+ if(!filename)
+ usage(blame_usage);
+ if(!commit)
+ commit = "HEAD";
+
+ if(prefix)
+ sprintf(filename_buf, "%s%s", prefix, filename);
+ else
+ strcpy(filename_buf, filename);
+ filename = filename_buf;
{
- struct commit* commit;
- if (get_sha1(argv[1], sha1))
- die("get_sha1 failed");
- commit = lookup_commit_reference(sha1);
+ struct commit* c;
+ if (get_sha1(commit, sha1))
+ die("get_sha1 failed, commit '%s' not found", commit);
+ c = lookup_commit_reference(sha1);
- if (fill_util_info(commit, filename)) {
- printf("%s not found in %s\n", filename, argv[1]);
+ if (fill_util_info(c, filename)) {
+ printf("%s not found in %s\n", filename, commit);
return 1;
}
}
@@ -535,7 +650,7 @@ int main(int argc, const char **argv)
args[num_args++] = NULL;
args[num_args++] = "--topo-order";
args[num_args++] = "--remove-empty";
- args[num_args++] = argv[1];
+ args[num_args++] = commit;
args[num_args++] = "--";
args[num_args++] = filename;
args[num_args] = NULL;
@@ -544,13 +659,35 @@ int main(int argc, const char **argv)
prepare_revision_walk(&rev);
process_commits(&rev, filename, &initial);
+ buf = blame_contents;
+ for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++)
+ i *= 10;
+
for (i = 0; i < num_blame_lines; i++) {
struct commit *c = blame_lines[i];
if (!c)
c = initial;
- printf("%d %.8s\n", i, sha1_to_hex(c->object.sha1));
-// printf("%d %s\n", i, find_unique_abbrev(blame_lines[i]->object.sha1, 6));
+ get_commit_info(c, &ci);
+ fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
+ if(compability)
+ printf("\t(%10s\t%10s\t%d)", ci.author,
+ format_time(ci.author_time, ci.author_tz), i+1);
+ else
+ printf(" (%-15.15s %10s %*d) ", ci.author,
+ format_time(ci.author_time, ci.author_tz),
+ max_digits, i+1);
+
+ if(i == num_blame_lines - 1) {
+ fwrite(buf, blame_len - (buf - blame_contents),
+ 1, stdout);
+ if(blame_contents[blame_len-1] != '\n')
+ putc('\n', stdout);
+ } else {
+ char* next_buf = index(buf, '\n') + 1;
+ fwrite(buf, next_buf - buf, 1, stdout);
+ buf = next_buf;
+ }
}
if (DEBUG) {
diff --git a/contrib/emacs/.gitignore b/contrib/emacs/.gitignore
new file mode 100644
index 0000000000..c531d9867f
--- /dev/null
+++ b/contrib/emacs/.gitignore
@@ -0,0 +1 @@
+*.elc
diff --git a/contrib/emacs/Makefile b/contrib/emacs/Makefile
new file mode 100644
index 0000000000..d3619db510
--- /dev/null
+++ b/contrib/emacs/Makefile
@@ -0,0 +1,20 @@
+## Build and install stuff
+
+EMACS = emacs
+
+ELC = git.elc vc-git.elc
+INSTALL = install
+INSTALL_ELC = $(INSTALL) -m 644
+prefix = $(HOME)
+emacsdir = $(prefix)/share/emacs/site-lisp
+
+all: $(ELC)
+
+install: all
+ $(INSTALL) -d $(emacsdir)
+ $(INSTALL_ELC) $(ELC) $(emacsdir)
+
+%.elc: %.el
+ $(EMACS) --batch --eval '(byte-compile-file "$<")'
+
+clean:; rm -f $(ELC)
diff --git a/git-annotate.perl b/git-annotate.perl
index d93ee19c7e..feea0a2d81 100755
--- a/git-annotate.perl
+++ b/git-annotate.perl
@@ -99,7 +99,7 @@ while (my $bound = pop @stack) {
}
}
push @revqueue, $head;
-init_claim( defined $starting_rev ? $starting_rev : 'dirty');
+init_claim( defined $starting_rev ? $head : 'dirty');
unless (defined $starting_rev) {
my $diff = open_pipe("git","diff","-R", "HEAD", "--",$filename)
or die "Failed to call git diff to check for dirty state: $!";
@@ -345,6 +345,7 @@ sub git_cat_file {
return () unless defined $rev && defined $filename;
my $blob = git_ls_tree($rev, $filename);
+ die "Failed to find a blob for $filename in rev $rev\n" if !defined $blob;
my $catfile = open_pipe("git","cat-file", "blob", $blob)
or die "Failed to git-cat-file blob $blob (rev $rev, file $filename): " . $!;
@@ -367,12 +368,13 @@ sub git_ls_tree {
my ($mode, $type, $blob, $tfilename);
while(<$lstree>) {
+ chomp;
($mode, $type, $blob, $tfilename) = split(/\s+/, $_, 4);
last if ($tfilename eq $filename);
}
close($lstree);
- return $blob if $filename eq $filename;
+ return $blob if ($tfilename eq $filename);
die "git-ls-tree failed to find blob for $filename";
}
@@ -418,7 +420,13 @@ sub format_date {
return $_[0];
}
my ($timestamp, $timezone) = split(' ', $_[0]);
- return strftime("%Y-%m-%d %H:%M:%S " . $timezone, gmtime($timestamp));
+ my $minutes = abs($timezone);
+ $minutes = int($minutes / 100) * 60 + ($minutes % 100);
+ if ($timezone < 0) {
+ $minutes = -$minutes;
+ }
+ my $t = $timestamp + $minutes * 60;
+ return strftime("%Y-%m-%d %H:%M:%S " . $timezone, gmtime($t));
}
# Copied from git-send-email.perl - We need a Git.pm module..
diff --git a/revision.c b/revision.c
index a3df810076..2a33637f62 100644
--- a/revision.c
+++ b/revision.c
@@ -684,13 +684,11 @@ static void rewrite_parents(struct commit *commit)
struct commit *get_revision(struct rev_info *revs)
{
struct commit_list *list = revs->commits;
- struct commit *commit;
if (!list)
return NULL;
/* Check the max_count ... */
- commit = list->item;
switch (revs->max_count) {
case -1:
break;
@@ -701,22 +699,28 @@ struct commit *get_revision(struct rev_info *revs)
}
do {
- commit = pop_most_recent_commit(&revs->commits, SEEN);
+ struct commit *commit = revs->commits->item;
+
if (commit->object.flags & (UNINTERESTING|SHOWN))
- continue;
+ goto next;
if (revs->min_age != -1 && (commit->date > revs->min_age))
- continue;
+ goto next;
if (revs->max_age != -1 && (commit->date < revs->max_age))
return NULL;
if (revs->no_merges && commit->parents && commit->parents->next)
- continue;
+ goto next;
if (revs->paths && revs->dense) {
if (!(commit->object.flags & TREECHANGE))
- continue;
+ goto next;
rewrite_parents(commit);
}
+ /* More to go? */
+ if (revs->max_count)
+ pop_most_recent_commit(&revs->commits, SEEN);
commit->object.flags |= SHOWN;
return commit;
+next:
+ pop_most_recent_commit(&revs->commits, SEEN);
} while (revs->commits);
return NULL;
}
diff --git a/t/.gitignore b/t/.gitignore
new file mode 100644
index 0000000000..fad67c097b
--- /dev/null
+++ b/t/.gitignore
@@ -0,0 +1 @@
+trash
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
new file mode 100644
index 0000000000..8cb32e156b
--- /dev/null
+++ b/t/annotate-tests.sh
@@ -0,0 +1,102 @@
+# This file isn't used as a test script directly, instead it is
+# sourced from t8001-annotate.sh and t8001-blame.sh.
+
+check_count () {
+ head=
+ case "$1" in -h) head="$2"; shift; shift ;; esac
+ $PROG file $head | perl -e '
+ my %expect = (@ARGV);
+ my %count = ();
+ while (<STDIN>) {
+ if (/^[0-9a-f]+\t\(([^\t]+)\t/) {
+ my $author = $1;
+ for ($author) { s/^\s*//; s/\s*$//; }
+ if (exists $expect{$author}) {
+ $count{$author}++;
+ }
+ }
+ }
+ my $bad = 0;
+ while (my ($author, $count) = each %count) {
+ my $ok;
+ if ($expect{$author} != $count) {
+ $bad = 1;
+ $ok = "bad";
+ }
+ else {
+ $ok = "good";
+ }
+ print STDERR "Author $author (expected $expect{$author}, attributed $count) $ok\n";
+ }
+ exit($bad);
+ ' "$@"
+}
+
+test_expect_success \
+ 'prepare reference tree' \
+ 'echo "1A quick brown fox jumps over the" >file &&
+ echo "lazy dog" >>file &&
+ git add file
+ GIT_AUTHOR_NAME="A" git commit -a -m "Initial."'
+
+test_expect_success \
+ 'check all lines blamed on A' \
+ 'check_count A 2'
+
+test_expect_success \
+ 'Setup new lines blamed on B' \
+ 'echo "2A quick brown fox jumps over the" >>file &&
+ echo "lazy dog" >> file &&
+ GIT_AUTHOR_NAME="B" git commit -a -m "Second."'
+
+test_expect_success \
+ 'Two lines blamed on A, two on B' \
+ 'check_count A 2 B 2'
+
+test_expect_success \
+ 'merge-setup part 1' \
+ 'git checkout -b branch1 master &&
+ echo "3A slow green fox jumps into the" >> file &&
+ echo "well." >> file &&
+ GIT_AUTHOR_NAME="B1" git commit -a -m "Branch1-1"'
+
+test_expect_success \
+ 'Two lines blamed on A, two on B, two on B1' \
+ 'check_count A 2 B 2 B1 2'
+
+test_expect_success \
+ 'merge-setup part 2' \
+ 'git checkout -b branch2 master &&
+ sed -e "s/2A quick brown/4A quick brown lazy dog/" < file > file.new &&
+ mv file.new file &&
+ GIT_AUTHOR_NAME="B2" git commit -a -m "Branch2-1"'
+
+test_expect_success \
+ 'Two lines blamed on A, one on B, one on B2' \
+ 'check_count A 2 B 1 B2 1'
+
+test_expect_success \
+ 'merge-setup part 3' \
+ 'git pull . branch1'
+
+test_expect_success \
+ 'Two lines blamed on A, one on B, two on B1, one on B2' \
+ 'check_count A 2 B 1 B1 2 B2 1'
+
+test_expect_success \
+ 'Annotating an old revision works' \
+ 'check_count -h master A 2 B 2'
+
+test_expect_success \
+ 'Annotating an old revision works' \
+ 'check_count -h master^ A 2'
+
+test_expect_success \
+ 'merge-setup part 4' \
+ 'echo "evil merge." >>file &&
+ EDITOR=: git commit -a --amend'
+
+test_expect_success \
+ 'Two lines blamed on A, one on B, two on B1, one on B2, one on A U Thor' \
+ 'check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1'
+
diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh
index 172908a5b0..2496397da3 100755
--- a/t/t8001-annotate.sh
+++ b/t/t8001-annotate.sh
@@ -3,88 +3,7 @@
test_description='git-annotate'
. ./test-lib.sh
-test_expect_success \
- 'prepare reference tree' \
- 'echo "1A quick brown fox jumps over the" >file &&
- echo "lazy dog" >>file &&
- git add file
- GIT_AUTHOR_NAME="A" git commit -a -m "Initial."'
-
-test_expect_success \
- 'check all lines blamed on A' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "A") == 2 ]'
-
-test_expect_success \
- 'Setup new lines blamed on B' \
- 'echo "2A quick brown fox jumps over the" >>file &&
- echo "lazy dog" >> file &&
- GIT_AUTHOR_NAME="B" git commit -a -m "Second."'
-
-test_expect_success \
- 'Two lines blamed on A' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "A") == 2 ]'
-
-test_expect_success \
- 'Two lines blamed on B' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "B") == 2 ]'
-
-test_expect_success \
- 'merge-setup part 1' \
- 'git checkout -b branch1 master &&
- echo "3A slow green fox jumps into the" >> file &&
- echo "well." >> file &&
- GIT_AUTHOR_NAME="B1" git commit -a -m "Branch1-1"'
-
-test_expect_success \
- 'Two lines blamed on A' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^A$") == 2 ]'
-
-test_expect_success \
- 'Two lines blamed on B' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^B$") == 2 ]'
-
-test_expect_success \
- 'Two lines blamed on B1' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^B1$") == 2 ]'
-
-test_expect_success \
- 'merge-setup part 2' \
- 'git checkout -b branch2 master &&
- sed -e "s/2A quick brown/4A quick brown lazy dog/" < file > file.new &&
- mv file.new file &&
- GIT_AUTHOR_NAME="B2" git commit -a -m "Branch2-1"'
-
-test_expect_success \
- 'Two lines blamed on A' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^A$") == 2 ]'
-
-test_expect_success \
- 'One line blamed on B' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^B$") == 1 ]'
-
-test_expect_success \
- 'One line blamed on B2' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^B2$") == 1 ]'
-
-
-test_expect_success \
- 'merge-setup part 3' \
- 'git pull . branch1'
-
-test_expect_success \
- 'Two lines blamed on A' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^A$") == 2 ]'
-
-test_expect_success \
- 'One line blamed on B' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^B$") == 1 ]'
-
-test_expect_success \
- 'Two lines blamed on B1' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^B1$") == 2 ]'
-
-test_expect_success \
- 'One line blamed on B2' \
- '[ $(git annotate file | awk "{print \$3}" | grep -c "^B2$") == 1 ]'
+PROG='git annotate'
+. ../annotate-tests.sh
test_done
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
new file mode 100755
index 0000000000..9777393996
--- /dev/null
+++ b/t/t8002-blame.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+test_description='git-blame'
+. ./test-lib.sh
+
+PROG='git blame -c'
+. ../annotate-tests.sh
+
+test_done