From af3feefa1d057713c2277cc1543d438e60c65306 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 24 Jan 2006 01:22:04 -0800 Subject: 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 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 --- diff-tree.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'diff-tree.c') diff --git a/diff-tree.c b/diff-tree.c index efa2b9476e..0c689360ee 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -6,6 +6,8 @@ static int show_root_diff = 0; static int no_commit_id = 0; static int verbose_header = 0; static int ignore_merges = 1; +static int show_empty_combined = 0; +static int combine_merges = 0; static int read_stdin = 0; static const char *header = NULL; @@ -79,9 +81,13 @@ static const char *generate_header(const unsigned char *commit_sha1, offset = sprintf(this_header, "%s%s ", header_prefix, diff_unique_abbrev(commit_sha1, abbrev)); - offset += sprintf(this_header + offset, "(from %s)\n", - parent_sha1 ? - diff_unique_abbrev(parent_sha1, abbrev) : "root"); + if (commit_sha1 != parent_sha1) + offset += sprintf(this_header + offset, "(from %s)\n", + parent_sha1 + ? diff_unique_abbrev(parent_sha1, abbrev) + : "root"); + else + offset += sprintf(this_header + offset, "(from parents)\n"); offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset); @@ -108,8 +114,16 @@ static int diff_tree_commit(const unsigned char *commit_sha1) } /* More than one parent? */ - if (ignore_merges && commit->parents && commit->parents->next) - return 0; + if (commit->parents && commit->parents->next) { + if (ignore_merges) + return 0; + else if (combine_merges) { + header = generate_header(sha1, sha1, + commit->buffer); + return diff_tree_combined_merge(sha1, header, + show_empty_combined); + } + } for (parents = commit->parents; parents; parents = parents->next) { struct commit *parent = parents->item; @@ -154,7 +168,7 @@ static int diff_tree_stdin(char *line) } static const char diff_tree_usage[] = -"git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] [-r] [--root] " +"git-diff-tree [--stdin] [-m] [-c] [-s] [-v] [--pretty] [-t] [-r] [--root] " "[] [] [...]\n" " -r diff recursively\n" " --root include the initial commit as diff against /dev/null\n" @@ -217,6 +231,10 @@ int main(int argc, const char **argv) ignore_merges = 0; continue; } + if (!strcmp(arg, "-c")) { + combine_merges = 1; + continue; + } if (!strcmp(arg, "-v")) { verbose_header = 1; header_prefix = "diff-tree "; @@ -245,6 +263,12 @@ int main(int argc, const char **argv) if (diff_options.output_format == DIFF_FORMAT_PATCH) diff_options.recursive = 1; + if (combine_merges) { + diff_options.output_format = DIFF_FORMAT_PATCH; + show_empty_combined = !ignore_merges; + ignore_merges = 0; + } + diff_tree_setup_paths(get_pathspec(prefix, argv)); diff_setup_done(&diff_options); -- cgit v1.2.3 From d8f4790e6fe7a9d94468ea83d1370643604d43e5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 24 Jan 2006 01:22:04 -0800 Subject: diff-tree --cc: denser combined diff output for a merge commit. Building on the previous '-c' (combined) option, '--cc' option squelches the output further by omitting hunks that consist of difference with solely one parent. Signed-off-by: Junio C Hamano --- diff-tree.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'diff-tree.c') diff --git a/diff-tree.c b/diff-tree.c index 0c689360ee..99c580cf75 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -8,6 +8,7 @@ static int verbose_header = 0; static int ignore_merges = 1; static int show_empty_combined = 0; static int combine_merges = 0; +static int dense_combined_merges = 0; static int read_stdin = 0; static const char *header = NULL; @@ -121,7 +122,8 @@ static int diff_tree_commit(const unsigned char *commit_sha1) header = generate_header(sha1, sha1, commit->buffer); return diff_tree_combined_merge(sha1, header, - show_empty_combined); + show_empty_combined, + dense_combined_merges); } } @@ -168,7 +170,7 @@ static int diff_tree_stdin(char *line) } static const char diff_tree_usage[] = -"git-diff-tree [--stdin] [-m] [-c] [-s] [-v] [--pretty] [-t] [-r] [--root] " +"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] " "[] [] [...]\n" " -r diff recursively\n" " --root include the initial commit as diff against /dev/null\n" @@ -235,6 +237,10 @@ int main(int argc, const char **argv) combine_merges = 1; continue; } + if (!strcmp(arg, "--cc")) { + dense_combined_merges = combine_merges = 1; + continue; + } if (!strcmp(arg, "-v")) { verbose_header = 1; header_prefix = "diff-tree "; -- cgit v1.2.3 From b2d4c56f2f370481c80e478ac323ebb13eece807 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 25 Jan 2006 02:37:40 -0800 Subject: diff-tree: abbreviate merge parent object names with --abbrev --pretty. When --abbrev is in effect, abbreviate the merge parent names in prettyprinted output. Signed-off-by: Junio C Hamano --- diff-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'diff-tree.c') diff --git a/diff-tree.c b/diff-tree.c index efa2b9476e..efa17d14a4 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -84,7 +84,7 @@ static const char *generate_header(const unsigned char *commit_sha1, diff_unique_abbrev(parent_sha1, abbrev) : "root"); offset += pretty_print_commit(commit_format, msg, len, this_header + offset, - sizeof(this_header) - offset); + sizeof(this_header) - offset, abbrev); return this_header; } -- cgit v1.2.3 From 3815f423ae39bf774de3c268c6d3e3b72128a4e5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 27 Jan 2006 01:54:59 -0800 Subject: pretty_print_commit(): pass commit object instead of commit->buffer. Signed-off-by: Junio C Hamano --- diff-tree.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'diff-tree.c') diff --git a/diff-tree.c b/diff-tree.c index efa17d14a4..44bc2381c9 100644 --- a/diff-tree.c +++ b/diff-tree.c @@ -64,12 +64,13 @@ static int diff_root_tree(const unsigned char *new, const char *base) static const char *generate_header(const unsigned char *commit_sha1, const unsigned char *parent_sha1, - const char *msg) + const struct commit *commit) { static char this_header[16384]; int offset; unsigned long len; int abbrev = diff_options.abbrev; + const char *msg = commit->buffer; if (!verbose_header) return sha1_to_hex(commit_sha1); @@ -82,7 +83,7 @@ static const char *generate_header(const unsigned char *commit_sha1, offset += sprintf(this_header + offset, "(from %s)\n", parent_sha1 ? diff_unique_abbrev(parent_sha1, abbrev) : "root"); - offset += pretty_print_commit(commit_format, msg, len, + offset += pretty_print_commit(commit_format, commit, len, this_header + offset, sizeof(this_header) - offset, abbrev); return this_header; @@ -103,7 +104,7 @@ static int diff_tree_commit(const unsigned char *commit_sha1) /* Root commit? */ if (show_root_diff && !commit->parents) { - header = generate_header(sha1, NULL, commit->buffer); + header = generate_header(sha1, NULL, commit); diff_root_tree(commit_sha1, ""); } @@ -113,9 +114,7 @@ static int diff_tree_commit(const unsigned char *commit_sha1) for (parents = commit->parents; parents; parents = parents->next) { struct commit *parent = parents->item; - header = generate_header(sha1, - parent->object.sha1, - commit->buffer); + header = generate_header(sha1, parent->object.sha1, commit); diff_tree_sha1_top(parent->object.sha1, commit_sha1, ""); if (!header && verbose_header) { header_prefix = "\ndiff-tree "; -- cgit v1.2.3