diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
#include "cache.h"
|
|
|
|
#include "commit.h"
|
2006-04-02 20:44:09 +08:00
|
|
|
#include "blob.h"
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
#include "diff.h"
|
|
|
|
#include "diffcore.h"
|
|
|
|
#include "quote.h"
|
2006-04-05 17:03:58 +08:00
|
|
|
#include "xdiff-interface.h"
|
2013-03-15 05:03:14 +08:00
|
|
|
#include "xdiff/xmacros.h"
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
#include "log-tree.h"
|
2009-04-30 03:49:52 +08:00
|
|
|
#include "refs.h"
|
2011-05-24 04:27:34 +08:00
|
|
|
#include "userdiff.h"
|
2011-12-17 18:15:48 +08:00
|
|
|
#include "sha1-array.h"
|
log: use true parents for diff even when rewriting
When using pathspec filtering in combination with diff-based log
output, parent simplification happens before the diff is computed.
The diff is therefore against the *simplified* parents.
This works okay, arguably by accident, in the normal case:
simplification reduces to one parent as long as the commit is TREESAME
to it. So the simplified parent of any given commit must have the
same tree contents on the filtered paths as its true (unfiltered)
parent.
However, --full-diff breaks this guarantee, and indeed gives pretty
spectacular results when comparing the output of
git log --graph --stat ...
git log --graph --full-diff --stat ...
(--graph internally kicks in parent simplification, much like
--parents).
To fix it, store a copy of the parent list before simplification (in a
slab) whenever --full-diff is in effect. Then use the stored parents
instead of the simplified ones in the commit display code paths. The
latter do not actually check for --full-diff to avoid duplicated code;
they just grab the original parents if save_parents() has not been
called for this revision walk.
For ordinary commits it should be obvious that this is the right thing
to do.
Merge commits are a bit subtle. Observe that with default
simplification, merge simplification is an all-or-nothing decision:
either the merge is TREESAME to one parent and disappears, or it is
different from all parents and the parent list remains intact.
Redundant parents are not pruned, so the existing code also shows them
as a merge.
So if we do show a merge commit, the parent list just consists of the
rewrite result on each parent. Running, e.g., --cc on this in
--full-diff mode is not very useful: if any commits were skipped, some
hunks will disagree with all sides of the merge (with one side,
because commits were skipped; with the others, because they didn't
have those changes in the first place). This triggers --cc showing
these hunks spuriously.
Therefore I believe that even for merge commits it is better to show
the diffs wrt. the original parents.
Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Thomas Rast <trast@inf.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-08-01 04:13:20 +08:00
|
|
|
#include "revision.h"
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
intersect_paths: respect mode in git's tree-sort
When we do a combined diff, we individually diff against
each parent, and then use intersect_paths to do a parallel
walk through the sorted results and come up with a final
list of interesting paths.
The sort order here is that returned by the diffs, which
means it is in git's tree-order which sorts sub-trees as if
their paths have "/" at the end. When we do our parallel
walk, we need to use a comparison function which provides
the same order.
Since 8518ff8 (combine-diff: optimize combine_diff_path sets
intersection, 2014-01-20), we use a simple strcmp to
compare the pathnames, and get this wrong. It's somewhat
hard to trigger because normally a diff does not produce
tree entries at all, and therefore the sort order is the
same as a strcmp. However, if the "-t" option is used with
the diff, then we will produce diff_filepairs for both trees
and files.
We can use base_name_compare to do the comparison, just as
the tree-diff code does. Even though what we have are not
technically base names (they are full paths within the
tree), the end result is the same (we do not care about
interior slashes at all, only about the final character).
However, since we do not have the length of each path
stored, we take a slight shortcut: if neither of the entries
is a sub-tree then the comparison is equivalent to a strcmp.
This lets us skip the extra strlen calls in the common case
without having to reimplement base_name_compare from
scratch.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-08-20 10:14:30 +08:00
|
|
|
static int compare_paths(const struct combine_diff_path *one,
|
|
|
|
const struct diff_filespec *two)
|
|
|
|
{
|
|
|
|
if (!S_ISDIR(one->mode) && !S_ISDIR(two->mode))
|
|
|
|
return strcmp(one->path, two->path);
|
|
|
|
|
|
|
|
return base_name_compare(one->path, strlen(one->path), one->mode,
|
|
|
|
two->path, strlen(two->path), two->mode);
|
|
|
|
}
|
|
|
|
|
2006-01-28 16:03:38 +08:00
|
|
|
static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
{
|
|
|
|
struct diff_queue_struct *q = &diff_queued_diff;
|
combine-diff: simplify intersect_paths() further
Linus once said:
I actually wish more people understood the really core low-level
kind of coding. Not big, complex stuff like the lockless name
lookup, but simply good use of pointers-to-pointers etc. For
example, I've seen too many people who delete a singly-linked
list entry by keeping track of the "prev" entry, and then to
delete the entry, doing something like
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person
doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry
pointer", and initialize that with the address of the
list_head. And then as they traverse the list, they can remove
the entry without using any conditionals, by just doing a "*pp =
entry->next".
Applying that simplification lets us lose 7 lines from this function
even while adding 2 lines of comment.
I was tempted to squash this into the original commit, but because
the benchmarking described in the commit log is without this
simplification, I decided to keep it a separate follow-up patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-29 05:55:59 +08:00
|
|
|
struct combine_diff_path *p, **tail = &curr;
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
int i, cmp;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
|
|
|
if (!n) {
|
|
|
|
for (i = 0; i < q->nr; i++) {
|
|
|
|
int len;
|
|
|
|
const char *path;
|
2006-08-15 09:36:00 +08:00
|
|
|
if (diff_unmodified_pair(q->queue[i]))
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
continue;
|
|
|
|
path = q->queue[i]->two->path;
|
|
|
|
len = strlen(path);
|
2006-02-07 04:53:07 +08:00
|
|
|
p = xmalloc(combine_diff_path_size(num_parent, len));
|
2009-05-01 17:06:36 +08:00
|
|
|
p->path = (char *) &(p->parent[num_parent]);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
memcpy(p->path, path, len);
|
|
|
|
p->path[len] = 0;
|
|
|
|
p->next = NULL;
|
2006-02-07 04:53:07 +08:00
|
|
|
memset(p->parent, 0,
|
|
|
|
sizeof(p->parent[0]) * num_parent);
|
|
|
|
|
2006-08-23 14:49:00 +08:00
|
|
|
hashcpy(p->sha1, q->queue[i]->two->sha1);
|
2006-02-07 04:53:07 +08:00
|
|
|
p->mode = q->queue[i]->two->mode;
|
2006-08-23 14:49:00 +08:00
|
|
|
hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1);
|
2006-02-07 04:53:07 +08:00
|
|
|
p->parent[n].mode = q->queue[i]->one->mode;
|
2006-02-10 18:30:52 +08:00
|
|
|
p->parent[n].status = q->queue[i]->status;
|
2006-01-25 19:34:10 +08:00
|
|
|
*tail = p;
|
|
|
|
tail = &p->next;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
combine-diff: simplify intersect_paths() further
Linus once said:
I actually wish more people understood the really core low-level
kind of coding. Not big, complex stuff like the lockless name
lookup, but simply good use of pointers-to-pointers etc. For
example, I've seen too many people who delete a singly-linked
list entry by keeping track of the "prev" entry, and then to
delete the entry, doing something like
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person
doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry
pointer", and initialize that with the address of the
list_head. And then as they traverse the list, they can remove
the entry without using any conditionals, by just doing a "*pp =
entry->next".
Applying that simplification lets us lose 7 lines from this function
even while adding 2 lines of comment.
I was tempted to squash this into the original commit, but because
the benchmarking described in the commit log is without this
simplification, I decided to keep it a separate follow-up patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-29 05:55:59 +08:00
|
|
|
return curr;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
/*
|
combine-diff: simplify intersect_paths() further
Linus once said:
I actually wish more people understood the really core low-level
kind of coding. Not big, complex stuff like the lockless name
lookup, but simply good use of pointers-to-pointers etc. For
example, I've seen too many people who delete a singly-linked
list entry by keeping track of the "prev" entry, and then to
delete the entry, doing something like
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person
doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry
pointer", and initialize that with the address of the
list_head. And then as they traverse the list, they can remove
the entry without using any conditionals, by just doing a "*pp =
entry->next".
Applying that simplification lets us lose 7 lines from this function
even while adding 2 lines of comment.
I was tempted to squash this into the original commit, but because
the benchmarking described in the commit log is without this
simplification, I decided to keep it a separate follow-up patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-29 05:55:59 +08:00
|
|
|
* paths in curr (linked list) and q->queue[] (array) are
|
|
|
|
* both sorted in the tree order.
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
*/
|
|
|
|
i = 0;
|
combine-diff: simplify intersect_paths() further
Linus once said:
I actually wish more people understood the really core low-level
kind of coding. Not big, complex stuff like the lockless name
lookup, but simply good use of pointers-to-pointers etc. For
example, I've seen too many people who delete a singly-linked
list entry by keeping track of the "prev" entry, and then to
delete the entry, doing something like
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person
doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry
pointer", and initialize that with the address of the
list_head. And then as they traverse the list, they can remove
the entry without using any conditionals, by just doing a "*pp =
entry->next".
Applying that simplification lets us lose 7 lines from this function
even while adding 2 lines of comment.
I was tempted to squash this into the original commit, but because
the benchmarking described in the commit log is without this
simplification, I decided to keep it a separate follow-up patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-29 05:55:59 +08:00
|
|
|
while ((p = *tail) != NULL) {
|
|
|
|
cmp = ((i >= q->nr)
|
intersect_paths: respect mode in git's tree-sort
When we do a combined diff, we individually diff against
each parent, and then use intersect_paths to do a parallel
walk through the sorted results and come up with a final
list of interesting paths.
The sort order here is that returned by the diffs, which
means it is in git's tree-order which sorts sub-trees as if
their paths have "/" at the end. When we do our parallel
walk, we need to use a comparison function which provides
the same order.
Since 8518ff8 (combine-diff: optimize combine_diff_path sets
intersection, 2014-01-20), we use a simple strcmp to
compare the pathnames, and get this wrong. It's somewhat
hard to trigger because normally a diff does not produce
tree entries at all, and therefore the sort order is the
same as a strcmp. However, if the "-t" option is used with
the diff, then we will produce diff_filepairs for both trees
and files.
We can use base_name_compare to do the comparison, just as
the tree-diff code does. Even though what we have are not
technically base names (they are full paths within the
tree), the end result is the same (we do not care about
interior slashes at all, only about the final character).
However, since we do not have the length of each path
stored, we take a slight shortcut: if neither of the entries
is a sub-tree then the comparison is equivalent to a strcmp.
This lets us skip the extra strlen calls in the common case
without having to reimplement base_name_compare from
scratch.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-08-20 10:14:30 +08:00
|
|
|
? -1 : compare_paths(p, q->queue[i]->two));
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
|
|
|
|
if (cmp < 0) {
|
combine-diff: simplify intersect_paths() further
Linus once said:
I actually wish more people understood the really core low-level
kind of coding. Not big, complex stuff like the lockless name
lookup, but simply good use of pointers-to-pointers etc. For
example, I've seen too many people who delete a singly-linked
list entry by keeping track of the "prev" entry, and then to
delete the entry, doing something like
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person
doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry
pointer", and initialize that with the address of the
list_head. And then as they traverse the list, they can remove
the entry without using any conditionals, by just doing a "*pp =
entry->next".
Applying that simplification lets us lose 7 lines from this function
even while adding 2 lines of comment.
I was tempted to squash this into the original commit, but because
the benchmarking described in the commit log is without this
simplification, I decided to keep it a separate follow-up patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-29 05:55:59 +08:00
|
|
|
/* p->path not in q->queue[]; drop it */
|
|
|
|
*tail = p->next;
|
|
|
|
free(p);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
continue;
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
}
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
if (cmp > 0) {
|
combine-diff: simplify intersect_paths() further
Linus once said:
I actually wish more people understood the really core low-level
kind of coding. Not big, complex stuff like the lockless name
lookup, but simply good use of pointers-to-pointers etc. For
example, I've seen too many people who delete a singly-linked
list entry by keeping track of the "prev" entry, and then to
delete the entry, doing something like
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person
doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry
pointer", and initialize that with the address of the
list_head. And then as they traverse the list, they can remove
the entry without using any conditionals, by just doing a "*pp =
entry->next".
Applying that simplification lets us lose 7 lines from this function
even while adding 2 lines of comment.
I was tempted to squash this into the original commit, but because
the benchmarking described in the commit log is without this
simplification, I decided to keep it a separate follow-up patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-29 05:55:59 +08:00
|
|
|
/* q->queue[i] not in p->path; skip it */
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
i++;
|
|
|
|
continue;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
|
|
|
|
hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1);
|
|
|
|
p->parent[n].mode = q->queue[i]->one->mode;
|
|
|
|
p->parent[n].status = q->queue[i]->status;
|
|
|
|
|
combine-diff: simplify intersect_paths() further
Linus once said:
I actually wish more people understood the really core low-level
kind of coding. Not big, complex stuff like the lockless name
lookup, but simply good use of pointers-to-pointers etc. For
example, I've seen too many people who delete a singly-linked
list entry by keeping track of the "prev" entry, and then to
delete the entry, doing something like
if (prev)
prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person
doesn't understand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entry
pointer", and initialize that with the address of the
list_head. And then as they traverse the list, they can remove
the entry without using any conditionals, by just doing a "*pp =
entry->next".
Applying that simplification lets us lose 7 lines from this function
even while adding 2 lines of comment.
I was tempted to squash this into the original commit, but because
the benchmarking described in the commit log is without this
simplification, I decided to keep it a separate follow-up patch.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-29 05:55:59 +08:00
|
|
|
tail = &p->next;
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
i++;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
return curr;
|
|
|
|
}
|
|
|
|
|
2006-01-31 08:34:29 +08:00
|
|
|
/* Lines lost from parent */
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
struct lline {
|
2013-03-24 01:23:28 +08:00
|
|
|
struct lline *next, *prev;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
int len;
|
|
|
|
unsigned long parent_map;
|
|
|
|
char line[FLEX_ARRAY];
|
|
|
|
};
|
|
|
|
|
2013-03-24 01:23:28 +08:00
|
|
|
/* Lines lost from current parent (before coalescing) */
|
|
|
|
struct plost {
|
|
|
|
struct lline *lost_head, *lost_tail;
|
|
|
|
int len;
|
|
|
|
};
|
|
|
|
|
2006-01-31 08:34:29 +08:00
|
|
|
/* Lines surviving in the merge result */
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
struct sline {
|
2013-03-24 01:23:28 +08:00
|
|
|
/* Accumulated and coalesced lost lines */
|
|
|
|
struct lline *lost;
|
|
|
|
int lenlost;
|
|
|
|
struct plost plost;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
char *bol;
|
|
|
|
int len;
|
2006-02-03 07:17:42 +08:00
|
|
|
/* bit 0 up to (N-1) are on if the parent has this line (i.e.
|
|
|
|
* we did not change it).
|
2006-01-31 08:34:29 +08:00
|
|
|
* bit N is used for "interesting" lines, including context.
|
2008-06-19 14:59:41 +08:00
|
|
|
* bit (N+1) is used for "do not show deletion before this".
|
2006-01-31 08:34:29 +08:00
|
|
|
*/
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
unsigned long flag;
|
2006-01-31 14:33:15 +08:00
|
|
|
unsigned long *p_lno;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
};
|
|
|
|
|
2013-03-15 05:03:14 +08:00
|
|
|
static int match_string_spaces(const char *line1, int len1,
|
|
|
|
const char *line2, int len2,
|
|
|
|
long flags)
|
|
|
|
{
|
|
|
|
if (flags & XDF_WHITESPACE_FLAGS) {
|
|
|
|
for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--);
|
|
|
|
for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(flags & (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE)))
|
|
|
|
return (len1 == len2 && !memcmp(line1, line2, len1));
|
|
|
|
|
|
|
|
while (len1 > 0 && len2 > 0) {
|
|
|
|
len1--;
|
|
|
|
len2--;
|
|
|
|
if (XDL_ISSPACE(line1[len1]) || XDL_ISSPACE(line2[len2])) {
|
|
|
|
if ((flags & XDF_IGNORE_WHITESPACE_CHANGE) &&
|
|
|
|
(!XDL_ISSPACE(line1[len1]) || !XDL_ISSPACE(line2[len2])))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (; len1 > 0 && XDL_ISSPACE(line1[len1]); len1--);
|
|
|
|
for (; len2 > 0 && XDL_ISSPACE(line2[len2]); len2--);
|
|
|
|
}
|
|
|
|
if (line1[len1] != line2[len2])
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & XDF_IGNORE_WHITESPACE) {
|
|
|
|
/* Consume remaining spaces */
|
|
|
|
for (; len1 > 0 && XDL_ISSPACE(line1[len1 - 1]); len1--);
|
|
|
|
for (; len2 > 0 && XDL_ISSPACE(line2[len2 - 1]); len2--);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We matched full line1 and line2 */
|
|
|
|
if (!len1 && !len2)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-03-24 01:23:28 +08:00
|
|
|
enum coalesce_direction { MATCH, BASE, NEW };
|
|
|
|
|
|
|
|
/* Coalesce new lines into base by finding LCS */
|
|
|
|
static struct lline *coalesce_lines(struct lline *base, int *lenbase,
|
|
|
|
struct lline *new, int lennew,
|
|
|
|
unsigned long parent, long flags)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
{
|
2013-03-24 01:23:28 +08:00
|
|
|
int **lcs;
|
|
|
|
enum coalesce_direction **directions;
|
|
|
|
struct lline *baseend, *newend = NULL;
|
|
|
|
int i, j, origbaselen = *lenbase;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2013-03-24 01:23:28 +08:00
|
|
|
if (new == NULL)
|
|
|
|
return base;
|
|
|
|
|
|
|
|
if (base == NULL) {
|
|
|
|
*lenbase = lennew;
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Coalesce new lines into base by finding the LCS
|
2013-07-29 16:18:21 +08:00
|
|
|
* - Create the table to run dynamic programming
|
2013-03-24 01:23:28 +08:00
|
|
|
* - Compute the LCS
|
|
|
|
* - Then reverse read the direction structure:
|
|
|
|
* - If we have MATCH, assign parent to base flag, and consume
|
|
|
|
* both baseend and newend
|
|
|
|
* - Else if we have BASE, consume baseend
|
|
|
|
* - Else if we have NEW, insert newend lline into base and
|
|
|
|
* consume newend
|
|
|
|
*/
|
|
|
|
lcs = xcalloc(origbaselen + 1, sizeof(int*));
|
|
|
|
directions = xcalloc(origbaselen + 1, sizeof(enum coalesce_direction*));
|
|
|
|
for (i = 0; i < origbaselen + 1; i++) {
|
|
|
|
lcs[i] = xcalloc(lennew + 1, sizeof(int));
|
|
|
|
directions[i] = xcalloc(lennew + 1, sizeof(enum coalesce_direction));
|
|
|
|
directions[i][0] = BASE;
|
|
|
|
}
|
|
|
|
for (j = 1; j < lennew + 1; j++)
|
|
|
|
directions[0][j] = NEW;
|
|
|
|
|
|
|
|
for (i = 1, baseend = base; i < origbaselen + 1; i++) {
|
|
|
|
for (j = 1, newend = new; j < lennew + 1; j++) {
|
|
|
|
if (match_string_spaces(baseend->line, baseend->len,
|
|
|
|
newend->line, newend->len, flags)) {
|
|
|
|
lcs[i][j] = lcs[i - 1][j - 1] + 1;
|
|
|
|
directions[i][j] = MATCH;
|
|
|
|
} else if (lcs[i][j - 1] >= lcs[i - 1][j]) {
|
|
|
|
lcs[i][j] = lcs[i][j - 1];
|
|
|
|
directions[i][j] = NEW;
|
|
|
|
} else {
|
|
|
|
lcs[i][j] = lcs[i - 1][j];
|
|
|
|
directions[i][j] = BASE;
|
|
|
|
}
|
|
|
|
if (newend->next)
|
|
|
|
newend = newend->next;
|
|
|
|
}
|
|
|
|
if (baseend->next)
|
|
|
|
baseend = baseend->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < origbaselen + 1; i++)
|
|
|
|
free(lcs[i]);
|
|
|
|
free(lcs);
|
|
|
|
|
|
|
|
/* At this point, baseend and newend point to the end of each lists */
|
|
|
|
i--;
|
|
|
|
j--;
|
|
|
|
while (i != 0 || j != 0) {
|
|
|
|
if (directions[i][j] == MATCH) {
|
|
|
|
baseend->parent_map |= 1<<parent;
|
|
|
|
baseend = baseend->prev;
|
|
|
|
newend = newend->prev;
|
|
|
|
i--;
|
|
|
|
j--;
|
|
|
|
} else if (directions[i][j] == NEW) {
|
|
|
|
struct lline *lline;
|
|
|
|
|
|
|
|
lline = newend;
|
|
|
|
/* Remove lline from new list and update newend */
|
|
|
|
if (lline->prev)
|
|
|
|
lline->prev->next = lline->next;
|
|
|
|
else
|
|
|
|
new = lline->next;
|
|
|
|
if (lline->next)
|
|
|
|
lline->next->prev = lline->prev;
|
|
|
|
|
|
|
|
newend = lline->prev;
|
|
|
|
j--;
|
|
|
|
|
|
|
|
/* Add lline to base list */
|
|
|
|
if (baseend) {
|
|
|
|
lline->next = baseend->next;
|
|
|
|
lline->prev = baseend;
|
|
|
|
if (lline->prev)
|
|
|
|
lline->prev->next = lline;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
2013-03-24 01:23:28 +08:00
|
|
|
else {
|
|
|
|
lline->next = base;
|
|
|
|
base = lline;
|
|
|
|
}
|
|
|
|
(*lenbase)++;
|
|
|
|
|
|
|
|
if (lline->next)
|
|
|
|
lline->next->prev = lline;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
baseend = baseend->prev;
|
|
|
|
i--;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-24 01:23:28 +08:00
|
|
|
newend = new;
|
|
|
|
while (newend) {
|
|
|
|
struct lline *lline = newend;
|
|
|
|
newend = newend->next;
|
|
|
|
free(lline);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < origbaselen + 1; i++)
|
|
|
|
free(directions[i]);
|
|
|
|
free(directions);
|
|
|
|
|
|
|
|
return base;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *grab_blob(const unsigned char *sha1, unsigned int mode,
|
|
|
|
unsigned long *size, struct userdiff_driver *textconv,
|
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
char *blob;
|
|
|
|
enum object_type type;
|
|
|
|
|
|
|
|
if (S_ISGITLINK(mode)) {
|
|
|
|
blob = xmalloc(100);
|
|
|
|
*size = snprintf(blob, 100,
|
|
|
|
"Subproject commit %s\n", sha1_to_hex(sha1));
|
|
|
|
} else if (is_null_sha1(sha1)) {
|
|
|
|
/* deleted blob */
|
|
|
|
*size = 0;
|
|
|
|
return xcalloc(1, 1);
|
|
|
|
} else if (textconv) {
|
|
|
|
struct diff_filespec *df = alloc_filespec(path);
|
|
|
|
fill_filespec(df, sha1, 1, mode);
|
|
|
|
*size = fill_textconv(textconv, df, &blob);
|
|
|
|
free_filespec(df);
|
|
|
|
} else {
|
|
|
|
blob = read_sha1_file(sha1, &type, size);
|
|
|
|
if (type != OBJ_BLOB)
|
|
|
|
die("object '%s' is not a blob!", sha1_to_hex(sha1));
|
|
|
|
}
|
|
|
|
return blob;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void append_lost(struct sline *sline, int n, const char *line, int len)
|
|
|
|
{
|
|
|
|
struct lline *lline;
|
|
|
|
unsigned long this_mask = (1UL<<n);
|
|
|
|
if (line[len-1] == '\n')
|
|
|
|
len--;
|
|
|
|
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
lline = xmalloc(sizeof(*lline) + len + 1);
|
|
|
|
lline->len = len;
|
|
|
|
lline->next = NULL;
|
2013-03-24 01:23:28 +08:00
|
|
|
lline->prev = sline->plost.lost_tail;
|
|
|
|
if (lline->prev)
|
|
|
|
lline->prev->next = lline;
|
|
|
|
else
|
|
|
|
sline->plost.lost_head = lline;
|
|
|
|
sline->plost.lost_tail = lline;
|
|
|
|
sline->plost.len++;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
lline->parent_map = this_mask;
|
|
|
|
memcpy(lline->line, line, len);
|
|
|
|
lline->line[len] = 0;
|
|
|
|
}
|
|
|
|
|
2006-04-04 09:53:15 +08:00
|
|
|
struct combine_diff_state {
|
2006-04-07 13:29:55 +08:00
|
|
|
unsigned int lno;
|
|
|
|
int ob, on, nb, nn;
|
2006-04-04 09:53:15 +08:00
|
|
|
unsigned long nmask;
|
|
|
|
int num_parent;
|
|
|
|
int n;
|
|
|
|
struct sline *sline;
|
|
|
|
struct sline *lost_bucket;
|
|
|
|
};
|
|
|
|
|
2006-04-05 17:03:58 +08:00
|
|
|
static void consume_line(void *state_, char *line, unsigned long len)
|
2006-04-04 09:53:15 +08:00
|
|
|
{
|
2006-04-05 17:03:58 +08:00
|
|
|
struct combine_diff_state *state = state_;
|
2006-04-04 09:53:15 +08:00
|
|
|
if (5 < len && !memcmp("@@ -", line, 4)) {
|
|
|
|
if (parse_hunk_header(line, len,
|
|
|
|
&state->ob, &state->on,
|
|
|
|
&state->nb, &state->nn))
|
|
|
|
return;
|
|
|
|
state->lno = state->nb;
|
2009-07-23 05:48:29 +08:00
|
|
|
if (state->nn == 0) {
|
2006-04-04 09:53:15 +08:00
|
|
|
/* @@ -X,Y +N,0 @@ removed Y lines
|
|
|
|
* that would have come *after* line N
|
|
|
|
* in the result. Our lost buckets hang
|
|
|
|
* to the line after the removed lines,
|
2009-07-23 05:48:29 +08:00
|
|
|
*
|
|
|
|
* Note that this is correct even when N == 0,
|
|
|
|
* in which case the hunk removes the first
|
|
|
|
* line in the file.
|
2006-04-04 09:53:15 +08:00
|
|
|
*/
|
|
|
|
state->lost_bucket = &state->sline[state->nb];
|
2009-07-23 05:48:29 +08:00
|
|
|
if (!state->nb)
|
|
|
|
state->nb = 1;
|
|
|
|
} else {
|
2006-04-04 09:53:15 +08:00
|
|
|
state->lost_bucket = &state->sline[state->nb-1];
|
2009-07-23 05:48:29 +08:00
|
|
|
}
|
2006-04-04 09:53:15 +08:00
|
|
|
if (!state->sline[state->nb-1].p_lno)
|
|
|
|
state->sline[state->nb-1].p_lno =
|
|
|
|
xcalloc(state->num_parent,
|
|
|
|
sizeof(unsigned long));
|
|
|
|
state->sline[state->nb-1].p_lno[state->n] = state->ob;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!state->lost_bucket)
|
|
|
|
return; /* not in any hunk yet */
|
|
|
|
switch (line[0]) {
|
|
|
|
case '-':
|
2013-03-24 01:23:28 +08:00
|
|
|
append_lost(state->lost_bucket, state->n, line+1, len-1);
|
2006-04-04 09:53:15 +08:00
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
state->sline[state->lno-1].flag |= state->nmask;
|
|
|
|
state->lno++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-30 03:49:52 +08:00
|
|
|
static void combine_diff(const unsigned char *parent, unsigned int mode,
|
|
|
|
mmfile_t *result_file,
|
2006-06-28 16:38:19 +08:00
|
|
|
struct sline *sline, unsigned int cnt, int n,
|
2011-05-24 04:31:05 +08:00
|
|
|
int num_parent, int result_deleted,
|
|
|
|
struct userdiff_driver *textconv,
|
2013-03-15 05:03:14 +08:00
|
|
|
const char *path, long flags)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
{
|
2006-04-04 09:53:15 +08:00
|
|
|
unsigned int p_lno, lno;
|
2006-01-31 14:33:15 +08:00
|
|
|
unsigned long nmask = (1UL << n);
|
2006-04-04 09:53:15 +08:00
|
|
|
xpparam_t xpp;
|
|
|
|
xdemitconf_t xecfg;
|
|
|
|
mmfile_t parent_file;
|
|
|
|
struct combine_diff_state state;
|
|
|
|
unsigned long sz;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2010-04-15 20:59:37 +08:00
|
|
|
if (result_deleted)
|
2006-02-07 10:54:08 +08:00
|
|
|
return; /* result deleted */
|
|
|
|
|
2011-05-24 04:31:05 +08:00
|
|
|
parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path);
|
2006-04-04 09:53:15 +08:00
|
|
|
parent_file.size = sz;
|
2008-10-25 21:30:37 +08:00
|
|
|
memset(&xpp, 0, sizeof(xpp));
|
2013-03-15 05:03:14 +08:00
|
|
|
xpp.flags = flags;
|
2007-07-05 02:05:46 +08:00
|
|
|
memset(&xecfg, 0, sizeof(xecfg));
|
2006-04-04 09:53:15 +08:00
|
|
|
memset(&state, 0, sizeof(state));
|
|
|
|
state.nmask = nmask;
|
|
|
|
state.sline = sline;
|
|
|
|
state.lno = 1;
|
|
|
|
state.num_parent = num_parent;
|
|
|
|
state.n = n;
|
|
|
|
|
2008-08-14 14:18:22 +08:00
|
|
|
xdi_diff_outf(&parent_file, result_file, consume_line, &state,
|
2010-05-05 04:41:34 +08:00
|
|
|
&xpp, &xecfg);
|
2006-04-04 09:53:15 +08:00
|
|
|
free(parent_file.ptr);
|
2006-01-31 14:33:15 +08:00
|
|
|
|
|
|
|
/* Assign line numbers for this parent.
|
|
|
|
*
|
|
|
|
* sline[lno].p_lno[n] records the first line number
|
|
|
|
* (counting from 1) for parent N if the final hunk display
|
|
|
|
* started by showing sline[lno] (possibly showing the lost
|
|
|
|
* lines attached to it first).
|
|
|
|
*/
|
2006-04-11 18:13:29 +08:00
|
|
|
for (lno = 0, p_lno = 1; lno <= cnt; lno++) {
|
2006-01-31 14:33:15 +08:00
|
|
|
struct lline *ll;
|
|
|
|
sline[lno].p_lno[n] = p_lno;
|
|
|
|
|
2013-03-24 01:23:28 +08:00
|
|
|
/* Coalesce new lines */
|
|
|
|
if (sline[lno].plost.lost_head) {
|
|
|
|
struct sline *sl = &sline[lno];
|
|
|
|
sl->lost = coalesce_lines(sl->lost, &sl->lenlost,
|
|
|
|
sl->plost.lost_head,
|
|
|
|
sl->plost.len, n, flags);
|
|
|
|
sl->plost.lost_head = sl->plost.lost_tail = NULL;
|
|
|
|
sl->plost.len = 0;
|
|
|
|
}
|
|
|
|
|
2006-01-31 14:33:15 +08:00
|
|
|
/* How many lines would this sline advance the p_lno? */
|
2013-03-24 01:23:28 +08:00
|
|
|
ll = sline[lno].lost;
|
2006-01-31 14:33:15 +08:00
|
|
|
while (ll) {
|
|
|
|
if (ll->parent_map & nmask)
|
|
|
|
p_lno++; /* '-' means parent had it */
|
|
|
|
ll = ll->next;
|
|
|
|
}
|
2006-04-11 18:13:29 +08:00
|
|
|
if (lno < cnt && !(sline[lno].flag & nmask))
|
2006-01-31 14:33:15 +08:00
|
|
|
p_lno++; /* no '+' means parent had it */
|
|
|
|
}
|
|
|
|
sline[lno].p_lno[n] = p_lno; /* trailer */
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned long context = 3;
|
|
|
|
static char combine_marker = '@';
|
|
|
|
|
|
|
|
static int interesting(struct sline *sline, unsigned long all_mask)
|
|
|
|
{
|
2006-02-03 07:17:42 +08:00
|
|
|
/* If some parents lost lines here, or if we have added to
|
|
|
|
* some parent, it is interesting.
|
|
|
|
*/
|
2013-03-24 01:23:28 +08:00
|
|
|
return ((sline->flag & all_mask) || sline->lost);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
|
2006-01-26 19:53:01 +08:00
|
|
|
static unsigned long adjust_hunk_tail(struct sline *sline,
|
|
|
|
unsigned long all_mask,
|
|
|
|
unsigned long hunk_begin,
|
|
|
|
unsigned long i)
|
|
|
|
{
|
2006-02-03 07:17:42 +08:00
|
|
|
/* i points at the first uninteresting line. If the last line
|
|
|
|
* of the hunk was interesting only because it has some
|
|
|
|
* deletion, then it is not all that interesting for the
|
|
|
|
* purpose of giving trailing context lines. This is because
|
|
|
|
* we output '-' line and then unmodified sline[i-1] itself in
|
|
|
|
* that case which gives us one extra context line.
|
2006-01-26 19:53:01 +08:00
|
|
|
*/
|
2006-02-03 07:17:42 +08:00
|
|
|
if ((hunk_begin + 1 <= i) && !(sline[i-1].flag & all_mask))
|
2006-01-26 19:53:01 +08:00
|
|
|
i--;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2006-02-03 07:17:42 +08:00
|
|
|
static unsigned long find_next(struct sline *sline,
|
|
|
|
unsigned long mark,
|
|
|
|
unsigned long i,
|
|
|
|
unsigned long cnt,
|
2006-06-28 16:38:19 +08:00
|
|
|
int look_for_uninteresting)
|
2006-01-26 19:53:01 +08:00
|
|
|
{
|
2006-02-03 07:17:42 +08:00
|
|
|
/* We have examined up to i-1 and are about to look at i.
|
|
|
|
* Find next interesting or uninteresting line. Here,
|
|
|
|
* "interesting" does not mean interesting(), but marked by
|
|
|
|
* the give_context() function below (i.e. it includes context
|
|
|
|
* lines that are not interesting to interesting() function
|
|
|
|
* that are surrounded by interesting() ones.
|
|
|
|
*/
|
2006-04-12 05:31:31 +08:00
|
|
|
while (i <= cnt)
|
2006-06-28 16:38:19 +08:00
|
|
|
if (look_for_uninteresting
|
2006-02-03 07:17:42 +08:00
|
|
|
? !(sline[i].flag & mark)
|
|
|
|
: (sline[i].flag & mark))
|
2006-01-26 19:53:01 +08:00
|
|
|
return i;
|
|
|
|
else
|
|
|
|
i++;
|
2006-04-12 05:31:31 +08:00
|
|
|
return i;
|
2006-01-26 19:53:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int give_context(struct sline *sline, unsigned long cnt, int num_parent)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
{
|
|
|
|
unsigned long all_mask = (1UL<<num_parent) - 1;
|
|
|
|
unsigned long mark = (1UL<<num_parent);
|
2008-06-19 14:59:41 +08:00
|
|
|
unsigned long no_pre_delete = (2UL<<num_parent);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
unsigned long i;
|
|
|
|
|
2006-02-03 07:17:42 +08:00
|
|
|
/* Two groups of interesting lines may have a short gap of
|
2006-07-10 13:50:18 +08:00
|
|
|
* uninteresting lines. Connect such groups to give them a
|
2006-02-03 07:17:42 +08:00
|
|
|
* bit of context.
|
|
|
|
*
|
|
|
|
* We first start from what the interesting() function says,
|
|
|
|
* and mark them with "mark", and paint context lines with the
|
|
|
|
* mark. So interesting() would still say false for such context
|
|
|
|
* lines but they are treated as "interesting" in the end.
|
|
|
|
*/
|
|
|
|
i = find_next(sline, mark, 0, cnt, 0);
|
2006-04-12 05:31:31 +08:00
|
|
|
if (cnt < i)
|
2006-01-26 19:53:01 +08:00
|
|
|
return 0;
|
|
|
|
|
2006-04-12 05:31:31 +08:00
|
|
|
while (i <= cnt) {
|
2006-01-26 19:53:01 +08:00
|
|
|
unsigned long j = (context < i) ? (i - context) : 0;
|
|
|
|
unsigned long k;
|
2006-02-03 07:17:42 +08:00
|
|
|
|
|
|
|
/* Paint a few lines before the first interesting line. */
|
2013-05-16 01:42:14 +08:00
|
|
|
while (j < i) {
|
|
|
|
if (!(sline[j].flag & mark))
|
|
|
|
sline[j].flag |= no_pre_delete;
|
|
|
|
sline[j++].flag |= mark;
|
|
|
|
}
|
2006-01-26 19:53:01 +08:00
|
|
|
|
|
|
|
again:
|
2006-02-03 07:17:42 +08:00
|
|
|
/* we know up to i is to be included. where does the
|
|
|
|
* next uninteresting one start?
|
|
|
|
*/
|
|
|
|
j = find_next(sline, mark, i, cnt, 1);
|
2006-04-12 05:31:31 +08:00
|
|
|
if (cnt < j)
|
2006-01-26 19:53:01 +08:00
|
|
|
break; /* the rest are all interesting */
|
|
|
|
|
|
|
|
/* lookahead context lines */
|
2006-02-03 07:17:42 +08:00
|
|
|
k = find_next(sline, mark, j, cnt, 0);
|
2006-01-26 19:53:01 +08:00
|
|
|
j = adjust_hunk_tail(sline, all_mask, i, j);
|
|
|
|
|
|
|
|
if (k < j + context) {
|
|
|
|
/* k is interesting and [j,k) are not, but
|
|
|
|
* paint them interesting because the gap is small.
|
|
|
|
*/
|
|
|
|
while (j < k)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
sline[j++].flag |= mark;
|
2006-01-26 19:53:01 +08:00
|
|
|
i = k;
|
|
|
|
goto again;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
2006-01-26 19:53:01 +08:00
|
|
|
|
|
|
|
/* j is the first uninteresting line and there is
|
2006-02-03 07:17:42 +08:00
|
|
|
* no overlap beyond it within context lines. Paint
|
|
|
|
* the trailing edge a bit.
|
2006-01-26 19:53:01 +08:00
|
|
|
*/
|
|
|
|
i = k;
|
2006-04-12 05:31:31 +08:00
|
|
|
k = (j + context < cnt+1) ? j + context : cnt+1;
|
2006-01-26 19:53:01 +08:00
|
|
|
while (j < k)
|
|
|
|
sline[j++].flag |= mark;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int make_hunks(struct sline *sline, unsigned long cnt,
|
|
|
|
int num_parent, int dense)
|
|
|
|
{
|
|
|
|
unsigned long all_mask = (1UL<<num_parent) - 1;
|
|
|
|
unsigned long mark = (1UL<<num_parent);
|
|
|
|
unsigned long i;
|
|
|
|
int has_interesting = 0;
|
|
|
|
|
2006-04-12 05:31:31 +08:00
|
|
|
for (i = 0; i <= cnt; i++) {
|
2006-01-26 19:53:01 +08:00
|
|
|
if (interesting(&sline[i], all_mask))
|
|
|
|
sline[i].flag |= mark;
|
|
|
|
else
|
|
|
|
sline[i].flag &= ~mark;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
2006-01-24 17:22:04 +08:00
|
|
|
if (!dense)
|
2006-01-26 19:53:01 +08:00
|
|
|
return give_context(sline, cnt, num_parent);
|
2006-01-24 17:22:04 +08:00
|
|
|
|
2006-01-26 05:11:38 +08:00
|
|
|
/* Look at each hunk, and if we have changes from only one
|
|
|
|
* parent, or the changes are the same from all but one
|
|
|
|
* parent, mark that uninteresting.
|
2006-01-24 17:22:04 +08:00
|
|
|
*/
|
|
|
|
i = 0;
|
2006-04-12 05:31:31 +08:00
|
|
|
while (i <= cnt) {
|
2006-01-26 19:53:01 +08:00
|
|
|
unsigned long j, hunk_begin, hunk_end;
|
2006-02-02 16:12:55 +08:00
|
|
|
unsigned long same_diff;
|
2006-04-12 05:31:31 +08:00
|
|
|
while (i <= cnt && !(sline[i].flag & mark))
|
2006-01-24 17:22:04 +08:00
|
|
|
i++;
|
2006-04-12 05:31:31 +08:00
|
|
|
if (cnt < i)
|
2006-01-24 17:22:04 +08:00
|
|
|
break; /* No more interesting hunks */
|
2006-01-26 19:53:01 +08:00
|
|
|
hunk_begin = i;
|
2006-04-12 05:31:31 +08:00
|
|
|
for (j = i + 1; j <= cnt; j++) {
|
2006-01-26 19:53:01 +08:00
|
|
|
if (!(sline[j].flag & mark)) {
|
|
|
|
/* Look beyond the end to see if there
|
|
|
|
* is an interesting line after this
|
|
|
|
* hunk within context span.
|
|
|
|
*/
|
|
|
|
unsigned long la; /* lookahead */
|
|
|
|
int contin = 0;
|
|
|
|
la = adjust_hunk_tail(sline, all_mask,
|
|
|
|
hunk_begin, j);
|
2006-04-12 05:31:31 +08:00
|
|
|
la = (la + context < cnt + 1) ?
|
|
|
|
(la + context) : cnt + 1;
|
2012-03-24 23:18:46 +08:00
|
|
|
while (la && j <= --la) {
|
2006-01-26 19:53:01 +08:00
|
|
|
if (sline[la].flag & mark) {
|
|
|
|
contin = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!contin)
|
|
|
|
break;
|
|
|
|
j = la;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hunk_end = j;
|
|
|
|
|
2006-02-02 16:12:55 +08:00
|
|
|
/* [i..hunk_end) are interesting. Now is it really
|
2006-02-02 17:28:08 +08:00
|
|
|
* interesting? We check if there are only two versions
|
|
|
|
* and the result matches one of them. That is, we look
|
|
|
|
* at:
|
|
|
|
* (+) line, which records lines added to which parents;
|
|
|
|
* this line appears in the result.
|
|
|
|
* (-) line, which records from what parents the line
|
|
|
|
* was removed; this line does not appear in the result.
|
|
|
|
* then check the set of parents the result has difference
|
|
|
|
* from, from all lines. If there are lines that has
|
|
|
|
* different set of parents that the result has differences
|
|
|
|
* from, that means we have more than two versions.
|
|
|
|
*
|
|
|
|
* Even when we have only two versions, if the result does
|
|
|
|
* not match any of the parents, the it should be considered
|
|
|
|
* interesting. In such a case, we would have all '+' line.
|
|
|
|
* After passing the above "two versions" test, that would
|
|
|
|
* appear as "the same set of parents" to be "all parents".
|
2006-01-24 17:22:04 +08:00
|
|
|
*/
|
2006-02-02 16:12:55 +08:00
|
|
|
same_diff = 0;
|
|
|
|
has_interesting = 0;
|
|
|
|
for (j = i; j < hunk_end && !has_interesting; j++) {
|
2006-02-03 07:17:42 +08:00
|
|
|
unsigned long this_diff = sline[j].flag & all_mask;
|
2013-03-24 01:23:28 +08:00
|
|
|
struct lline *ll = sline[j].lost;
|
2006-02-02 16:12:55 +08:00
|
|
|
if (this_diff) {
|
|
|
|
/* This has some changes. Is it the
|
|
|
|
* same as others?
|
|
|
|
*/
|
|
|
|
if (!same_diff)
|
|
|
|
same_diff = this_diff;
|
|
|
|
else if (same_diff != this_diff) {
|
|
|
|
has_interesting = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (ll && !has_interesting) {
|
|
|
|
/* Lost this line from these parents;
|
|
|
|
* who are they? Are they the same?
|
|
|
|
*/
|
|
|
|
this_diff = ll->parent_map;
|
|
|
|
if (!same_diff)
|
|
|
|
same_diff = this_diff;
|
|
|
|
else if (same_diff != this_diff) {
|
|
|
|
has_interesting = 1;
|
|
|
|
}
|
|
|
|
ll = ll->next;
|
|
|
|
}
|
2006-01-24 17:22:04 +08:00
|
|
|
}
|
2006-02-02 16:12:55 +08:00
|
|
|
|
2006-02-02 17:28:08 +08:00
|
|
|
if (!has_interesting && same_diff != all_mask) {
|
2006-01-24 17:22:04 +08:00
|
|
|
/* This hunk is not that interesting after all */
|
2006-01-26 19:53:01 +08:00
|
|
|
for (j = hunk_begin; j < hunk_end; j++)
|
2006-01-24 17:22:04 +08:00
|
|
|
sline[j].flag &= ~mark;
|
|
|
|
}
|
|
|
|
i = hunk_end;
|
|
|
|
}
|
2006-01-26 19:53:01 +08:00
|
|
|
|
|
|
|
has_interesting = give_context(sline, cnt, num_parent);
|
2006-01-26 06:26:22 +08:00
|
|
|
return has_interesting;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
|
2007-02-04 04:37:54 +08:00
|
|
|
static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long l1, int n, unsigned long null_context)
|
2006-01-31 14:33:15 +08:00
|
|
|
{
|
|
|
|
l0 = sline[l0].p_lno[n];
|
|
|
|
l1 = sline[l1].p_lno[n];
|
2007-02-04 04:37:54 +08:00
|
|
|
printf(" -%lu,%lu", l0, l1-l0-null_context);
|
2006-01-31 14:33:15 +08:00
|
|
|
}
|
|
|
|
|
2006-10-26 15:05:04 +08:00
|
|
|
static int hunk_comment_line(const char *bol)
|
|
|
|
{
|
2006-10-26 17:05:05 +08:00
|
|
|
int ch;
|
|
|
|
|
|
|
|
if (!bol)
|
|
|
|
return 0;
|
|
|
|
ch = *bol & 0xff;
|
2006-10-26 15:05:04 +08:00
|
|
|
return (isalpha(ch) || ch == '_' || ch == '$');
|
|
|
|
}
|
|
|
|
|
2008-08-28 10:48:01 +08:00
|
|
|
static void show_line_to_eol(const char *line, int len, const char *reset)
|
|
|
|
{
|
|
|
|
int saw_cr_at_eol = 0;
|
|
|
|
if (len < 0)
|
|
|
|
len = strlen(line);
|
|
|
|
saw_cr_at_eol = (len && line[len-1] == '\r');
|
|
|
|
|
|
|
|
printf("%.*s%s%s\n", len - saw_cr_at_eol, line,
|
|
|
|
reset,
|
|
|
|
saw_cr_at_eol ? "\r" : "");
|
|
|
|
}
|
|
|
|
|
2013-02-08 04:15:28 +08:00
|
|
|
static void dump_sline(struct sline *sline, const char *line_prefix,
|
|
|
|
unsigned long cnt, int num_parent,
|
2010-04-15 20:59:37 +08:00
|
|
|
int use_color, int result_deleted)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
{
|
|
|
|
unsigned long mark = (1UL<<num_parent);
|
2008-06-19 14:59:41 +08:00
|
|
|
unsigned long no_pre_delete = (2UL<<num_parent);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
int i;
|
2006-01-31 14:33:15 +08:00
|
|
|
unsigned long lno = 0;
|
2006-08-10 15:30:33 +08:00
|
|
|
const char *c_frag = diff_get_color(use_color, DIFF_FRAGINFO);
|
2009-11-27 14:55:18 +08:00
|
|
|
const char *c_func = diff_get_color(use_color, DIFF_FUNCINFO);
|
2006-08-10 15:30:33 +08:00
|
|
|
const char *c_new = diff_get_color(use_color, DIFF_FILE_NEW);
|
|
|
|
const char *c_old = diff_get_color(use_color, DIFF_FILE_OLD);
|
|
|
|
const char *c_plain = diff_get_color(use_color, DIFF_PLAIN);
|
|
|
|
const char *c_reset = diff_get_color(use_color, DIFF_RESET);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2010-04-15 20:59:37 +08:00
|
|
|
if (result_deleted)
|
2006-02-07 10:54:08 +08:00
|
|
|
return; /* result deleted */
|
|
|
|
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
while (1) {
|
2006-04-13 04:23:50 +08:00
|
|
|
unsigned long hunk_end;
|
|
|
|
unsigned long rlines;
|
2006-10-26 15:05:04 +08:00
|
|
|
const char *hunk_comment = NULL;
|
2007-02-04 04:37:54 +08:00
|
|
|
unsigned long null_context = 0;
|
2006-10-26 15:05:04 +08:00
|
|
|
|
|
|
|
while (lno <= cnt && !(sline[lno].flag & mark)) {
|
|
|
|
if (hunk_comment_line(sline[lno].bol))
|
|
|
|
hunk_comment = sline[lno].bol;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
lno++;
|
2006-10-26 15:05:04 +08:00
|
|
|
}
|
2006-04-11 18:13:29 +08:00
|
|
|
if (cnt < lno)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
break;
|
2006-04-11 18:13:29 +08:00
|
|
|
else {
|
2006-04-12 05:31:31 +08:00
|
|
|
for (hunk_end = lno + 1; hunk_end <= cnt; hunk_end++)
|
2006-04-11 18:13:29 +08:00
|
|
|
if (!(sline[hunk_end].flag & mark))
|
|
|
|
break;
|
|
|
|
}
|
2006-04-12 05:31:31 +08:00
|
|
|
rlines = hunk_end - lno;
|
|
|
|
if (cnt < hunk_end)
|
|
|
|
rlines--; /* pointing at the last delete hunk */
|
2007-02-04 04:37:54 +08:00
|
|
|
|
|
|
|
if (!context) {
|
|
|
|
/*
|
|
|
|
* Even when running with --unified=0, all
|
|
|
|
* lines in the hunk needs to be processed in
|
|
|
|
* the loop below in order to show the
|
|
|
|
* deletion recorded in lost_head. However,
|
|
|
|
* we do not want to show the resulting line
|
|
|
|
* with all blank context markers in such a
|
|
|
|
* case. Compensate.
|
|
|
|
*/
|
|
|
|
unsigned long j;
|
|
|
|
for (j = lno; j < hunk_end; j++)
|
|
|
|
if (!(sline[j].flag & (mark-1)))
|
|
|
|
null_context++;
|
|
|
|
rlines -= null_context;
|
|
|
|
}
|
|
|
|
|
2013-02-08 04:15:28 +08:00
|
|
|
printf("%s%s", line_prefix, c_frag);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
|
2006-01-31 14:33:15 +08:00
|
|
|
for (i = 0; i < num_parent; i++)
|
2007-02-04 04:37:54 +08:00
|
|
|
show_parent_lno(sline, lno, hunk_end, i, null_context);
|
2006-04-12 05:31:31 +08:00
|
|
|
printf(" +%lu,%lu ", lno+1, rlines);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
|
2006-10-26 15:05:04 +08:00
|
|
|
|
|
|
|
if (hunk_comment) {
|
|
|
|
int comment_end = 0;
|
|
|
|
for (i = 0; i < 40; i++) {
|
|
|
|
int ch = hunk_comment[i] & 0xff;
|
|
|
|
if (!ch || ch == '\n')
|
|
|
|
break;
|
|
|
|
if (!isspace(ch))
|
|
|
|
comment_end = i;
|
|
|
|
}
|
|
|
|
if (comment_end)
|
2009-11-27 14:55:18 +08:00
|
|
|
printf("%s%s %s%s", c_reset,
|
|
|
|
c_plain, c_reset,
|
|
|
|
c_func);
|
2006-10-26 15:05:04 +08:00
|
|
|
for (i = 0; i < comment_end; i++)
|
|
|
|
putchar(hunk_comment[i]);
|
|
|
|
}
|
|
|
|
|
2006-08-10 15:30:33 +08:00
|
|
|
printf("%s\n", c_reset);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
while (lno < hunk_end) {
|
|
|
|
struct lline *ll;
|
|
|
|
int j;
|
2006-02-03 07:17:42 +08:00
|
|
|
unsigned long p_mask;
|
2009-03-08 04:02:26 +08:00
|
|
|
struct sline *sl = &sline[lno++];
|
2013-03-24 01:23:28 +08:00
|
|
|
ll = (sl->flag & no_pre_delete) ? NULL : sl->lost;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
while (ll) {
|
2013-02-08 04:15:28 +08:00
|
|
|
printf("%s%s", line_prefix, c_old);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
for (j = 0; j < num_parent; j++) {
|
|
|
|
if (ll->parent_map & (1UL<<j))
|
|
|
|
putchar('-');
|
|
|
|
else
|
|
|
|
putchar(' ');
|
|
|
|
}
|
2008-08-28 10:48:01 +08:00
|
|
|
show_line_to_eol(ll->line, -1, c_reset);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
ll = ll->next;
|
|
|
|
}
|
2006-04-12 05:31:31 +08:00
|
|
|
if (cnt < lno)
|
2006-04-11 18:13:29 +08:00
|
|
|
break;
|
2006-02-03 07:17:42 +08:00
|
|
|
p_mask = 1;
|
2013-02-08 04:15:28 +08:00
|
|
|
fputs(line_prefix, stdout);
|
2007-02-04 04:37:54 +08:00
|
|
|
if (!(sl->flag & (mark-1))) {
|
|
|
|
/*
|
|
|
|
* This sline was here to hang the
|
|
|
|
* lost lines in front of it.
|
|
|
|
*/
|
|
|
|
if (!context)
|
|
|
|
continue;
|
2006-08-10 15:30:33 +08:00
|
|
|
fputs(c_plain, stdout);
|
2007-02-04 04:37:54 +08:00
|
|
|
}
|
2006-08-10 15:30:33 +08:00
|
|
|
else
|
|
|
|
fputs(c_new, stdout);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
for (j = 0; j < num_parent; j++) {
|
2006-02-03 07:17:42 +08:00
|
|
|
if (p_mask & sl->flag)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
putchar('+');
|
2006-02-03 07:17:42 +08:00
|
|
|
else
|
|
|
|
putchar(' ');
|
|
|
|
p_mask <<= 1;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
2008-08-28 10:48:01 +08:00
|
|
|
show_line_to_eol(sl->bol, sl->len, c_reset);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-02 15:29:03 +08:00
|
|
|
static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
|
|
|
|
int i, int j)
|
|
|
|
{
|
|
|
|
/* We have already examined parent j and we know parent i
|
|
|
|
* and parent j are the same, so reuse the combined result
|
|
|
|
* of parent j for parent i.
|
|
|
|
*/
|
|
|
|
unsigned long lno, imask, jmask;
|
|
|
|
imask = (1UL<<i);
|
|
|
|
jmask = (1UL<<j);
|
|
|
|
|
2006-04-11 18:13:29 +08:00
|
|
|
for (lno = 0; lno <= cnt; lno++) {
|
2013-03-24 01:23:28 +08:00
|
|
|
struct lline *ll = sline->lost;
|
2006-01-31 14:33:15 +08:00
|
|
|
sline->p_lno[i] = sline->p_lno[j];
|
2006-02-02 15:29:03 +08:00
|
|
|
while (ll) {
|
|
|
|
if (ll->parent_map & jmask)
|
|
|
|
ll->parent_map |= imask;
|
|
|
|
ll = ll->next;
|
|
|
|
}
|
2006-02-03 07:17:42 +08:00
|
|
|
if (sline->flag & jmask)
|
|
|
|
sline->flag |= imask;
|
2006-02-02 15:29:03 +08:00
|
|
|
sline++;
|
|
|
|
}
|
2006-02-07 10:54:08 +08:00
|
|
|
/* the overall size of the file (sline[cnt]) */
|
|
|
|
sline->p_lno[i] = sline->p_lno[j];
|
2006-02-02 15:29:03 +08:00
|
|
|
}
|
|
|
|
|
2007-12-27 08:51:19 +08:00
|
|
|
static void dump_quoted_path(const char *head,
|
|
|
|
const char *prefix,
|
|
|
|
const char *path,
|
2013-02-08 04:15:28 +08:00
|
|
|
const char *line_prefix,
|
2006-08-10 15:30:33 +08:00
|
|
|
const char *c_meta, const char *c_reset)
|
Log message printout cleanups (#2)
Here's a further patch on top of the previous one with cosmetic
improvements (no "real" code changes, just trivial updates):
- it gets the "---" before a diffstat right, including for the combined
merge case. Righ now the logic is that we always use "---" when we have
a diffstat, and an empty line otherwise. That's how I visually prefer
it, but hey, it can be tweaked later.
- I made "diff --cc/combined" add the "---/+++" header lines too. The
thing won't be mistaken for a valid diff, since the "@@" lines have too
many "@" characters (three or more), but it just makes it visually
match a real diff, which at least to me makes a big difference in
readability. Without them, it just looks very "wrong".
I guess I should have taken the filename from each individual entry
(and had one "---" file per parent), but I didn't even bother to try to
see how that works, so this was the simple thing.
With this, doing a
git log --cc --patch-with-stat
looks quite readable, I think. The only nagging issue - as far as I'm
concerned - is that diffstats for merges are pretty questionable the way
they are done now. I suspect it would be better to just have the _first_
diffstat, and always make the merge diffstat be the one for "result
against first parent".
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 07:59:42 +08:00
|
|
|
{
|
2007-12-27 08:51:19 +08:00
|
|
|
static struct strbuf buf = STRBUF_INIT;
|
|
|
|
|
|
|
|
strbuf_reset(&buf);
|
2013-02-08 04:15:28 +08:00
|
|
|
strbuf_addstr(&buf, line_prefix);
|
2007-12-27 08:51:19 +08:00
|
|
|
strbuf_addstr(&buf, c_meta);
|
|
|
|
strbuf_addstr(&buf, head);
|
2007-12-27 09:13:36 +08:00
|
|
|
quote_two_c_style(&buf, prefix, path, 0);
|
2007-12-27 08:51:19 +08:00
|
|
|
strbuf_addstr(&buf, c_reset);
|
|
|
|
puts(buf.buf);
|
Log message printout cleanups (#2)
Here's a further patch on top of the previous one with cosmetic
improvements (no "real" code changes, just trivial updates):
- it gets the "---" before a diffstat right, including for the combined
merge case. Righ now the logic is that we always use "---" when we have
a diffstat, and an empty line otherwise. That's how I visually prefer
it, but hey, it can be tweaked later.
- I made "diff --cc/combined" add the "---/+++" header lines too. The
thing won't be mistaken for a valid diff, since the "@@" lines have too
many "@" characters (three or more), but it just makes it visually
match a real diff, which at least to me makes a big difference in
readability. Without them, it just looks very "wrong".
I guess I should have taken the filename from each individual entry
(and had one "---" file per parent), but I didn't even bother to try to
see how that works, so this was the simple thing.
With this, doing a
git log --cc --patch-with-stat
looks quite readable, I think. The only nagging issue - as far as I'm
concerned - is that diffstats for merges are pretty questionable the way
they are done now. I suspect it would be better to just have the _first_
diffstat, and always make the merge diffstat be the one for "result
against first parent".
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 07:59:42 +08:00
|
|
|
}
|
|
|
|
|
2011-05-24 04:16:41 +08:00
|
|
|
static void show_combined_header(struct combine_diff_path *elem,
|
|
|
|
int num_parent,
|
|
|
|
int dense,
|
|
|
|
struct rev_info *rev,
|
2013-02-08 04:15:28 +08:00
|
|
|
const char *line_prefix,
|
2011-05-24 04:27:34 +08:00
|
|
|
int mode_differs,
|
|
|
|
int show_file_header)
|
2011-05-24 04:16:41 +08:00
|
|
|
{
|
|
|
|
struct diff_options *opt = &rev->diffopt;
|
|
|
|
int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
|
|
|
|
const char *a_prefix = opt->a_prefix ? opt->a_prefix : "a/";
|
|
|
|
const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/";
|
2011-08-18 13:03:12 +08:00
|
|
|
const char *c_meta = diff_get_color_opt(opt, DIFF_METAINFO);
|
|
|
|
const char *c_reset = diff_get_color_opt(opt, DIFF_RESET);
|
2011-05-24 04:16:41 +08:00
|
|
|
const char *abb;
|
|
|
|
int added = 0;
|
|
|
|
int deleted = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (rev->loginfo && !rev->no_commit_id)
|
|
|
|
show_log(rev);
|
|
|
|
|
|
|
|
dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
|
2013-02-08 04:15:28 +08:00
|
|
|
"", elem->path, line_prefix, c_meta, c_reset);
|
|
|
|
printf("%s%sindex ", line_prefix, c_meta);
|
2011-05-24 04:16:41 +08:00
|
|
|
for (i = 0; i < num_parent; i++) {
|
|
|
|
abb = find_unique_abbrev(elem->parent[i].sha1,
|
|
|
|
abbrev);
|
|
|
|
printf("%s%s", i ? "," : "", abb);
|
|
|
|
}
|
|
|
|
abb = find_unique_abbrev(elem->sha1, abbrev);
|
|
|
|
printf("..%s%s\n", abb, c_reset);
|
|
|
|
|
|
|
|
if (mode_differs) {
|
|
|
|
deleted = !elem->mode;
|
|
|
|
|
|
|
|
/* We say it was added if nobody had it */
|
|
|
|
added = !deleted;
|
|
|
|
for (i = 0; added && i < num_parent; i++)
|
|
|
|
if (elem->parent[i].status !=
|
|
|
|
DIFF_STATUS_ADDED)
|
|
|
|
added = 0;
|
|
|
|
if (added)
|
2013-02-08 04:15:28 +08:00
|
|
|
printf("%s%snew file mode %06o",
|
|
|
|
line_prefix, c_meta, elem->mode);
|
2011-05-24 04:16:41 +08:00
|
|
|
else {
|
|
|
|
if (deleted)
|
2013-02-08 04:15:28 +08:00
|
|
|
printf("%s%sdeleted file ",
|
|
|
|
line_prefix, c_meta);
|
2011-05-24 04:16:41 +08:00
|
|
|
printf("mode ");
|
|
|
|
for (i = 0; i < num_parent; i++) {
|
|
|
|
printf("%s%06o", i ? "," : "",
|
|
|
|
elem->parent[i].mode);
|
|
|
|
}
|
|
|
|
if (elem->mode)
|
|
|
|
printf("..%06o", elem->mode);
|
|
|
|
}
|
|
|
|
printf("%s\n", c_reset);
|
|
|
|
}
|
|
|
|
|
2011-05-24 04:27:34 +08:00
|
|
|
if (!show_file_header)
|
|
|
|
return;
|
|
|
|
|
2011-05-24 04:16:41 +08:00
|
|
|
if (added)
|
|
|
|
dump_quoted_path("--- ", "", "/dev/null",
|
2013-02-08 04:15:28 +08:00
|
|
|
line_prefix, c_meta, c_reset);
|
2011-05-24 04:16:41 +08:00
|
|
|
else
|
|
|
|
dump_quoted_path("--- ", a_prefix, elem->path,
|
2013-02-08 04:15:28 +08:00
|
|
|
line_prefix, c_meta, c_reset);
|
2011-05-24 04:16:41 +08:00
|
|
|
if (deleted)
|
|
|
|
dump_quoted_path("+++ ", "", "/dev/null",
|
2013-02-08 04:15:28 +08:00
|
|
|
line_prefix, c_meta, c_reset);
|
2011-05-24 04:16:41 +08:00
|
|
|
else
|
|
|
|
dump_quoted_path("+++ ", b_prefix, elem->path,
|
2013-02-08 04:15:28 +08:00
|
|
|
line_prefix, c_meta, c_reset);
|
2011-05-24 04:16:41 +08:00
|
|
|
}
|
|
|
|
|
2006-08-14 10:19:34 +08:00
|
|
|
static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
|
2011-08-05 02:39:10 +08:00
|
|
|
int dense, int working_tree_file,
|
|
|
|
struct rev_info *rev)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
{
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
struct diff_options *opt = &rev->diffopt;
|
2006-04-04 09:53:15 +08:00
|
|
|
unsigned long result_size, cnt, lno;
|
2010-04-15 20:59:37 +08:00
|
|
|
int result_deleted = 0;
|
2006-04-17 23:14:47 +08:00
|
|
|
char *result, *cp;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
struct sline *sline; /* survived lines */
|
2006-02-07 04:53:07 +08:00
|
|
|
int mode_differs = 0;
|
2006-08-14 10:19:34 +08:00
|
|
|
int i, show_hunks;
|
2006-04-04 09:53:15 +08:00
|
|
|
mmfile_t result_file;
|
2011-05-24 04:27:34 +08:00
|
|
|
struct userdiff_driver *userdiff;
|
2011-05-24 04:31:05 +08:00
|
|
|
struct userdiff_driver *textconv = NULL;
|
2011-05-24 04:27:34 +08:00
|
|
|
int is_binary;
|
2013-02-08 04:15:28 +08:00
|
|
|
const char *line_prefix = diff_line_prefix(opt);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2006-05-14 04:23:48 +08:00
|
|
|
context = opt->context;
|
2011-05-24 04:27:34 +08:00
|
|
|
userdiff = userdiff_find_by_path(elem->path);
|
|
|
|
if (!userdiff)
|
|
|
|
userdiff = userdiff_find_by_name("default");
|
2011-05-24 04:31:05 +08:00
|
|
|
if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV))
|
|
|
|
textconv = userdiff_get_textconv(userdiff);
|
2008-08-19 11:08:09 +08:00
|
|
|
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
/* Read the result of merge first */
|
2006-04-04 09:53:15 +08:00
|
|
|
if (!working_tree_file)
|
2011-05-24 04:31:05 +08:00
|
|
|
result = grab_blob(elem->sha1, elem->mode, &result_size,
|
|
|
|
textconv, elem->path);
|
2006-01-28 16:03:38 +08:00
|
|
|
else {
|
2006-02-07 04:30:00 +08:00
|
|
|
/* Used by diff-tree to read from the working tree */
|
2006-01-28 16:03:38 +08:00
|
|
|
struct stat st;
|
2007-02-26 14:24:47 +08:00
|
|
|
int fd = -1;
|
|
|
|
|
|
|
|
if (lstat(elem->path, &st) < 0)
|
|
|
|
goto deleted_file;
|
|
|
|
|
|
|
|
if (S_ISLNK(st.st_mode)) {
|
2008-12-18 04:37:58 +08:00
|
|
|
struct strbuf buf = STRBUF_INIT;
|
|
|
|
|
|
|
|
if (strbuf_readlink(&buf, elem->path, st.st_size) < 0) {
|
2007-02-26 14:24:47 +08:00
|
|
|
error("readlink(%s): %s", elem->path,
|
|
|
|
strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
2008-12-18 04:37:58 +08:00
|
|
|
result_size = buf.len;
|
|
|
|
result = strbuf_detach(&buf, NULL);
|
2007-02-26 14:24:47 +08:00
|
|
|
elem->mode = canon_mode(st.st_mode);
|
2009-04-30 03:49:52 +08:00
|
|
|
} else if (S_ISDIR(st.st_mode)) {
|
|
|
|
unsigned char sha1[20];
|
|
|
|
if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0)
|
2011-05-24 04:31:05 +08:00
|
|
|
result = grab_blob(elem->sha1, elem->mode,
|
|
|
|
&result_size, NULL, NULL);
|
2009-04-30 03:49:52 +08:00
|
|
|
else
|
2011-05-24 04:31:05 +08:00
|
|
|
result = grab_blob(sha1, elem->mode,
|
|
|
|
&result_size, NULL, NULL);
|
|
|
|
} else if (textconv) {
|
|
|
|
struct diff_filespec *df = alloc_filespec(elem->path);
|
diff: do not use null sha1 as a sentinel value
The diff code represents paths using the diff_filespec
struct. This struct has a sha1 to represent the sha1 of the
content at that path, as well as a sha1_valid member which
indicates whether its sha1 field is actually useful. If
sha1_valid is not true, then the filespec represents a
working tree file (e.g., for the no-index case, or for when
the index is not up-to-date).
The diff_filespec is only used internally, though. At the
interfaces to the diff subsystem, callers feed the sha1
directly, and we create a diff_filespec from it. It's at
that point that we look at the sha1 and decide whether it is
valid or not; callers may pass the null sha1 as a sentinel
value to indicate that it is not.
We should not typically see the null sha1 coming from any
other source (e.g., in the index itself, or from a tree).
However, a corrupt tree might have a null sha1, which would
cause "diff --patch" to accidentally diff the working tree
version of a file instead of treating it as a blob.
This patch extends the edges of the diff interface to accept
a "sha1_valid" flag whenever we accept a sha1, and to use
that flag when creating a filespec. In some cases, this
means passing the flag through several layers, making the
code change larger than would be desirable.
One alternative would be to simply die() upon seeing
corrupted trees with null sha1s. However, this fix more
directly addresses the problem (while bogus sha1s in a tree
are probably a bad thing, it is really the sentinel
confusion sending us down the wrong code path that is what
makes it devastating). And it means that git is more capable
of examining and debugging these corrupted trees. For
example, you can still "diff --raw" such a tree to find out
when the bogus entry was introduced; you just cannot do a
"--patch" diff (just as you could not with any other
corrupted tree, as we do not have any content to diff).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-07-28 23:03:01 +08:00
|
|
|
fill_filespec(df, null_sha1, 0, st.st_mode);
|
2011-05-24 04:31:05 +08:00
|
|
|
result_size = fill_textconv(textconv, df, &result);
|
|
|
|
free_filespec(df);
|
2009-02-10 04:54:52 +08:00
|
|
|
} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
|
2007-03-07 09:44:37 +08:00
|
|
|
size_t len = xsize_t(st.st_size);
|
2008-05-03 21:27:26 +08:00
|
|
|
ssize_t done;
|
2007-03-04 03:38:00 +08:00
|
|
|
int is_file, i;
|
2006-01-28 16:03:38 +08:00
|
|
|
|
2006-03-30 14:55:43 +08:00
|
|
|
elem->mode = canon_mode(st.st_mode);
|
2007-03-04 03:38:00 +08:00
|
|
|
/* if symlinks don't work, assume symlink if all parents
|
|
|
|
* are symlinks
|
|
|
|
*/
|
|
|
|
is_file = has_symlinks;
|
|
|
|
for (i = 0; !is_file && i < num_parent; i++)
|
|
|
|
is_file = !S_ISLNK(elem->parent[i].mode);
|
|
|
|
if (!is_file)
|
|
|
|
elem->mode = canon_mode(S_IFLNK);
|
|
|
|
|
2006-04-04 09:53:15 +08:00
|
|
|
result_size = len;
|
2006-01-28 16:03:38 +08:00
|
|
|
result = xmalloc(len + 1);
|
2008-05-03 21:27:26 +08:00
|
|
|
|
|
|
|
done = read_in_full(fd, result, len);
|
|
|
|
if (done < 0)
|
2009-06-27 23:58:47 +08:00
|
|
|
die_errno("read error '%s'", elem->path);
|
2008-05-03 21:27:26 +08:00
|
|
|
else if (done < len)
|
|
|
|
die("early EOF '%s'", elem->path);
|
|
|
|
|
2006-01-28 16:03:38 +08:00
|
|
|
result[len] = 0;
|
2008-08-24 03:21:21 +08:00
|
|
|
|
|
|
|
/* If not a fake symlink, apply filters, e.g. autocrlf */
|
|
|
|
if (is_file) {
|
2008-10-10 03:12:12 +08:00
|
|
|
struct strbuf buf = STRBUF_INIT;
|
2008-08-24 03:21:21 +08:00
|
|
|
|
|
|
|
if (convert_to_git(elem->path, result, len, &buf, safe_crlf)) {
|
|
|
|
free(result);
|
|
|
|
result = strbuf_detach(&buf, &len);
|
|
|
|
result_size = len;
|
|
|
|
}
|
|
|
|
}
|
2006-01-28 16:03:38 +08:00
|
|
|
}
|
|
|
|
else {
|
2007-02-26 14:24:47 +08:00
|
|
|
deleted_file:
|
2010-04-15 20:59:37 +08:00
|
|
|
result_deleted = 1;
|
2006-04-04 09:53:15 +08:00
|
|
|
result_size = 0;
|
2006-02-14 15:07:04 +08:00
|
|
|
elem->mode = 0;
|
2006-07-25 15:30:18 +08:00
|
|
|
result = xcalloc(1, 1);
|
2006-01-28 16:03:38 +08:00
|
|
|
}
|
2007-02-26 14:24:47 +08:00
|
|
|
|
2006-01-28 16:03:38 +08:00
|
|
|
if (0 <= fd)
|
|
|
|
close(fd);
|
|
|
|
}
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2011-05-24 04:16:59 +08:00
|
|
|
for (i = 0; i < num_parent; i++) {
|
|
|
|
if (elem->parent[i].mode != elem->mode) {
|
|
|
|
mode_differs = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-24 04:31:05 +08:00
|
|
|
if (textconv)
|
|
|
|
is_binary = 0;
|
|
|
|
else if (userdiff->binary != -1)
|
2011-05-24 04:27:34 +08:00
|
|
|
is_binary = userdiff->binary;
|
|
|
|
else {
|
|
|
|
is_binary = buffer_is_binary(result, result_size);
|
|
|
|
for (i = 0; !is_binary && i < num_parent; i++) {
|
|
|
|
char *buf;
|
|
|
|
unsigned long size;
|
|
|
|
buf = grab_blob(elem->parent[i].sha1,
|
|
|
|
elem->parent[i].mode,
|
2011-05-24 04:31:05 +08:00
|
|
|
&size, NULL, NULL);
|
2011-05-24 04:27:34 +08:00
|
|
|
if (buffer_is_binary(buf, size))
|
|
|
|
is_binary = 1;
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (is_binary) {
|
|
|
|
show_combined_header(elem, num_parent, dense, rev,
|
2013-02-08 04:15:28 +08:00
|
|
|
line_prefix, mode_differs, 0);
|
2011-05-24 04:27:34 +08:00
|
|
|
printf("Binary files differ\n");
|
|
|
|
free(result);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-06-28 16:38:19 +08:00
|
|
|
for (cnt = 0, cp = result; cp < result + result_size; cp++) {
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
if (*cp == '\n')
|
|
|
|
cnt++;
|
|
|
|
}
|
2006-04-04 09:53:15 +08:00
|
|
|
if (result_size && result[result_size-1] != '\n')
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
cnt++; /* incomplete line */
|
|
|
|
|
2006-04-11 18:13:29 +08:00
|
|
|
sline = xcalloc(cnt+2, sizeof(*sline));
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
sline[0].bol = result;
|
2006-06-28 16:38:19 +08:00
|
|
|
for (lno = 0, cp = result; cp < result + result_size; cp++) {
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
if (*cp == '\n') {
|
|
|
|
sline[lno].len = cp - sline[lno].bol;
|
|
|
|
lno++;
|
|
|
|
if (lno < cnt)
|
|
|
|
sline[lno].bol = cp + 1;
|
|
|
|
}
|
|
|
|
}
|
2006-04-04 09:53:15 +08:00
|
|
|
if (result_size && result[result_size-1] != '\n')
|
|
|
|
sline[cnt-1].len = result_size - (sline[cnt-1].bol - result);
|
|
|
|
|
|
|
|
result_file.ptr = result;
|
|
|
|
result_file.size = result_size;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2006-04-11 18:13:29 +08:00
|
|
|
/* Even p_lno[cnt+1] is valid -- that is for the end line number
|
|
|
|
* for deletion hunk at the end.
|
|
|
|
*/
|
|
|
|
sline[0].p_lno = xcalloc((cnt+2) * num_parent, sizeof(unsigned long));
|
|
|
|
for (lno = 0; lno <= cnt; lno++)
|
2006-01-31 14:33:15 +08:00
|
|
|
sline[lno+1].p_lno = sline[lno].p_lno + num_parent;
|
|
|
|
|
2006-02-02 15:29:03 +08:00
|
|
|
for (i = 0; i < num_parent; i++) {
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < i; j++) {
|
2006-08-18 02:54:57 +08:00
|
|
|
if (!hashcmp(elem->parent[i].sha1,
|
|
|
|
elem->parent[j].sha1)) {
|
2006-02-02 15:29:03 +08:00
|
|
|
reuse_combine_diff(sline, cnt, i, j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i <= j)
|
2009-04-30 03:49:52 +08:00
|
|
|
combine_diff(elem->parent[i].sha1,
|
|
|
|
elem->parent[i].mode,
|
|
|
|
&result_file, sline,
|
2011-05-24 04:31:05 +08:00
|
|
|
cnt, i, num_parent, result_deleted,
|
2013-03-15 05:03:14 +08:00
|
|
|
textconv, elem->path, opt->xdl_opts);
|
2006-02-02 15:29:03 +08:00
|
|
|
}
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2006-01-26 06:26:22 +08:00
|
|
|
show_hunks = make_hunks(sline, cnt, num_parent, dense);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2006-02-14 15:07:04 +08:00
|
|
|
if (show_hunks || mode_differs || working_tree_file) {
|
2011-05-24 04:16:41 +08:00
|
|
|
show_combined_header(elem, num_parent, dense, rev,
|
2013-02-08 04:15:28 +08:00
|
|
|
line_prefix, mode_differs, 1);
|
|
|
|
dump_sline(sline, line_prefix, cnt, num_parent,
|
2011-08-18 13:03:12 +08:00
|
|
|
opt->use_color, result_deleted);
|
2006-01-26 06:26:22 +08:00
|
|
|
}
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
free(result);
|
|
|
|
|
2006-06-28 16:38:19 +08:00
|
|
|
for (lno = 0; lno < cnt; lno++) {
|
2013-03-24 01:23:28 +08:00
|
|
|
if (sline[lno].lost) {
|
|
|
|
struct lline *ll = sline[lno].lost;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
while (ll) {
|
|
|
|
struct lline *tmp = ll;
|
|
|
|
ll = ll->next;
|
|
|
|
free(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-02-03 07:17:42 +08:00
|
|
|
free(sline[0].p_lno);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
free(sline);
|
|
|
|
}
|
|
|
|
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct rev_info *rev)
|
diff-tree -c raw output
NOTE! This makes "-c" be the default, which effectively means that merges
are never ignored any more, and "-m" is a no-op. So it changes semantics.
I would also like to make "--cc" the default if you do patches, but didn't
actually do that.
The raw output format is not wonderfully pretty, but it's distinguishable
from a "normal patch" in that a normal patch with just one parent has just
one colon at the beginning, while a multi-parent raw diff has <n> colons
for <n> parents.
So now, in the kernel, when you do
git-diff-tree cce0cac125623f9b68f25dd1350f6d616220a8dd
(to see the manual ARM merge that had a conflict in arch/arm/Kconfig), you
get
cce0cac125623f9b68f25dd1350f6d616220a8dd
::100644 100644 100644 4a63a8e2e45247a11c068c6ed66c6e7aba29ddd9 77eee38762d69d3de95ae45dd9278df9b8225e2c 2f61726d2f4b636f6e66696700dbf71a59dad287 arch/arm/Kconfig
ie you see two colons (two parents), then three modes (parent modes
followed by result mode), then three sha1s (parent sha1s followed by
result sha1).
Which is pretty close to the normal raw diff output.
Cool/stupid exercise:
$ git-whatchanged | grep '^::' | cut -f2- | sort |
uniq -c | sort -n | less -S
will show which files have needed the most file-level merge conflict
resolution. Useful? Probably not. But kind of interesting.
For the kernel, it's
....
10 arch/ia64/Kconfig
11 drivers/scsi/Kconfig
12 drivers/net/Makefile
17 include/linux/libata.h
18 include/linux/pci_ids.h
23 drivers/net/Kconfig
24 drivers/scsi/libata-scsi.c
28 drivers/scsi/libata-core.c
43 MAINTAINERS
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-10 02:30:28 +08:00
|
|
|
{
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
struct diff_options *opt = &rev->diffopt;
|
2013-02-04 05:08:18 +08:00
|
|
|
int line_termination, inter_name_termination, i;
|
2013-02-08 04:15:28 +08:00
|
|
|
const char *line_prefix = diff_line_prefix(opt);
|
diff-tree -c raw output
NOTE! This makes "-c" be the default, which effectively means that merges
are never ignored any more, and "-m" is a no-op. So it changes semantics.
I would also like to make "--cc" the default if you do patches, but didn't
actually do that.
The raw output format is not wonderfully pretty, but it's distinguishable
from a "normal patch" in that a normal patch with just one parent has just
one colon at the beginning, while a multi-parent raw diff has <n> colons
for <n> parents.
So now, in the kernel, when you do
git-diff-tree cce0cac125623f9b68f25dd1350f6d616220a8dd
(to see the manual ARM merge that had a conflict in arch/arm/Kconfig), you
get
cce0cac125623f9b68f25dd1350f6d616220a8dd
::100644 100644 100644 4a63a8e2e45247a11c068c6ed66c6e7aba29ddd9 77eee38762d69d3de95ae45dd9278df9b8225e2c 2f61726d2f4b636f6e66696700dbf71a59dad287 arch/arm/Kconfig
ie you see two colons (two parents), then three modes (parent modes
followed by result mode), then three sha1s (parent sha1s followed by
result sha1).
Which is pretty close to the normal raw diff output.
Cool/stupid exercise:
$ git-whatchanged | grep '^::' | cut -f2- | sort |
uniq -c | sort -n | less -S
will show which files have needed the most file-level merge conflict
resolution. Useful? Probably not. But kind of interesting.
For the kernel, it's
....
10 arch/ia64/Kconfig
11 drivers/scsi/Kconfig
12 drivers/net/Makefile
17 include/linux/libata.h
18 include/linux/pci_ids.h
23 drivers/net/Kconfig
24 drivers/scsi/libata-scsi.c
28 drivers/scsi/libata-core.c
43 MAINTAINERS
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-10 02:30:28 +08:00
|
|
|
|
|
|
|
line_termination = opt->line_termination;
|
|
|
|
inter_name_termination = '\t';
|
|
|
|
if (!line_termination)
|
|
|
|
inter_name_termination = 0;
|
|
|
|
|
2006-10-26 17:05:59 +08:00
|
|
|
if (rev->loginfo && !rev->no_commit_id)
|
2008-04-29 16:32:59 +08:00
|
|
|
show_log(rev);
|
diff-tree -c raw output
NOTE! This makes "-c" be the default, which effectively means that merges
are never ignored any more, and "-m" is a no-op. So it changes semantics.
I would also like to make "--cc" the default if you do patches, but didn't
actually do that.
The raw output format is not wonderfully pretty, but it's distinguishable
from a "normal patch" in that a normal patch with just one parent has just
one colon at the beginning, while a multi-parent raw diff has <n> colons
for <n> parents.
So now, in the kernel, when you do
git-diff-tree cce0cac125623f9b68f25dd1350f6d616220a8dd
(to see the manual ARM merge that had a conflict in arch/arm/Kconfig), you
get
cce0cac125623f9b68f25dd1350f6d616220a8dd
::100644 100644 100644 4a63a8e2e45247a11c068c6ed66c6e7aba29ddd9 77eee38762d69d3de95ae45dd9278df9b8225e2c 2f61726d2f4b636f6e66696700dbf71a59dad287 arch/arm/Kconfig
ie you see two colons (two parents), then three modes (parent modes
followed by result mode), then three sha1s (parent sha1s followed by
result sha1).
Which is pretty close to the normal raw diff output.
Cool/stupid exercise:
$ git-whatchanged | grep '^::' | cut -f2- | sort |
uniq -c | sort -n | less -S
will show which files have needed the most file-level merge conflict
resolution. Useful? Probably not. But kind of interesting.
For the kernel, it's
....
10 arch/ia64/Kconfig
11 drivers/scsi/Kconfig
12 drivers/net/Makefile
17 include/linux/libata.h
18 include/linux/pci_ids.h
23 drivers/net/Kconfig
24 drivers/scsi/libata-scsi.c
28 drivers/scsi/libata-core.c
43 MAINTAINERS
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-10 02:30:28 +08:00
|
|
|
|
2013-02-15 02:29:59 +08:00
|
|
|
|
2006-06-25 01:21:53 +08:00
|
|
|
if (opt->output_format & DIFF_FORMAT_RAW) {
|
2013-02-08 04:15:28 +08:00
|
|
|
printf("%s", line_prefix);
|
2013-02-15 02:29:59 +08:00
|
|
|
|
2013-02-04 05:08:18 +08:00
|
|
|
/* As many colons as there are parents */
|
|
|
|
for (i = 0; i < num_parent; i++)
|
|
|
|
putchar(':');
|
2006-02-10 07:23:06 +08:00
|
|
|
|
|
|
|
/* Show the modes */
|
2013-02-04 05:08:18 +08:00
|
|
|
for (i = 0; i < num_parent; i++)
|
|
|
|
printf("%06o ", p->parent[i].mode);
|
|
|
|
printf("%06o", p->mode);
|
2006-02-10 07:23:06 +08:00
|
|
|
|
|
|
|
/* Show sha1's */
|
|
|
|
for (i = 0; i < num_parent; i++)
|
|
|
|
printf(" %s", diff_unique_abbrev(p->parent[i].sha1,
|
|
|
|
opt->abbrev));
|
|
|
|
printf(" %s ", diff_unique_abbrev(p->sha1, opt->abbrev));
|
|
|
|
}
|
|
|
|
|
2006-06-25 01:21:53 +08:00
|
|
|
if (opt->output_format & (DIFF_FORMAT_RAW | DIFF_FORMAT_NAME_STATUS)) {
|
2006-02-10 18:30:52 +08:00
|
|
|
for (i = 0; i < num_parent; i++)
|
|
|
|
putchar(p->parent[i].status);
|
|
|
|
putchar(inter_name_termination);
|
|
|
|
}
|
2006-02-10 07:23:06 +08:00
|
|
|
|
Full rework of quote_c_style and write_name_quoted.
* quote_c_style works on a strbuf instead of a wild buffer.
* quote_c_style is now clever enough to not add double quotes if not needed.
* write_name_quoted inherits those advantages, but also take a different
set of arguments. Now instead of asking for quotes or not, you pass a
"terminator". If it's \0 then we assume you don't want to escape, else C
escaping is performed. In any case, the terminator is also appended to the
stream. It also no longer takes the prefix/prefix_len arguments, as it's
seldomly used, and makes some optimizations harder.
* write_name_quotedpfx is created to work like write_name_quoted and take
the prefix/prefix_len arguments.
Thanks to those API changes, diff.c has somehow lost weight, thanks to the
removal of functions that were wrappers around the old write_name_quoted
trying to give it a semantics like the new one, but performing a lot of
allocations for this goal. Now we always write directly to the stream, no
intermediate allocation is performed.
As a side effect of the refactor in builtin-apply.c, the length of the bar
graphs in diffstats are not affected anymore by the fact that the path was
clipped.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
2007-09-20 06:42:15 +08:00
|
|
|
write_name_quoted(p->path, stdout, line_termination);
|
2006-02-10 07:23:06 +08:00
|
|
|
}
|
|
|
|
|
2011-08-05 02:39:10 +08:00
|
|
|
/*
|
|
|
|
* The result (p->elem) is from the working tree and their
|
|
|
|
* parents are typically from multiple stages during a merge
|
|
|
|
* (i.e. diff-files) or the state in HEAD and in the index
|
|
|
|
* (i.e. diff-index).
|
|
|
|
*/
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
void show_combined_diff(struct combine_diff_path *p,
|
2006-02-10 07:23:06 +08:00
|
|
|
int num_parent,
|
|
|
|
int dense,
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
struct rev_info *rev)
|
2006-02-10 07:23:06 +08:00
|
|
|
{
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
struct diff_options *opt = &rev->diffopt;
|
2013-02-08 04:15:28 +08:00
|
|
|
|
2006-06-25 01:21:53 +08:00
|
|
|
if (opt->output_format & (DIFF_FORMAT_RAW |
|
|
|
|
DIFF_FORMAT_NAME |
|
2006-08-14 10:19:34 +08:00
|
|
|
DIFF_FORMAT_NAME_STATUS))
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
show_raw_diff(p, num_parent, rev);
|
2006-08-14 10:19:34 +08:00
|
|
|
else if (opt->output_format & DIFF_FORMAT_PATCH)
|
2011-08-05 02:39:10 +08:00
|
|
|
show_patch_diff(p, num_parent, dense, 1, rev);
|
diff-tree -c raw output
NOTE! This makes "-c" be the default, which effectively means that merges
are never ignored any more, and "-m" is a no-op. So it changes semantics.
I would also like to make "--cc" the default if you do patches, but didn't
actually do that.
The raw output format is not wonderfully pretty, but it's distinguishable
from a "normal patch" in that a normal patch with just one parent has just
one colon at the beginning, while a multi-parent raw diff has <n> colons
for <n> parents.
So now, in the kernel, when you do
git-diff-tree cce0cac125623f9b68f25dd1350f6d616220a8dd
(to see the manual ARM merge that had a conflict in arch/arm/Kconfig), you
get
cce0cac125623f9b68f25dd1350f6d616220a8dd
::100644 100644 100644 4a63a8e2e45247a11c068c6ed66c6e7aba29ddd9 77eee38762d69d3de95ae45dd9278df9b8225e2c 2f61726d2f4b636f6e66696700dbf71a59dad287 arch/arm/Kconfig
ie you see two colons (two parents), then three modes (parent modes
followed by result mode), then three sha1s (parent sha1s followed by
result sha1).
Which is pretty close to the normal raw diff output.
Cool/stupid exercise:
$ git-whatchanged | grep '^::' | cut -f2- | sort |
uniq -c | sort -n | less -S
will show which files have needed the most file-level merge conflict
resolution. Useful? Probably not. But kind of interesting.
For the kernel, it's
....
10 arch/ia64/Kconfig
11 drivers/scsi/Kconfig
12 drivers/net/Makefile
17 include/linux/libata.h
18 include/linux/pci_ids.h
23 drivers/net/Kconfig
24 drivers/scsi/libata-scsi.c
28 drivers/scsi/libata-core.c
43 MAINTAINERS
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-10 02:30:28 +08:00
|
|
|
}
|
|
|
|
|
2011-08-20 14:32:51 +08:00
|
|
|
static void free_combined_pair(struct diff_filepair *pair)
|
|
|
|
{
|
|
|
|
free(pair->two);
|
|
|
|
free(pair);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A combine_diff_path expresses N parents on the LHS against 1 merge
|
|
|
|
* result. Synthesize a diff_filepair that has N entries on the "one"
|
|
|
|
* side and 1 entry on the "two" side.
|
|
|
|
*
|
|
|
|
* In the future, we might want to add more data to combine_diff_path
|
|
|
|
* so that we can fill fields we are ignoring (most notably, size) here,
|
|
|
|
* but currently nobody uses it, so this should suffice for now.
|
|
|
|
*/
|
|
|
|
static struct diff_filepair *combined_pair(struct combine_diff_path *p,
|
|
|
|
int num_parent)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct diff_filepair *pair;
|
|
|
|
struct diff_filespec *pool;
|
|
|
|
|
|
|
|
pair = xmalloc(sizeof(*pair));
|
|
|
|
pool = xcalloc(num_parent + 1, sizeof(struct diff_filespec));
|
|
|
|
pair->one = pool + 1;
|
|
|
|
pair->two = pool;
|
|
|
|
|
|
|
|
for (i = 0; i < num_parent; i++) {
|
|
|
|
pair->one[i].path = p->path;
|
|
|
|
pair->one[i].mode = p->parent[i].mode;
|
|
|
|
hashcpy(pair->one[i].sha1, p->parent[i].sha1);
|
|
|
|
pair->one[i].sha1_valid = !is_null_sha1(p->parent[i].sha1);
|
|
|
|
pair->one[i].has_more_entries = 1;
|
|
|
|
}
|
|
|
|
pair->one[num_parent - 1].has_more_entries = 0;
|
|
|
|
|
|
|
|
pair->two->path = p->path;
|
|
|
|
pair->two->mode = p->mode;
|
|
|
|
hashcpy(pair->two->sha1, p->sha1);
|
|
|
|
pair->two->sha1_valid = !is_null_sha1(p->sha1);
|
|
|
|
return pair;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void handle_combined_callback(struct diff_options *opt,
|
|
|
|
struct combine_diff_path *paths,
|
|
|
|
int num_parent,
|
|
|
|
int num_paths)
|
|
|
|
{
|
|
|
|
struct combine_diff_path *p;
|
|
|
|
struct diff_queue_struct q;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
q.queue = xcalloc(num_paths, sizeof(struct diff_filepair *));
|
|
|
|
q.alloc = num_paths;
|
|
|
|
q.nr = num_paths;
|
2014-01-21 00:20:41 +08:00
|
|
|
for (i = 0, p = paths; p; p = p->next)
|
2011-08-20 14:32:51 +08:00
|
|
|
q.queue[i++] = combined_pair(p, num_parent);
|
|
|
|
opt->format_callback(&q, opt, opt->format_callback_data);
|
|
|
|
for (i = 0; i < num_paths; i++)
|
|
|
|
free_combined_pair(q.queue[i]);
|
|
|
|
free(q.queue);
|
|
|
|
}
|
|
|
|
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
static const char *path_path(void *obj)
|
|
|
|
{
|
|
|
|
struct combine_diff_path *path = (struct combine_diff_path *)obj;
|
|
|
|
|
|
|
|
return path->path;
|
|
|
|
}
|
|
|
|
|
2014-02-03 20:47:20 +08:00
|
|
|
|
|
|
|
/* find set of paths that every parent touches */
|
combine-diff: speed it up, by using multiparent diff tree-walker directly
As was recently shown in "combine-diff: optimize
combine_diff_path sets intersection", combine-diff runs very slowly. In
that commit we optimized paths sets intersection, but that accounted
only for ~ 25% of the slowness, and as my tracing showed, for linux.git
v3.10..v3.11, for merges a lot of time is spent computing
diff(commit,commit^2) just to only then intersect that huge diff to
almost small set of files from diff(commit,commit^1).
In previous commit, we described the problem in more details, and
reworked the diff tree-walker to be general one - i.e. to work in
multiple parent case too. Now is the time to take advantage of it for
finding paths for combine diff.
The implementation is straightforward - if we know, we can get generated
diff paths directly, and at present that means no diff filtering or
rename/copy detection was requested(*), we can call multiparent tree-walker
directly and get ready paths.
(*) because e.g. at present, all diffcore transformations work on
diff_filepair queues, but in the future, that limitation can be
lifted, if filters would operate directly on combine_diff_paths.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") and with `-c --merges` ("git log -c --merges")
before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c log -c --merges
before 1.9s 16.4s 15.2s
after 1.9s 2.4s 1.1s
The result stayed the same.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-25 00:21:51 +08:00
|
|
|
static struct combine_diff_path *find_paths_generic(const unsigned char *sha1,
|
2014-02-03 20:47:20 +08:00
|
|
|
const struct sha1_array *parents, struct diff_options *opt)
|
|
|
|
{
|
|
|
|
struct combine_diff_path *paths = NULL;
|
|
|
|
int i, num_parent = parents->nr;
|
|
|
|
|
|
|
|
int output_format = opt->output_format;
|
|
|
|
const char *orderfile = opt->orderfile;
|
|
|
|
|
|
|
|
opt->output_format = DIFF_FORMAT_NO_OUTPUT;
|
|
|
|
/* tell diff_tree to emit paths in sorted (=tree) order */
|
|
|
|
opt->orderfile = NULL;
|
|
|
|
|
combine-diff: speed it up, by using multiparent diff tree-walker directly
As was recently shown in "combine-diff: optimize
combine_diff_path sets intersection", combine-diff runs very slowly. In
that commit we optimized paths sets intersection, but that accounted
only for ~ 25% of the slowness, and as my tracing showed, for linux.git
v3.10..v3.11, for merges a lot of time is spent computing
diff(commit,commit^2) just to only then intersect that huge diff to
almost small set of files from diff(commit,commit^1).
In previous commit, we described the problem in more details, and
reworked the diff tree-walker to be general one - i.e. to work in
multiple parent case too. Now is the time to take advantage of it for
finding paths for combine diff.
The implementation is straightforward - if we know, we can get generated
diff paths directly, and at present that means no diff filtering or
rename/copy detection was requested(*), we can call multiparent tree-walker
directly and get ready paths.
(*) because e.g. at present, all diffcore transformations work on
diff_filepair queues, but in the future, that limitation can be
lifted, if filters would operate directly on combine_diff_paths.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") and with `-c --merges` ("git log -c --merges")
before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c log -c --merges
before 1.9s 16.4s 15.2s
after 1.9s 2.4s 1.1s
The result stayed the same.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-25 00:21:51 +08:00
|
|
|
/* D(A,P1...Pn) = D(A,P1) ^ ... ^ D(A,Pn) (wrt paths) */
|
2014-02-03 20:47:20 +08:00
|
|
|
for (i = 0; i < num_parent; i++) {
|
|
|
|
/*
|
|
|
|
* show stat against the first parent even when doing
|
|
|
|
* combined diff.
|
|
|
|
*/
|
|
|
|
int stat_opt = (output_format &
|
|
|
|
(DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT));
|
|
|
|
if (i == 0 && stat_opt)
|
|
|
|
opt->output_format = stat_opt;
|
|
|
|
else
|
|
|
|
opt->output_format = DIFF_FORMAT_NO_OUTPUT;
|
|
|
|
diff_tree_sha1(parents->sha1[i], sha1, "", opt);
|
|
|
|
diffcore_std(opt);
|
|
|
|
paths = intersect_paths(paths, i, num_parent);
|
|
|
|
|
|
|
|
/* if showing diff, show it in requested order */
|
|
|
|
if (opt->output_format != DIFF_FORMAT_NO_OUTPUT &&
|
|
|
|
orderfile) {
|
|
|
|
diffcore_order(orderfile);
|
|
|
|
}
|
|
|
|
|
|
|
|
diff_flush(opt);
|
|
|
|
}
|
|
|
|
|
|
|
|
opt->output_format = output_format;
|
|
|
|
opt->orderfile = orderfile;
|
|
|
|
return paths;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
combine-diff: speed it up, by using multiparent diff tree-walker directly
As was recently shown in "combine-diff: optimize
combine_diff_path sets intersection", combine-diff runs very slowly. In
that commit we optimized paths sets intersection, but that accounted
only for ~ 25% of the slowness, and as my tracing showed, for linux.git
v3.10..v3.11, for merges a lot of time is spent computing
diff(commit,commit^2) just to only then intersect that huge diff to
almost small set of files from diff(commit,commit^1).
In previous commit, we described the problem in more details, and
reworked the diff tree-walker to be general one - i.e. to work in
multiple parent case too. Now is the time to take advantage of it for
finding paths for combine diff.
The implementation is straightforward - if we know, we can get generated
diff paths directly, and at present that means no diff filtering or
rename/copy detection was requested(*), we can call multiparent tree-walker
directly and get ready paths.
(*) because e.g. at present, all diffcore transformations work on
diff_filepair queues, but in the future, that limitation can be
lifted, if filters would operate directly on combine_diff_paths.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") and with `-c --merges` ("git log -c --merges")
before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c log -c --merges
before 1.9s 16.4s 15.2s
after 1.9s 2.4s 1.1s
The result stayed the same.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-25 00:21:51 +08:00
|
|
|
/*
|
|
|
|
* find set of paths that everybody touches, assuming diff is run without
|
|
|
|
* rename/copy detection, etc, comparing all trees simultaneously (= faster).
|
|
|
|
*/
|
|
|
|
static struct combine_diff_path *find_paths_multitree(
|
|
|
|
const unsigned char *sha1, const struct sha1_array *parents,
|
|
|
|
struct diff_options *opt)
|
|
|
|
{
|
|
|
|
int i, nparent = parents->nr;
|
|
|
|
const unsigned char **parents_sha1;
|
|
|
|
struct combine_diff_path paths_head;
|
|
|
|
struct strbuf base;
|
|
|
|
|
|
|
|
parents_sha1 = xmalloc(nparent * sizeof(parents_sha1[0]));
|
|
|
|
for (i = 0; i < nparent; i++)
|
|
|
|
parents_sha1[i] = parents->sha1[i];
|
|
|
|
|
|
|
|
/* fake list head, so worker can assume it is non-NULL */
|
|
|
|
paths_head.next = NULL;
|
|
|
|
|
|
|
|
strbuf_init(&base, PATH_MAX);
|
|
|
|
diff_tree_paths(&paths_head, sha1, parents_sha1, nparent, &base, opt);
|
|
|
|
|
|
|
|
strbuf_release(&base);
|
|
|
|
free(parents_sha1);
|
|
|
|
return paths_head.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-29 16:24:49 +08:00
|
|
|
void diff_tree_combined(const unsigned char *sha1,
|
2011-12-17 18:15:48 +08:00
|
|
|
const struct sha1_array *parents,
|
2006-04-29 16:24:49 +08:00
|
|
|
int dense,
|
|
|
|
struct rev_info *rev)
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
{
|
Log message printout cleanups
On Sun, 16 Apr 2006, Junio C Hamano wrote:
>
> In the mid-term, I am hoping we can drop the generate_header()
> callchain _and_ the custom code that formats commit log in-core,
> found in cmd_log_wc().
Ok, this was nastier than expected, just because the dependencies between
the different log-printing stuff were absolutely _everywhere_, but here's
a patch that does exactly that.
The patch is not very easy to read, and the "--patch-with-stat" thing is
still broken (it does not call the "show_log()" thing properly for
merges). That's not a new bug. In the new world order it _should_ do
something like
if (rev->logopt)
show_log(rev, rev->logopt, "---\n");
but it doesn't. I haven't looked at the --with-stat logic, so I left it
alone.
That said, this patch removes more lines than it adds, and in particular,
the "cmd_log_wc()" loop is now a very clean:
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
free(commit->buffer);
commit->buffer = NULL;
}
so it doesn't get much prettier than this. All the complexity is entirely
hidden in log-tree.c, and any code that needs to flush the log literally
just needs to do the "if (rev->logopt) show_log(...)" incantation.
I had to make the combined_diff() logic take a "struct rev_info" instead
of just a "struct diff_options", but that part is pretty clean.
This does change "git whatchanged" from using "diff-tree" as the commit
descriptor to "commit", and I changed one of the tests to reflect that new
reality. Otherwise everything still passes, and my other tests look fine
too.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-04-18 02:59:32 +08:00
|
|
|
struct diff_options *opt = &rev->diffopt;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
struct diff_options diffopts;
|
2014-02-03 20:47:20 +08:00
|
|
|
struct combine_diff_path *p, *paths;
|
2011-12-17 18:15:48 +08:00
|
|
|
int i, num_paths, needsep, show_log_first, num_parent = parents->nr;
|
combine-diff: speed it up, by using multiparent diff tree-walker directly
As was recently shown in "combine-diff: optimize
combine_diff_path sets intersection", combine-diff runs very slowly. In
that commit we optimized paths sets intersection, but that accounted
only for ~ 25% of the slowness, and as my tracing showed, for linux.git
v3.10..v3.11, for merges a lot of time is spent computing
diff(commit,commit^2) just to only then intersect that huge diff to
almost small set of files from diff(commit,commit^1).
In previous commit, we described the problem in more details, and
reworked the diff tree-walker to be general one - i.e. to work in
multiple parent case too. Now is the time to take advantage of it for
finding paths for combine diff.
The implementation is straightforward - if we know, we can get generated
diff paths directly, and at present that means no diff filtering or
rename/copy detection was requested(*), we can call multiparent tree-walker
directly and get ready paths.
(*) because e.g. at present, all diffcore transformations work on
diff_filepair queues, but in the future, that limitation can be
lifted, if filters would operate directly on combine_diff_paths.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") and with `-c --merges` ("git log -c --merges")
before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c log -c --merges
before 1.9s 16.4s 15.2s
after 1.9s 2.4s 1.1s
The result stayed the same.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-25 00:21:51 +08:00
|
|
|
int need_generic_pathscan;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2014-02-03 20:47:19 +08:00
|
|
|
/* nothing to do, if no parents */
|
|
|
|
if (!num_parent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
show_log_first = !!rev->loginfo && !rev->no_commit_id;
|
|
|
|
needsep = 0;
|
|
|
|
if (show_log_first) {
|
|
|
|
show_log(rev);
|
|
|
|
|
2014-06-07 02:35:01 +08:00
|
|
|
if (rev->verbose_header && opt->output_format &&
|
2014-07-30 01:56:48 +08:00
|
|
|
opt->output_format != DIFF_FORMAT_NO_OUTPUT &&
|
|
|
|
!commit_format_is_empty(rev->commit_format))
|
2014-02-03 20:47:19 +08:00
|
|
|
printf("%s%c", diff_line_prefix(opt),
|
|
|
|
opt->line_termination);
|
|
|
|
}
|
|
|
|
|
2006-02-10 06:35:19 +08:00
|
|
|
diffopts = *opt;
|
2013-07-14 16:35:58 +08:00
|
|
|
copy_pathspec(&diffopts.pathspec, &opt->pathspec);
|
2007-11-11 03:05:14 +08:00
|
|
|
DIFF_OPT_SET(&diffopts, RECURSIVE);
|
|
|
|
DIFF_OPT_CLR(&diffopts, ALLOW_EXTERNAL);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2014-02-03 20:47:20 +08:00
|
|
|
/* find set of paths that everybody touches
|
|
|
|
*
|
combine-diff: speed it up, by using multiparent diff tree-walker directly
As was recently shown in "combine-diff: optimize
combine_diff_path sets intersection", combine-diff runs very slowly. In
that commit we optimized paths sets intersection, but that accounted
only for ~ 25% of the slowness, and as my tracing showed, for linux.git
v3.10..v3.11, for merges a lot of time is spent computing
diff(commit,commit^2) just to only then intersect that huge diff to
almost small set of files from diff(commit,commit^1).
In previous commit, we described the problem in more details, and
reworked the diff tree-walker to be general one - i.e. to work in
multiple parent case too. Now is the time to take advantage of it for
finding paths for combine diff.
The implementation is straightforward - if we know, we can get generated
diff paths directly, and at present that means no diff filtering or
rename/copy detection was requested(*), we can call multiparent tree-walker
directly and get ready paths.
(*) because e.g. at present, all diffcore transformations work on
diff_filepair queues, but in the future, that limitation can be
lifted, if filters would operate directly on combine_diff_paths.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") and with `-c --merges` ("git log -c --merges")
before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c log -c --merges
before 1.9s 16.4s 15.2s
after 1.9s 2.4s 1.1s
The result stayed the same.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-25 00:21:51 +08:00
|
|
|
* NOTE
|
|
|
|
*
|
|
|
|
* Diffcore transformations are bound to diff_filespec and logic
|
|
|
|
* comparing two entries - i.e. they do not apply directly to combine
|
|
|
|
* diff.
|
|
|
|
*
|
|
|
|
* If some of such transformations is requested - we launch generic
|
|
|
|
* path scanning, which works significantly slower compared to
|
|
|
|
* simultaneous all-trees-in-one-go scan in find_paths_multitree().
|
|
|
|
*
|
|
|
|
* TODO some of the filters could be ported to work on
|
|
|
|
* combine_diff_paths - i.e. all functionality that skips paths, so in
|
|
|
|
* theory, we could end up having only multitree path scanning.
|
|
|
|
*
|
|
|
|
* NOTE please keep this semantically in sync with diffcore_std()
|
2014-02-03 20:47:20 +08:00
|
|
|
*/
|
combine-diff: speed it up, by using multiparent diff tree-walker directly
As was recently shown in "combine-diff: optimize
combine_diff_path sets intersection", combine-diff runs very slowly. In
that commit we optimized paths sets intersection, but that accounted
only for ~ 25% of the slowness, and as my tracing showed, for linux.git
v3.10..v3.11, for merges a lot of time is spent computing
diff(commit,commit^2) just to only then intersect that huge diff to
almost small set of files from diff(commit,commit^1).
In previous commit, we described the problem in more details, and
reworked the diff tree-walker to be general one - i.e. to work in
multiple parent case too. Now is the time to take advantage of it for
finding paths for combine diff.
The implementation is straightforward - if we know, we can get generated
diff paths directly, and at present that means no diff filtering or
rename/copy detection was requested(*), we can call multiparent tree-walker
directly and get ready paths.
(*) because e.g. at present, all diffcore transformations work on
diff_filepair queues, but in the future, that limitation can be
lifted, if filters would operate directly on combine_diff_paths.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") and with `-c --merges` ("git log -c --merges")
before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c log -c --merges
before 1.9s 16.4s 15.2s
after 1.9s 2.4s 1.1s
The result stayed the same.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-02-25 00:21:51 +08:00
|
|
|
need_generic_pathscan = opt->skip_stat_unmatch ||
|
|
|
|
DIFF_OPT_TST(opt, FOLLOW_RENAMES) ||
|
|
|
|
opt->break_opt != -1 ||
|
|
|
|
opt->detect_rename ||
|
|
|
|
opt->pickaxe ||
|
|
|
|
opt->filter;
|
|
|
|
|
|
|
|
|
|
|
|
if (need_generic_pathscan) {
|
|
|
|
/*
|
|
|
|
* NOTE generic case also handles --stat, as it computes
|
|
|
|
* diff(sha1,parent_i) for all i to do the job, specifically
|
|
|
|
* for parent0.
|
|
|
|
*/
|
|
|
|
paths = find_paths_generic(sha1, parents, &diffopts);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int stat_opt;
|
|
|
|
paths = find_paths_multitree(sha1, parents, &diffopts);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* show stat against the first parent even
|
|
|
|
* when doing combined diff.
|
|
|
|
*/
|
|
|
|
stat_opt = (opt->output_format &
|
|
|
|
(DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT));
|
|
|
|
if (stat_opt) {
|
|
|
|
diffopts.output_format = stat_opt;
|
|
|
|
|
|
|
|
diff_tree_sha1(parents->sha1[0], sha1, "", &diffopts);
|
|
|
|
diffcore_std(&diffopts);
|
|
|
|
if (opt->orderfile)
|
|
|
|
diffcore_order(opt->orderfile);
|
|
|
|
diff_flush(&diffopts);
|
|
|
|
}
|
|
|
|
}
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
|
2014-01-21 00:20:41 +08:00
|
|
|
/* find out number of surviving paths */
|
|
|
|
for (num_paths = 0, p = paths; p; p = p->next)
|
|
|
|
num_paths++;
|
combine-diff: optimize combine_diff_path sets intersection
When generating combined diff, for each commit, we intersect diff
paths from diff(parent_0,commit) to diff(parent_i,commit) comparing
all paths pairs, i.e. doing it the quadratic way. That is correct,
but could be optimized.
Paths come from trees in sorted (= tree) order, and so does diff_tree()
emits resulting paths in that order too. Now if we look at diffcore
transformations, all of them, except diffcore_order, preserve resulting
path ordering:
- skip_stat_unmatch, grep, pickaxe, filter
-- just skip elements -> order stays preserved
- break -- just breaks diff for a path, adding path
dup after the path -> order stays preserved
- detect rename/copy -- resulting paths are emitted sorted
(verified empirically)
So only diffcore_order changes diff paths ordering.
But diffcore_order meaning affects only presentation - i.e. only how to
show the diff, so we could do all the internal computations without
paths reordering, and order only resultant paths set. This is faster,
since, if we know two paths sets are all ordered, their intersection
could be done in linear time.
This patch does just that.
Timings for `git log --raw --no-abbrev --no-renames` without `-c` ("git log")
and with `-c` ("git log -c") before and after the patch are as follows:
linux.git v3.10..v3.11
log log -c
before 1.9s 20.4s
after 1.9s 16.6s
navy.git (private repo)
log log -c
before 0.83s 15.6s
after 0.83s 2.1s
P.S.
I think linux.git case is sped up not so much as the second one, since
in navy.git, there are more exotic (subtree, etc) merges.
P.P.S.
My tracing showed that the rest of the time (16.6s vs 1.9s) is usually
spent in computing huge diffs from commit to second parent. Will try to
deal with it, if I'll have time.
P.P.P.S.
For combine_diff_path, ->len is not needed anymore - will remove it in
the next noisy cleanup path, to maintain good signal/noise ratio here.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-01-21 00:20:40 +08:00
|
|
|
|
|
|
|
/* order paths according to diffcore_order */
|
|
|
|
if (opt->orderfile && num_paths) {
|
|
|
|
struct obj_order *o;
|
|
|
|
|
|
|
|
o = xmalloc(sizeof(*o) * num_paths);
|
|
|
|
for (i = 0, p = paths; p; p = p->next, i++)
|
|
|
|
o[i].obj = p;
|
|
|
|
order_objects(opt->orderfile, path_path, o, num_paths);
|
|
|
|
for (i = 0; i < num_paths - 1; i++) {
|
|
|
|
p = o[i].obj;
|
|
|
|
p->next = o[i+1].obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = o[num_paths-1].obj;
|
|
|
|
p->next = NULL;
|
|
|
|
paths = o[0].obj;
|
|
|
|
free(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-02-06 14:25:00 +08:00
|
|
|
if (num_paths) {
|
2006-06-25 01:21:53 +08:00
|
|
|
if (opt->output_format & (DIFF_FORMAT_RAW |
|
|
|
|
DIFF_FORMAT_NAME |
|
|
|
|
DIFF_FORMAT_NAME_STATUS)) {
|
2014-01-21 00:20:41 +08:00
|
|
|
for (p = paths; p; p = p->next)
|
|
|
|
show_raw_diff(p, num_parent, rev);
|
2006-06-28 06:08:19 +08:00
|
|
|
needsep = 1;
|
2006-04-11 08:36:53 +08:00
|
|
|
}
|
2006-10-12 18:01:00 +08:00
|
|
|
else if (opt->output_format &
|
|
|
|
(DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT))
|
2006-06-28 06:08:19 +08:00
|
|
|
needsep = 1;
|
2011-08-20 14:32:51 +08:00
|
|
|
else if (opt->output_format & DIFF_FORMAT_CALLBACK)
|
|
|
|
handle_combined_callback(opt, paths, num_parent, num_paths);
|
|
|
|
|
2006-06-25 01:21:53 +08:00
|
|
|
if (opt->output_format & DIFF_FORMAT_PATCH) {
|
2006-06-28 06:08:19 +08:00
|
|
|
if (needsep)
|
2013-02-08 04:15:28 +08:00
|
|
|
printf("%s%c", diff_line_prefix(opt),
|
|
|
|
opt->line_termination);
|
2014-01-21 00:20:41 +08:00
|
|
|
for (p = paths; p; p = p->next)
|
|
|
|
show_patch_diff(p, num_parent, dense,
|
|
|
|
0, rev);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clean things up */
|
|
|
|
while (paths) {
|
2006-01-28 16:03:38 +08:00
|
|
|
struct combine_diff_path *tmp = paths;
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
paths = paths->next;
|
|
|
|
free(tmp);
|
|
|
|
}
|
2013-05-28 06:49:57 +08:00
|
|
|
|
2013-07-14 16:35:58 +08:00
|
|
|
free_pathspec(&diffopts.pathspec);
|
diff-tree -c: show a merge commit a bit more sensibly.
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-01-24 17:22:04 +08:00
|
|
|
}
|
2006-04-29 16:24:49 +08:00
|
|
|
|
2011-12-17 18:20:07 +08:00
|
|
|
void diff_tree_combined_merge(const struct commit *commit, int dense,
|
|
|
|
struct rev_info *rev)
|
2006-04-29 16:24:49 +08:00
|
|
|
{
|
log: use true parents for diff even when rewriting
When using pathspec filtering in combination with diff-based log
output, parent simplification happens before the diff is computed.
The diff is therefore against the *simplified* parents.
This works okay, arguably by accident, in the normal case:
simplification reduces to one parent as long as the commit is TREESAME
to it. So the simplified parent of any given commit must have the
same tree contents on the filtered paths as its true (unfiltered)
parent.
However, --full-diff breaks this guarantee, and indeed gives pretty
spectacular results when comparing the output of
git log --graph --stat ...
git log --graph --full-diff --stat ...
(--graph internally kicks in parent simplification, much like
--parents).
To fix it, store a copy of the parent list before simplification (in a
slab) whenever --full-diff is in effect. Then use the stored parents
instead of the simplified ones in the commit display code paths. The
latter do not actually check for --full-diff to avoid duplicated code;
they just grab the original parents if save_parents() has not been
called for this revision walk.
For ordinary commits it should be obvious that this is the right thing
to do.
Merge commits are a bit subtle. Observe that with default
simplification, merge simplification is an all-or-nothing decision:
either the merge is TREESAME to one parent and disappears, or it is
different from all parents and the parent list remains intact.
Redundant parents are not pruned, so the existing code also shows them
as a merge.
So if we do show a merge commit, the parent list just consists of the
rewrite result on each parent. Running, e.g., --cc on this in
--full-diff mode is not very useful: if any commits were skipped, some
hunks will disagree with all sides of the merge (with one side,
because commits were skipped; with the others, because they didn't
have those changes in the first place). This triggers --cc showing
these hunks spuriously.
Therefore I believe that even for merge commits it is better to show
the diffs wrt. the original parents.
Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Helped-by: Junio C Hamano <gitster@pobox.com>
Helped-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Thomas Rast <trast@inf.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2013-08-01 04:13:20 +08:00
|
|
|
struct commit_list *parent = get_saved_parents(rev, commit);
|
2011-12-17 18:15:48 +08:00
|
|
|
struct sha1_array parents = SHA1_ARRAY_INIT;
|
|
|
|
|
|
|
|
while (parent) {
|
|
|
|
sha1_array_append(&parents, parent->item->object.sha1);
|
|
|
|
parent = parent->next;
|
|
|
|
}
|
2011-12-17 18:20:07 +08:00
|
|
|
diff_tree_combined(commit->object.sha1, &parents, dense, rev);
|
2011-12-17 18:15:48 +08:00
|
|
|
sha1_array_clear(&parents);
|
2006-04-29 16:24:49 +08:00
|
|
|
}
|