Merge branch 'mm/line-log-use-standard-diff-output' into seen

* mm/line-log-use-standard-diff-output:
  doc: note that -L supports patch formatting and pickaxe options
  t4211: add tests for -L with standard diff options
  line-log: route -L output through the standard diff pipeline
  line-log: fix crash when combined with pickaxe options
This commit is contained in:
Junio C Hamano
2026-03-06 21:30:07 -08:00
35 changed files with 865 additions and 218 deletions

View File

@@ -11,5 +11,9 @@
Patch output can be suppressed using `--no-patch`, but other diff formats
(namely `--raw`, `--numstat`, `--shortstat`, `--dirstat`, `--summary`,
`--name-only`, `--name-status`, `--check`) are not currently implemented.
+
Patch formatting options such as `--word-diff`, `--color-moved`,
`--no-prefix`, and whitespace options (`-w`, `-b`) are supported,
as are pickaxe options (`-S`, `-G`).
+
include::line-range-format.adoc[]

279
diff.c
View File

@@ -608,6 +608,52 @@ struct emit_callback {
struct strbuf *header;
};
/*
* State for the line-range callback wrappers that sit between
* xdi_diff_outf() and fn_out_consume(). xdiff produces a normal,
* unfiltered diff; the wrappers intercept each hunk header and line,
* track post-image position, and forward only lines that fall within
* the requested ranges. Contiguous in-range lines are collected into
* range hunks and flushed with a synthetic @@ header so that
* fn_out_consume() sees well-formed unified-diff fragments.
*
* Removal lines ('-') cannot be classified by post-image position, so
* they are buffered in pending_rm until the next '+' or ' ' line
* reveals whether they precede an in-range line (flush into range hunk) or
* an out-of-range line (discard).
*/
struct line_range_callback {
xdiff_emit_line_fn orig_line_fn;
void *orig_cb_data;
const struct range_set *ranges; /* 0-based [start, end) */
unsigned int cur_range; /* index into the range_set */
/* Post/pre-image line counters (1-based, set from hunk headers) */
long lno_post;
long lno_pre;
/*
* Function name from most recent xdiff hunk header;
* size matches struct func_line.buf in xdiff/xemit.c.
*/
char func[80];
long funclen;
/* Range hunk being accumulated for the current range */
struct strbuf rhunk;
long rhunk_old_begin, rhunk_old_count;
long rhunk_new_begin, rhunk_new_count;
int rhunk_active;
int rhunk_has_changes; /* any '+' or '-' lines? */
/* Removal lines not yet known to be in-range */
struct strbuf pending_rm;
int pending_rm_count;
long pending_rm_pre_begin; /* pre-image line of first pending */
int ret; /* latched error from orig_line_fn */
};
static int count_lines(const char *data, int size)
{
int count, ch, completely_empty = 1, nl_just_seen = 0;
@@ -2493,6 +2539,188 @@ static int quick_consume(void *priv, char *line UNUSED, unsigned long len UNUSED
return 1;
}
static void discard_pending_rm(struct line_range_callback *s)
{
strbuf_reset(&s->pending_rm);
s->pending_rm_count = 0;
}
static void flush_rhunk(struct line_range_callback *s)
{
struct strbuf hdr = STRBUF_INIT;
const char *p, *end;
if (!s->rhunk_active || s->ret)
return;
/* Drain any pending removal lines into the range hunk */
if (s->pending_rm_count) {
strbuf_addbuf(&s->rhunk, &s->pending_rm);
s->rhunk_old_count += s->pending_rm_count;
s->rhunk_has_changes = 1;
discard_pending_rm(s);
}
/*
* Suppress context-only hunks: they contain no actual changes
* and would just be noise. This can happen when the inflated
* ctxlen causes xdiff to emit context covering a range that
* has no changes in this commit.
*/
if (!s->rhunk_has_changes) {
s->rhunk_active = 0;
strbuf_reset(&s->rhunk);
return;
}
strbuf_addf(&hdr, "@@ -%ld,%ld +%ld,%ld @@",
s->rhunk_old_begin, s->rhunk_old_count,
s->rhunk_new_begin, s->rhunk_new_count);
if (s->funclen > 0) {
strbuf_addch(&hdr, ' ');
strbuf_add(&hdr, s->func, s->funclen);
}
strbuf_addch(&hdr, '\n');
s->ret = s->orig_line_fn(s->orig_cb_data, hdr.buf, hdr.len);
strbuf_release(&hdr);
/*
* Replay buffered lines one at a time through fn_out_consume.
* The cast discards const because xdiff_emit_line_fn takes
* char *, though fn_out_consume does not modify the buffer.
*/
p = s->rhunk.buf;
end = p + s->rhunk.len;
while (!s->ret && p < end) {
const char *eol = memchr(p, '\n', end - p);
unsigned long line_len = eol ? (unsigned long)(eol - p + 1)
: (unsigned long)(end - p);
s->ret = s->orig_line_fn(s->orig_cb_data, (char *)p, line_len);
p += line_len;
}
s->rhunk_active = 0;
strbuf_reset(&s->rhunk);
}
static void line_range_hunk_fn(void *data,
long old_begin, long old_nr UNUSED,
long new_begin, long new_nr UNUSED,
const char *func, long funclen)
{
struct line_range_callback *s = data;
/*
* When count > 0, begin is 1-based. When count == 0, begin is
* adjusted down by 1 by xdl_emit_hunk_hdr(), but no lines of
* that type will arrive, so the value is unused.
*
* Any pending removal lines from the previous xdiff hunk are
* intentionally left in pending_rm: the line callback will
* flush or discard them when the next content line reveals
* whether the removals precede in-range content.
*/
s->lno_post = new_begin;
s->lno_pre = old_begin;
if (funclen > 0) {
if (funclen > (long)sizeof(s->func))
funclen = sizeof(s->func);
memcpy(s->func, func, funclen);
}
s->funclen = funclen;
}
static int line_range_line_fn(void *priv, char *line, unsigned long len)
{
struct line_range_callback *s = priv;
const struct range *cur;
long lno_0, cur_pre;
if (s->ret)
return s->ret;
if (line[0] == '-') {
if (!s->pending_rm_count)
s->pending_rm_pre_begin = s->lno_pre;
s->lno_pre++;
strbuf_add(&s->pending_rm, line, len);
s->pending_rm_count++;
return s->ret;
}
if (line[0] == '\\') {
if (s->pending_rm_count)
strbuf_add(&s->pending_rm, line, len);
else if (s->rhunk_active)
strbuf_add(&s->rhunk, line, len);
/* otherwise outside tracked range; drop silently */
return s->ret;
}
if (line[0] != '+' && line[0] != ' ')
BUG("unexpected diff line type '%c'", line[0]);
lno_0 = s->lno_post - 1;
cur_pre = s->lno_pre; /* save before advancing for context lines */
s->lno_post++;
if (line[0] == ' ')
s->lno_pre++;
/* Advance past ranges we've passed */
while (s->cur_range < s->ranges->nr &&
lno_0 >= s->ranges->ranges[s->cur_range].end) {
if (s->rhunk_active)
flush_rhunk(s);
discard_pending_rm(s);
s->cur_range++;
}
/* Past all ranges */
if (s->cur_range >= s->ranges->nr) {
discard_pending_rm(s);
return s->ret;
}
cur = &s->ranges->ranges[s->cur_range];
/* Before current range */
if (lno_0 < cur->start) {
discard_pending_rm(s);
return s->ret;
}
/* In range so start a new range hunk if needed */
if (!s->rhunk_active) {
s->rhunk_active = 1;
s->rhunk_has_changes = 0;
s->rhunk_new_begin = lno_0 + 1;
s->rhunk_old_begin = s->pending_rm_count
? s->pending_rm_pre_begin : cur_pre;
s->rhunk_old_count = 0;
s->rhunk_new_count = 0;
strbuf_reset(&s->rhunk);
}
/* Flush pending removals into range hunk */
if (s->pending_rm_count) {
strbuf_addbuf(&s->rhunk, &s->pending_rm);
s->rhunk_old_count += s->pending_rm_count;
s->rhunk_has_changes = 1;
discard_pending_rm(s);
}
strbuf_add(&s->rhunk, line, len);
s->rhunk_new_count++;
if (line[0] == '+')
s->rhunk_has_changes = 1;
else
s->rhunk_old_count++;
return s->ret;
}
static void pprint_rename(struct strbuf *name, const char *a, const char *b)
{
const char *old_name = a;
@@ -3592,7 +3820,8 @@ static void builtin_diff(const char *name_a,
const char *xfrm_msg,
int must_show_header,
struct diff_options *o,
int complete_rewrite)
int complete_rewrite,
const struct range_set *line_ranges)
{
mmfile_t mf1, mf2;
const char *lbl[2];
@@ -3833,6 +4062,52 @@ static void builtin_diff(const char *name_a,
*/
xdi_diff_outf(&mf1, &mf2, NULL, quick_consume,
&ecbdata, &xpp, &xecfg);
} else if (line_ranges) {
struct line_range_callback lr_state;
unsigned int i;
long max_span = 0;
memset(&lr_state, 0, sizeof(lr_state));
lr_state.orig_line_fn = fn_out_consume;
lr_state.orig_cb_data = &ecbdata;
lr_state.ranges = line_ranges;
strbuf_init(&lr_state.rhunk, 0);
strbuf_init(&lr_state.pending_rm, 0);
/*
* Inflate ctxlen so that all changes within
* any single range are merged into one xdiff
* hunk and the inter-change context is emitted.
* The callback clips back to range boundaries.
*
* The optimal ctxlen depends on where changes
* fall within the range, which is only known
* after xdiff runs; the max range span is the
* upper bound that guarantees correctness in a
* single pass.
*/
for (i = 0; i < line_ranges->nr; i++) {
long span = line_ranges->ranges[i].end -
line_ranges->ranges[i].start;
if (span > max_span)
max_span = span;
}
if (max_span > xecfg.ctxlen)
xecfg.ctxlen = max_span;
if (xdi_diff_outf(&mf1, &mf2,
line_range_hunk_fn,
line_range_line_fn,
&lr_state, &xpp, &xecfg))
die("unable to generate diff for %s",
one->path);
flush_rhunk(&lr_state);
if (lr_state.ret)
die("unable to generate diff for %s",
one->path);
strbuf_release(&lr_state.rhunk);
strbuf_release(&lr_state.pending_rm);
} else if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
&ecbdata, &xpp, &xecfg))
die("unable to generate diff for %s", one->path);
@@ -4674,7 +4949,7 @@ static void run_diff_cmd(const struct external_diff *pgm,
builtin_diff(name, other ? other : name,
one, two, xfrm_msg, must_show_header,
o, complete_rewrite);
o, complete_rewrite, p->line_ranges);
if (p->status == DIFF_STATUS_COPIED ||
p->status == DIFF_STATUS_RENAMED)
o->found_changes = 1;

View File

@@ -19,6 +19,17 @@ struct userdiff_driver;
* in anything else.
*/
/* A range [start, end). Lines are numbered starting at 0. */
struct range {
long start, end;
};
/* A set of ranges. The ranges must always be disjoint and sorted. */
struct range_set {
unsigned int alloc, nr;
struct range *ranges;
};
/* We internally use unsigned short as the score value,
* and rely on an int capable to hold 32-bits. -B can take
* -Bmerge_score/break_score format and the two scores are
@@ -106,6 +117,11 @@ int diff_filespec_is_binary(struct repository *, struct diff_filespec *);
struct diff_filepair {
struct diff_filespec *one;
struct diff_filespec *two;
/*
* Tracked line ranges for -L filtering; borrowed from
* line_log_data and must not be freed.
*/
const struct range_set *line_ranges;
unsigned short int score;
char status; /* M C R A D U etc. (see Documentation/diff-format.adoc or DIFF_STATUS_* in diff.h) */
unsigned broken_pair : 1;

View File

@@ -858,173 +858,33 @@ static void queue_diffs(struct line_log_data *range,
diff_queue_clear(&diff_queued_diff);
diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
if (opt->detect_rename && diff_might_be_rename()) {
/* must look at the full tree diff to detect renames */
clear_pathspec(&opt->pathspec);
diff_queue_clear(&diff_queued_diff);
struct diff_options rename_opts;
diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
/*
* Build a private diff_options for rename detection so
* that any user-specified options on the original opts
* (e.g. pickaxe) cannot discard diff pairs needed for
* rename tracking. Similar to blame's find_rename().
*/
repo_diff_setup(opt->repo, &rename_opts);
rename_opts.flags.recursive = 1;
rename_opts.detect_rename = opt->detect_rename;
rename_opts.rename_score = opt->rename_score;
rename_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
diff_setup_done(&rename_opts);
/* must look at the full tree diff to detect renames */
diff_queue_clear(&diff_queued_diff);
diff_tree_oid(parent_tree_oid, tree_oid, "", &rename_opts);
filter_diffs_for_paths(range, 1);
diffcore_std(opt);
diffcore_std(&rename_opts);
filter_diffs_for_paths(range, 0);
diff_free(&rename_opts);
}
move_diff_queue(queue, &diff_queued_diff);
}
static char *get_nth_line(long line, unsigned long *ends, void *data)
{
if (line == 0)
return (char *)data;
else
return (char *)data + ends[line] + 1;
}
static void print_line(const char *prefix, char first,
long line, unsigned long *ends, void *data,
const char *color, const char *reset, FILE *file)
{
char *begin = get_nth_line(line, ends, data);
char *end = get_nth_line(line+1, ends, data);
int had_nl = 0;
if (end > begin && end[-1] == '\n') {
end--;
had_nl = 1;
}
fputs(prefix, file);
fputs(color, file);
putc(first, file);
fwrite(begin, 1, end-begin, file);
fputs(reset, file);
putc('\n', file);
if (!had_nl)
fputs("\\ No newline at end of file\n", file);
}
static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *range)
{
unsigned int i, j = 0;
long p_lines, t_lines;
unsigned long *p_ends = NULL, *t_ends = NULL;
struct diff_filepair *pair = range->pair;
struct diff_ranges *diff = &range->diff;
struct diff_options *opt = &rev->diffopt;
const char *prefix = diff_line_prefix(opt);
const char *c_reset = diff_get_color(opt->use_color, DIFF_RESET);
const char *c_frag = diff_get_color(opt->use_color, DIFF_FRAGINFO);
const char *c_meta = diff_get_color(opt->use_color, DIFF_METAINFO);
const char *c_old = diff_get_color(opt->use_color, DIFF_FILE_OLD);
const char *c_new = diff_get_color(opt->use_color, DIFF_FILE_NEW);
const char *c_context = diff_get_color(opt->use_color, DIFF_CONTEXT);
if (!pair || !diff)
goto out;
if (pair->one->oid_valid)
fill_line_ends(rev->diffopt.repo, pair->one, &p_lines, &p_ends);
fill_line_ends(rev->diffopt.repo, pair->two, &t_lines, &t_ends);
fprintf(opt->file, "%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset);
fprintf(opt->file, "%s%s--- %s%s%s\n", prefix, c_meta,
pair->one->oid_valid ? "a/" : "",
pair->one->oid_valid ? pair->one->path : "/dev/null",
c_reset);
fprintf(opt->file, "%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset);
for (i = 0; i < range->ranges.nr; i++) {
long p_start, p_end;
long t_start = range->ranges.ranges[i].start;
long t_end = range->ranges.ranges[i].end;
long t_cur = t_start;
unsigned int j_last;
/*
* If a diff range touches multiple line ranges, then all
* those line ranges should be shown, so take a step back if
* the current line range is still in the previous diff range
* (even if only partially).
*/
if (j > 0 && diff->target.ranges[j-1].end > t_start)
j--;
while (j < diff->target.nr && diff->target.ranges[j].end < t_start)
j++;
if (j == diff->target.nr || diff->target.ranges[j].start >= t_end)
continue;
/* Scan ahead to determine the last diff that falls in this range */
j_last = j;
while (j_last < diff->target.nr && diff->target.ranges[j_last].start < t_end)
j_last++;
if (j_last > j)
j_last--;
/*
* Compute parent hunk headers: we know that the diff
* has the correct line numbers (but not all hunks).
* So it suffices to shift the start/end according to
* the line numbers of the first/last hunk(s) that
* fall in this range.
*/
if (t_start < diff->target.ranges[j].start)
p_start = diff->parent.ranges[j].start - (diff->target.ranges[j].start-t_start);
else
p_start = diff->parent.ranges[j].start;
if (t_end > diff->target.ranges[j_last].end)
p_end = diff->parent.ranges[j_last].end + (t_end-diff->target.ranges[j_last].end);
else
p_end = diff->parent.ranges[j_last].end;
if (!p_start && !p_end) {
p_start = -1;
p_end = -1;
}
/* Now output a diff hunk for this range */
fprintf(opt->file, "%s%s@@ -%ld,%ld +%ld,%ld @@%s\n",
prefix, c_frag,
p_start+1, p_end-p_start, t_start+1, t_end-t_start,
c_reset);
while (j < diff->target.nr && diff->target.ranges[j].start < t_end) {
int k;
for (; t_cur < diff->target.ranges[j].start; t_cur++)
print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
c_context, c_reset, opt->file);
for (k = diff->parent.ranges[j].start; k < diff->parent.ranges[j].end; k++)
print_line(prefix, '-', k, p_ends, pair->one->data,
c_old, c_reset, opt->file);
for (; t_cur < diff->target.ranges[j].end && t_cur < t_end; t_cur++)
print_line(prefix, '+', t_cur, t_ends, pair->two->data,
c_new, c_reset, opt->file);
j++;
}
for (; t_cur < t_end; t_cur++)
print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
c_context, c_reset, opt->file);
}
out:
free(p_ends);
free(t_ends);
}
/*
* NEEDSWORK: manually building a diff here is not the Right
* Thing(tm). log -L should be built into the diff pipeline.
*/
static void dump_diff_hacky(struct rev_info *rev, struct line_log_data *range)
{
const char *prefix = diff_line_prefix(&rev->diffopt);
fprintf(rev->diffopt.file, "%s\n", prefix);
while (range) {
dump_diff_hacky_one(rev, range);
range = range->next;
}
}
/*
* Unlike most other functions, this destructively operates on
* 'range'.
@@ -1088,7 +948,7 @@ static int process_diff_filepair(struct rev_info *rev,
static struct diff_filepair *diff_filepair_dup(struct diff_filepair *pair)
{
struct diff_filepair *new_filepair = xmalloc(sizeof(struct diff_filepair));
struct diff_filepair *new_filepair = xcalloc(1, sizeof(struct diff_filepair));
new_filepair->one = pair->one;
new_filepair->two = pair->two;
new_filepair->one->count++;
@@ -1146,11 +1006,25 @@ static int process_all_files(struct line_log_data **range_out,
int line_log_print(struct rev_info *rev, struct commit *commit)
{
show_log(rev);
if (!(rev->diffopt.output_format & DIFF_FORMAT_NO_OUTPUT)) {
struct line_log_data *range = lookup_line_range(rev, commit);
dump_diff_hacky(rev, range);
struct line_log_data *r;
const char *prefix = diff_line_prefix(&rev->diffopt);
fprintf(rev->diffopt.file, "%s\n", prefix);
for (r = range; r; r = r->next) {
if (r->pair) {
struct diff_filepair *p =
diff_filepair_dup(r->pair);
p->line_ranges = &r->ranges;
diff_q(&diff_queued_diff, p);
}
}
diffcore_std(&rev->diffopt);
diff_flush(&rev->diffopt);
}
return 1;
}

View File

@@ -1,22 +1,12 @@
#ifndef LINE_LOG_H
#define LINE_LOG_H
#include "diffcore.h" /* struct range, struct range_set */
struct rev_info;
struct commit;
struct string_list;
/* A range [start,end]. Lines are numbered starting at 0, and the
* ranges include start but exclude end. */
struct range {
long start, end;
};
/* A set of ranges. The ranges must always be disjoint and sorted. */
struct range_set {
unsigned int alloc, nr;
struct range *ranges;
};
/* A diff, encoded as the set of pre- and post-image ranges where the
* files differ. A pair of ranges corresponds to a hunk. */
struct diff_ranges {

View File

@@ -3128,6 +3128,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
if (want_ancestry(revs))
revs->limited = 1;
revs->topo_order = 1;
if (!revs->diffopt.output_format)
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
}
if (revs->topo_order && !generation_numbers_enabled(the_repository))

View File

@@ -129,7 +129,7 @@ test_expect_success '-L with --output' '
git checkout parallel-change &&
git log --output=log -L :main:b.c >output &&
test_must_be_empty output &&
test_line_count = 70 log
test_line_count = 75 log
'
test_expect_success 'range_set_union' '
@@ -339,14 +339,106 @@ test_expect_success 'zero-width regex .* matches any function name' '
test_cmp expect actual
'
test_expect_success 'setup for diff pipeline tests' '
git checkout parent-oids &&
head_blob_old=$(git rev-parse --short HEAD^:file.c) &&
head_blob_new=$(git rev-parse --short HEAD:file.c) &&
root_blob=$(git rev-parse --short HEAD~4:file.c) &&
null_blob=$(test_oid zero | cut -c1-7) &&
head_blob_old_full=$(git rev-parse HEAD^:file.c) &&
head_blob_new_full=$(git rev-parse HEAD:file.c) &&
root_blob_full=$(git rev-parse HEAD~4:file.c) &&
null_blob_full=$(test_oid zero)
'
test_expect_success '-L diff output includes index and new file mode' '
git log -L:func2:file.c --format= >actual &&
# Output should contain index headers (not present in old code path)
grep "^index $head_blob_old\.\.$head_blob_new 100644" actual &&
# Root commit should show new file mode and null index
grep "^new file mode 100644" actual &&
grep "^index $null_blob\.\.$root_blob$" actual &&
# Hunk headers should include funcname context
grep "^@@ .* @@ int func1()" actual
'
test_expect_success '-L with --word-diff' '
cat >expect <<-\EOF &&
diff --git a/file.c b/file.c
--- a/file.c
+++ b/file.c
@@ -6,4 +6,4 @@ int func1()
int func2()
{
return [-F2;-]{+F2 + 2;+}
}
diff --git a/file.c b/file.c
new file mode 100644
--- /dev/null
+++ b/file.c
@@ -0,0 +6,4 @@
{+int func2()+}
{+{+}
{+ return F2;+}
{+}+}
EOF
git log -L:func2:file.c --word-diff --format= >actual &&
grep -v "^index " actual >actual.filtered &&
grep -v "^index " expect >expect.filtered &&
test_cmp expect.filtered actual.filtered
'
test_expect_success '-L with --no-prefix' '
git log -L:func2:file.c --no-prefix --format= >actual &&
grep "^diff --git file.c file.c" actual &&
grep "^--- file.c" actual &&
! grep "^--- a/" actual
'
test_expect_success '-L with --full-index' '
git log -L:func2:file.c --full-index --format= >actual &&
grep "^index $head_blob_old_full\.\.$head_blob_new_full 100644" actual &&
grep "^index $null_blob_full\.\.$root_blob_full$" actual
'
test_expect_success 'setup -L with whitespace change' '
git checkout -b ws-change parent-oids &&
sed "s/ return F2 + 2;/ return F2 + 2;/" file.c >tmp &&
mv tmp file.c &&
git commit -a -m "Whitespace change in func2()"
'
test_expect_success '-L with --ignore-all-space suppresses whitespace-only diff' '
git log -L:func2:file.c --format= >without_w &&
git log -L:func2:file.c --format= -w >with_w &&
# Without -w: three commits produce diffs (whitespace, modify, root)
test $(grep -c "^diff --git" without_w) = 3 &&
# With -w: whitespace-only commit produces no hunk, so only two diffs
test $(grep -c "^diff --git" with_w) = 2
'
test_expect_success 'show line-log with graph' '
git checkout parent-oids &&
head_blob_old=$(git rev-parse --short HEAD^:file.c) &&
head_blob_new=$(git rev-parse --short HEAD:file.c) &&
root_blob=$(git rev-parse --short HEAD~4:file.c) &&
null_blob=$(test_oid zero | cut -c1-7) &&
qz_to_tab_space >expect <<-EOF &&
* $head_oid Modify func2() in file.c
|Z
| diff --git a/file.c b/file.c
| index $head_blob_old..$head_blob_new 100644
| --- a/file.c
| +++ b/file.c
| @@ -6,4 +6,4 @@
| @@ -6,4 +6,4 @@ int func1()
| int func2()
| {
| - return F2;
@@ -355,6 +447,8 @@ test_expect_success 'show line-log with graph' '
* $root_oid Add func1() and func2() in file.c
ZZ
diff --git a/file.c b/file.c
new file mode 100644
index $null_blob..$root_blob
--- /dev/null
+++ b/file.c
@@ -0,0 +6,4 @@
@@ -367,4 +461,248 @@ test_expect_success 'show line-log with graph' '
test_cmp expect actual
'
test_expect_success 'setup for -L with -G/-S/--find-object and a merge with rename' '
git checkout --orphan pickaxe-rename &&
git reset --hard &&
echo content >file &&
git add file &&
git commit -m "add file" &&
git checkout -b pickaxe-rename-side &&
git mv file renamed-file &&
git commit -m "rename file" &&
git checkout pickaxe-rename &&
git commit --allow-empty -m "diverge" &&
git merge --no-edit pickaxe-rename-side &&
git mv renamed-file file &&
git commit -m "rename back"
'
test_expect_success '-L -G does not crash with merge and rename' '
git log --format="%s" --no-patch -L 1,1:file -G "." >actual
'
test_expect_success '-L -S does not crash with merge and rename' '
git log --format="%s" --no-patch -L 1,1:file -S content >actual
'
test_expect_success '-L --find-object does not crash with merge and rename' '
git log --format="%s" --no-patch -L 1,1:file \
--find-object=$(git rev-parse HEAD:file) >actual
'
test_expect_failure '-L -G should filter commits by pattern' '
git log --format="%s" --no-patch -L 1,1:file -G "nomatch" >actual &&
test_must_be_empty actual
'
test_expect_failure '-L -S should filter commits by pattern' '
git log --format="%s" --no-patch -L 1,1:file -S "nomatch" >actual &&
test_must_be_empty actual
'
test_expect_failure '-L --find-object should filter commits by object' '
git log --format="%s" --no-patch -L 1,1:file \
--find-object=$ZERO_OID >actual &&
test_must_be_empty actual
'
test_expect_success '-L with --word-diff-regex' '
git checkout parent-oids &&
git log -L:func2:file.c --word-diff \
--word-diff-regex="[a-zA-Z0-9_]+" --format= >actual &&
# Word-diff markers must be present
grep "{+" actual &&
grep "+}" actual &&
# No line-level +/- markers (word-diff replaces them);
# exclude --- header lines from the check
! grep "^+[^+]" actual &&
! grep "^-[^-]" actual
'
test_expect_success '-L with --src-prefix and --dst-prefix' '
git checkout parent-oids &&
git log -L:func2:file.c --src-prefix=old/ --dst-prefix=new/ \
--format= >actual &&
grep "^diff --git old/file.c new/file.c" actual &&
grep "^--- old/file.c" actual &&
grep "^+++ new/file.c" actual &&
! grep "^--- a/" actual
'
test_expect_success '-L with --abbrev' '
git checkout parent-oids &&
git log -L:func2:file.c --abbrev=4 --format= -1 >actual &&
# 4-char abbreviated hashes on index line
grep "^index [0-9a-f]\{4\}\.\.[0-9a-f]\{4\}" actual
'
test_expect_success '-L with -b suppresses whitespace-only diff' '
git checkout ws-change &&
git log -L:func2:file.c --format= >without_b &&
git log -L:func2:file.c --format= -b >with_b &&
test $(grep -c "^diff --git" without_b) = 3 &&
test $(grep -c "^diff --git" with_b) = 2
'
test_expect_success '-L with --output-indicator-*' '
git checkout parent-oids &&
git log -L:func2:file.c --output-indicator-new=">" \
--output-indicator-old="<" --output-indicator-context="|" \
--format= -1 >actual &&
grep "^>" actual &&
grep "^<" actual &&
grep "^|" actual &&
# No standard +/-/space content markers; exclude ---/+++ headers
! grep "^+[^+]" actual &&
! grep "^-[^-]" actual &&
! grep "^ " actual
'
test_expect_success '-L with -R reverses diff' '
git checkout parent-oids &&
git log -L:func2:file.c -R --format= -1 >actual &&
grep "^diff --git b/file.c a/file.c" actual &&
grep "^--- b/file.c" actual &&
grep "^+++ a/file.c" actual &&
# The modification added "F2 + 2", so reversed it is removed
grep "^-.*F2 + 2" actual &&
grep "^+.*return F2;" actual
'
test_expect_success 'setup for color-moved test' '
git checkout -b color-moved-test parent-oids &&
cat >big.c <<-\EOF &&
int bigfunc()
{
int a = 1;
int b = 2;
int c = 3;
return a + b + c;
}
EOF
git add big.c &&
git commit -m "add bigfunc" &&
sed "s/ / /" big.c >tmp && mv tmp big.c &&
git commit -a -m "reindent bigfunc"
'
test_expect_success '-L with --color-moved' '
git log -L:bigfunc:big.c --color-moved=zebra \
--color-moved-ws=ignore-all-space \
--color=always --format= -1 >actual.raw &&
test_decode_color <actual.raw >actual &&
# Old moved lines: bold magenta; new moved lines: bold cyan
grep "BOLD;MAGENTA" actual &&
grep "BOLD;CYAN" actual
'
test_expect_success 'setup for no-newline-at-eof tests' '
git checkout --orphan no-newline &&
git reset --hard &&
printf "int top()\n{\n return 1;\n}\n\nint bot()\n{\n return 2;\n}" >noeol.c &&
git add noeol.c &&
test_tick &&
git commit -m "add noeol.c (no trailing newline)" &&
sed "s/return 2/return 22/" noeol.c >tmp && mv tmp noeol.c &&
git commit -a -m "modify bot()" &&
printf "int top()\n{\n return 1;\n}\n\nint bot()\n{\n return 33;\n}\n" >noeol.c &&
git commit -a -m "modify bot() and add trailing newline"
'
# When the tracked function is at the end of a file with no trailing
# newline, the "\ No newline at end of file" marker should appear.
test_expect_success '-L no-newline-at-eof appears in tracked range' '
git log -L:bot:noeol.c --format= -1 HEAD~1 >actual &&
grep "No newline at end of file" actual
'
# When tracking a function that ends before the no-newline content,
# the marker should not appear in the output.
test_expect_success '-L no-newline-at-eof suppressed outside range' '
git log -L:top:noeol.c --format= >actual &&
! grep "No newline at end of file" actual
'
# When a commit removes a no-newline last line and replaces it with
# a newline-terminated line, the marker should still appear (on the
# old side of the diff).
test_expect_success '-L no-newline-at-eof marker with deleted line' '
git log -L:bot:noeol.c --format= -1 >actual &&
grep "No newline at end of file" actual
'
test_expect_success 'setup for range boundary deletion test' '
git checkout --orphan range-boundary &&
git reset --hard &&
cat >boundary.c <<-\EOF &&
void above()
{
return;
}
void tracked()
{
int x = 1;
int y = 2;
}
void below()
{
return;
}
EOF
git add boundary.c &&
test_tick &&
git commit -m "add boundary.c" &&
cat >boundary.c <<-\EOF &&
void above()
{
return;
}
void tracked()
{
int x = 1;
int y = 2;
}
void below_renamed()
{
return 0;
}
EOF
git commit -a -m "modify below() only"
'
# When only a function below the tracked range is modified, the
# tracked function should not produce a diff.
test_expect_success '-L suppresses deletions outside tracked range' '
git log -L:tracked:boundary.c --format= >actual &&
test $(grep -c "^diff --git" actual) = 1
'
test_expect_success '-L with -S filters to string-count changes' '
git checkout parent-oids &&
git log -L:func2:file.c -S "F2 + 2" --format= >actual &&
# -S searches the whole file, not just the tracked range;
# combined with the -L range walk, this selects commits that
# both touch func2 and change the count of "F2 + 2" in the file.
test $(grep -c "^diff --git" actual) = 1 &&
grep "F2 + 2" actual
'
test_expect_success '-L with -G filters to diff-text matches' '
git checkout parent-oids &&
git log -L:func2:file.c -G "F2 [+] 2" --format= >actual &&
# -G greps the whole-file diff text, not just the tracked range;
# combined with -L, this selects commits that both touch func2
# and have "F2 + 2" in their diff.
test $(grep -c "^diff --git" actual) = 1 &&
grep "F2 + 2" actual
'
test_done

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:47:40 2013 +0100
change at very beginning
diff --git a/a.c b/a.c
index bdb2bb1..5e709a1 100644
--- a/a.c
+++ b/a.c
@@ -1,3 +1,4 @@
@@ -20,6 +21,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -1,3 +1,3 @@
@@ -35,6 +37,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +1,3 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -20,3 +20,5 @@
@@ -20,3 +20,5 @@ long f(long x)
printf("%ld\n", f(15));
return 0;
-}
@@ -23,9 +24,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -20,3 +20,3 @@
@@ -20,3 +20,3 @@ int main ()
printf("%ld\n", f(15));
return 0;
-}
@@ -39,9 +41,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -19,3 +19,3 @@
@@ -19,3 +19,3 @@ int f(int x)
- printf("%d\n", f(15));
+ printf("%ld\n", f(15));
return 0;
@@ -54,6 +57,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +18,3 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:49:50 2013 +0100
another simple change
diff --git a/b.c b/b.c
index 5de3ea4..bf79c2f 100644
--- a/b.c
+++ b/b.c
@@ -4,9 +4,9 @@
@@ -26,6 +27,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -47,6 +49,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -67,6 +70,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
@@ -18,5 +18,7 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -25,9 +26,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -43,6 +45,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -71,6 +74,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -91,6 +95,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,21 @@
@@ -39,6 +40,7 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,19 @@
@@ -71,6 +73,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index e51de13..bdb2bb1 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -102,6 +105,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -134,6 +138,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,18 +3,19 @@
@@ -164,6 +169,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,18 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,21 @@
@@ -39,6 +40,7 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,19 @@
@@ -71,6 +73,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index e51de13..bdb2bb1 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -102,6 +105,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -134,6 +138,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,18 +3,19 @@
@@ -164,6 +169,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,18 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:50:24 2013 +0100
move within the file
diff --git a/b.c b/b.c
index bf79c2f..27c829c 100644
--- a/b.c
+++ b/b.c
@@ -25,0 +18,9 @@
@@ -25,9 +26,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
@@ -18,5 +18,7 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -45,9 +47,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -63,9 +66,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
@@ -17,5 +17,5 @@ int f(int x)
int main ()
{
- printf("%d\n", f(15));
@@ -80,6 +84,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@

View File

@@ -13,6 +13,7 @@ Date: Thu Feb 28 10:49:50 2013 +0100
another simple change
diff --git a/b.c b/b.c
index 5de3ea4..bf79c2f 100644
--- a/b.c
+++ b/b.c
@@ -4,14 +4,14 @@
@@ -39,6 +40,7 @@ Date: Fri Apr 12 16:15:57 2013 +0200
change on another line of history while rename happens
diff --git a/a.c b/a.c
index 5de3ea4..01b5b65 100644
--- a/a.c
+++ b/a.c
@@ -4,14 +4,14 @@
@@ -65,6 +67,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index e51de13..bdb2bb1 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -91,6 +94,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -117,6 +121,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,13 +3,14 @@
@@ -142,6 +147,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,13 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -26,6 +27,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -46,6 +48,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index e51de13..bdb2bb1 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -31,6 +32,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -57,6 +59,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,13 +3,14 @@
@@ -82,6 +85,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,13 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -23,9 +24,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -41,9 +43,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
@@ -17,5 +17,5 @@ int f(int x)
int main ()
{
- printf("%d\n", f(15));
@@ -58,6 +61,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
@@ -18,5 +18,7 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -25,9 +26,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -43,9 +45,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
@@ -17,5 +17,5 @@ int f(int x)
int main ()
{
- printf("%d\n", f(15));
@@ -60,6 +63,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -23,9 +24,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -41,6 +43,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 3233403..e51de13 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -69,6 +72,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 444e415..3233403 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -89,6 +93,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,11 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index 0b9cae5..5de3ea4 100644
--- a/a.c
+++ b/a.c
@@ -22,1 +24,1 @@
-}
\ No newline at end of file
@@ -23,0 +24,1 @@ int main ()
+/* incomplete lines are bad! */
commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
@@ -19,9 +18,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index 5e709a1..0b9cae5 100644
--- a/a.c
+++ b/a.c
@@ -22,1 +22,1 @@
@@ -22,1 +22,1 @@ int main ()
-}
+}
\ No newline at end of file
@@ -33,6 +33,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..444e415
--- /dev/null
+++ b/a.c
@@ -0,0 +20,1 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:47:40 2013 +0100
change at very beginning
diff --git a/a.c b/a.c
index 3a78aaf..d325124 100644
--- a/a.c
+++ b/a.c
@@ -1,3 +1,4 @@
@@ -20,6 +21,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -1,3 +1,3 @@
@@ -35,6 +37,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +1,3 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -20,3 +20,5 @@
@@ -20,3 +20,5 @@ long f(long x)
printf("%ld\n", f(15));
return 0;
-}
@@ -23,9 +24,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -20,3 +20,3 @@
@@ -20,3 +20,3 @@ int main ()
printf("%ld\n", f(15));
return 0;
-}
@@ -39,9 +41,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -19,3 +19,3 @@
@@ -19,3 +19,3 @@ int f(int x)
- printf("%d\n", f(15));
+ printf("%ld\n", f(15));
return 0;
@@ -54,6 +57,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +18,3 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:49:50 2013 +0100
another simple change
diff --git a/b.c b/b.c
index 62c1fc2..69cb69c 100644
--- a/b.c
+++ b/b.c
@@ -4,9 +4,9 @@
@@ -26,6 +27,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -47,6 +49,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -67,6 +70,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
@@ -18,5 +18,7 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -25,9 +26,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -43,6 +45,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -71,6 +74,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -91,6 +95,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,21 @@
@@ -39,6 +40,7 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,19 @@
@@ -71,6 +73,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index 75c0119..3a78aaf 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -102,6 +105,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -134,6 +138,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,18 +3,19 @@
@@ -164,6 +169,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,18 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,21 @@
@@ -39,6 +40,7 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -4,19 +4,19 @@
@@ -71,6 +73,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index 75c0119..3a78aaf 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -102,6 +105,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,19 +3,19 @@
@@ -134,6 +138,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,18 +3,19 @@
@@ -164,6 +169,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,18 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:50:24 2013 +0100
move within the file
diff --git a/b.c b/b.c
index 69cb69c..a0d566e 100644
--- a/b.c
+++ b/b.c
@@ -25,0 +18,9 @@
@@ -25,9 +26,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
@@ -18,5 +18,7 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -45,9 +47,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -63,9 +66,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
@@ -17,5 +17,5 @@ int f(int x)
int main ()
{
- printf("%d\n", f(15));
@@ -80,6 +84,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@

View File

@@ -13,6 +13,7 @@ Date: Thu Feb 28 10:49:50 2013 +0100
another simple change
diff --git a/b.c b/b.c
index 62c1fc2..69cb69c 100644
--- a/b.c
+++ b/b.c
@@ -4,14 +4,14 @@
@@ -39,6 +40,7 @@ Date: Fri Apr 12 16:15:57 2013 +0200
change on another line of history while rename happens
diff --git a/a.c b/a.c
index 62c1fc2..e1e8475 100644
--- a/a.c
+++ b/a.c
@@ -4,14 +4,14 @@
@@ -65,6 +67,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index 75c0119..3a78aaf 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -91,6 +94,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -117,6 +121,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,13 +3,14 @@
@@ -142,6 +147,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,13 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -26,6 +27,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -46,6 +48,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,6 +5,7 @@ Date: Thu Feb 28 10:45:41 2013 +0100
touch comment
diff --git a/a.c b/a.c
index 75c0119..3a78aaf 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -31,6 +32,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,14 +3,14 @@
@@ -57,6 +59,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,13 +3,14 @@
@@ -82,6 +85,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,13 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -23,9 +24,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -41,9 +43,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
@@ -17,5 +17,5 @@ int f(int x)
int main ()
{
- printf("%d\n", f(15));
@@ -58,6 +61,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,7 @@
@@ -18,5 +18,7 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -25,9 +26,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -43,9 +45,10 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -17,5 +17,5 @@
@@ -17,5 +17,5 @@ int f(int x)
int main ()
{
- printf("%d\n", f(15));
@@ -60,6 +63,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +16,5 @@

View File

@@ -5,9 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -23,9 +24,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -18,5 +18,5 @@
@@ -18,5 +18,5 @@ long f(long x)
int main ()
{
printf("%ld\n", f(15));
@@ -41,6 +43,7 @@ Date: Thu Feb 28 10:45:16 2013 +0100
touch both functions
diff --git a/a.c b/a.c
index 7a296b9..75c0119 100644
--- a/a.c
+++ b/a.c
@@ -3,9 +3,9 @@
@@ -69,6 +72,7 @@ Date: Thu Feb 28 10:44:55 2013 +0100
change f()
diff --git a/a.c b/a.c
index 9f550c3..7a296b9 100644
--- a/a.c
+++ b/a.c
@@ -3,8 +3,9 @@
@@ -89,6 +93,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +3,8 @@

View File

@@ -5,11 +5,10 @@ Date: Thu Feb 28 10:48:43 2013 +0100
change back to complete line
diff --git a/a.c b/a.c
index e4fa1d8..62c1fc2 100644
--- a/a.c
+++ b/a.c
@@ -22,1 +24,1 @@
-}
\ No newline at end of file
@@ -23,0 +24,1 @@ int main ()
+/* incomplete lines are bad! */
commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10
@@ -19,9 +18,10 @@ Date: Thu Feb 28 10:48:10 2013 +0100
change to an incomplete line at end
diff --git a/a.c b/a.c
index d325124..e4fa1d8 100644
--- a/a.c
+++ b/a.c
@@ -22,1 +22,1 @@
@@ -22,1 +22,1 @@ int main ()
-}
+}
\ No newline at end of file
@@ -33,6 +33,8 @@ Date: Thu Feb 28 10:44:48 2013 +0100
initial
diff --git a/a.c b/a.c
new file mode 100644
index 0000000..9f550c3
--- /dev/null
+++ b/a.c
@@ -0,0 +20,1 @@