From 0f3a290b89b89bb5375cf5019b067e4a99f02620 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 27 Oct 2008 12:51:59 -0700 Subject: Add a 'source' decorator for commits We already support decorating commits by tags or branches that point to them, but especially when we are looking at multiple branches together, we sometimes want to see _how_ we reached a particular commit. We can abuse the '->util' field in the commit to keep track of that as we walk the commit lists, and get a reasonably useful view into which branch or tag first reaches that commit. Of course, if the commit is reachable through multiple sources (which is common), our particular choice of "first" reachable is entirely random and depends on the particular path we happened to follow. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano diff --git a/builtin-log.c b/builtin-log.c index a0944f7..176cbce 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -56,6 +56,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, if (!strcmp(arg, "--decorate")) { load_ref_decorations(); decorate = 1; + } else if (!strcmp(arg, "--source")) { + rev->show_source = 1; } else die("unrecognized argument: %s", arg); } diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 06cdeb7..857742a 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -100,7 +100,7 @@ static void show_commit(struct commit *commit) children = children->next; } } - show_decorations(commit); + show_decorations(&revs, commit); if (revs.commit_format == CMIT_FMT_ONELINE) putchar(' '); else diff --git a/log-tree.c b/log-tree.c index cec3c06..cf7947b 100644 --- a/log-tree.c +++ b/log-tree.c @@ -52,11 +52,13 @@ static void show_parents(struct commit *commit, int abbrev) } } -void show_decorations(struct commit *commit) +void show_decorations(struct rev_info *opt, struct commit *commit) { const char *prefix; struct name_decoration *decoration; + if (opt->show_source && commit->util) + printf(" %s", (char *) commit->util); decoration = lookup_decoration(&name_decoration, &commit->object); if (!decoration) return; @@ -279,7 +281,7 @@ void show_log(struct rev_info *opt) fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout); if (opt->print_parents) show_parents(commit, abbrev_commit); - show_decorations(commit); + show_decorations(opt, commit); if (opt->graph && !graph_is_commit_finished(opt->graph)) { putchar('\n'); graph_show_remainder(opt->graph); @@ -352,7 +354,7 @@ void show_log(struct rev_info *opt) printf(" (from %s)", diff_unique_abbrev(parent->object.sha1, abbrev_commit)); - show_decorations(commit); + show_decorations(opt, commit); printf("%s", diff_get_color_opt(&opt->diffopt, DIFF_RESET)); if (opt->commit_format == CMIT_FMT_ONELINE) { putchar(' '); diff --git a/log-tree.h b/log-tree.h index 3c8127b..f2a9008 100644 --- a/log-tree.h +++ b/log-tree.h @@ -12,7 +12,7 @@ int log_tree_diff_flush(struct rev_info *); int log_tree_commit(struct rev_info *, struct commit *); int log_tree_opt_parse(struct rev_info *, const char **, int); void show_log(struct rev_info *opt); -void show_decorations(struct commit *commit); +void show_decorations(struct rev_info *opt, struct commit *commit); void log_write_email_headers(struct rev_info *opt, const char *name, const char **subject_p, const char **extra_headers_p, diff --git a/revision.c b/revision.c index 2f646de..d45f05a 100644 --- a/revision.c +++ b/revision.c @@ -199,6 +199,8 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object mark_parents_uninteresting(commit); revs->limited = 1; } + if (revs->show_source && !commit->util) + commit->util = (void *) name; return commit; } @@ -484,6 +486,8 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, if (parse_commit(p) < 0) return -1; + if (revs->show_source && !p->util) + p->util = commit->util; p->object.flags |= left_flag; if (!(p->object.flags & SEEN)) { p->object.flags |= SEEN; diff --git a/revision.h b/revision.h index 2fdb2dd..51a4863 100644 --- a/revision.h +++ b/revision.h @@ -53,6 +53,7 @@ struct rev_info { left_right:1, rewrite_parents:1, print_parents:1, + show_source:1, reverse:1, reverse_output_stage:1, cherry_pick:1, -- cgit v0.10.2-6-g49f6 From 3a5e860815010e362c746aedf7981e9b3b9a69e8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 3 Nov 2008 10:45:41 -0800 Subject: revision: make tree comparison functions take commits rather than trees This will make it easier to do various clever things that don't depend on the pure tree contents. It also makes the parameter passing much simpler - the callers doesn't really look at trees anywhere else, and it's really the function that should look at the low-level details. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano diff --git a/revision.c b/revision.c index d45f05a..56b09eb 100644 --- a/revision.c +++ b/revision.c @@ -294,8 +294,11 @@ static void file_change(struct diff_options *options, DIFF_OPT_SET(options, HAS_CHANGES); } -static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2) +static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct commit *commit) { + struct tree *t1 = parent->tree; + struct tree *t2 = commit->tree; + if (!t1) return REV_TREE_NEW; if (!t2) @@ -308,12 +311,13 @@ static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree return tree_difference; } -static int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1) +static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit) { int retval; void *tree; unsigned long size; struct tree_desc empty, real; + struct tree *t1 = commit->tree; if (!t1) return 0; @@ -347,7 +351,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) return; if (!commit->parents) { - if (rev_same_tree_as_empty(revs, commit->tree)) + if (rev_same_tree_as_empty(revs, commit)) commit->object.flags |= TREESAME; return; } @@ -367,7 +371,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) die("cannot simplify commit %s (because of %s)", sha1_to_hex(commit->object.sha1), sha1_to_hex(p->object.sha1)); - switch (rev_compare_tree(revs, p->tree, commit->tree)) { + switch (rev_compare_tree(revs, p, commit)) { case REV_TREE_SAME: tree_same = 1; if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) { @@ -387,7 +391,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) case REV_TREE_NEW: if (revs->remove_empty_trees && - rev_same_tree_as_empty(revs, p->tree)) { + rev_same_tree_as_empty(revs, p)) { /* We are adding all the specified * paths from this parent, so the * history beyond this parent is not -- cgit v0.10.2-6-g49f6 From d467a525da28b28a0d8e16a42e121ab638fa7347 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 3 Nov 2008 11:23:57 -0800 Subject: Make '--decorate' set an explicit 'show_decorations' flag We will want to add decorations without necessarily showing them, so add an explicit revisions info flag as to whether we're showing decorations or not. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano diff --git a/builtin-log.c b/builtin-log.c index 176cbce..82ea07b 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -28,7 +28,6 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { int i; - int decorate = 0; rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; @@ -55,7 +54,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, const char *arg = argv[i]; if (!strcmp(arg, "--decorate")) { load_ref_decorations(); - decorate = 1; + rev->show_decorations = 1; } else if (!strcmp(arg, "--source")) { rev->show_source = 1; } else diff --git a/log-tree.c b/log-tree.c index cf7947b..5444f08 100644 --- a/log-tree.c +++ b/log-tree.c @@ -59,6 +59,8 @@ void show_decorations(struct rev_info *opt, struct commit *commit) if (opt->show_source && commit->util) printf(" %s", (char *) commit->util); + if (!opt->show_decorations) + return; decoration = lookup_decoration(&name_decoration, &commit->object); if (!decoration) return; diff --git a/revision.h b/revision.h index 51a4863..0a1806a 100644 --- a/revision.h +++ b/revision.h @@ -54,6 +54,7 @@ struct rev_info { rewrite_parents:1, print_parents:1, show_source:1, + show_decorations:1, reverse:1, reverse_output_stage:1, cherry_pick:1, -- cgit v0.10.2-6-g49f6 From 78892e32616f00bf173496ca0502aff2e523db31 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 3 Nov 2008 11:25:46 -0800 Subject: revision traversal: '--simplify-by-decoration' With this, you can simplify history not by the contents of the tree, but whether a commit has been named (ie it's referred to by some branch or tag) or not. This makes it possible to see the relationship between different named commits, without actually seeing any of the details. When used with pathspec, you would get the usual view that is limited to the commits that change the contents of the tree plus commits that are named. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano diff --git a/revision.c b/revision.c index 56b09eb..9dc55d4 100644 --- a/revision.c +++ b/revision.c @@ -11,6 +11,7 @@ #include "reflog-walk.h" #include "patch-ids.h" #include "decorate.h" +#include "log-tree.h" volatile show_early_output_fn_t show_early_output; @@ -301,6 +302,24 @@ static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct if (!t1) return REV_TREE_NEW; + + if (revs->simplify_by_decoration) { + /* + * If we are simplifying by decoration, then the commit + * is worth showing if it has a tag pointing at it. + */ + if (lookup_decoration(&name_decoration, &commit->object)) + return REV_TREE_DIFFERENT; + /* + * A commit that is not pointed by a tag is uninteresting + * if we are not limited by path. This means that you will + * see the usual "commits that touch the paths" plus any + * tagged commit by specifying both --simplify-by-decoration + * and pathspec. + */ + if (!revs->prune_data) + return REV_TREE_SAME; + } if (!t2) return REV_TREE_DIFFERENT; tree_difference = REV_TREE_SAME; @@ -1041,6 +1060,14 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg revs->rewrite_parents = 1; revs->simplify_history = 0; revs->limited = 1; + } else if (!strcmp(arg, "--simplify-by-decoration")) { + revs->simplify_merges = 1; + revs->rewrite_parents = 1; + revs->simplify_history = 0; + revs->simplify_by_decoration = 1; + revs->limited = 1; + revs->prune = 1; + load_ref_decorations(); } else if (!strcmp(arg, "--date-order")) { revs->lifo = 0; revs->topo_order = 1; diff --git a/revision.h b/revision.h index 0a1806a..7cf8487 100644 --- a/revision.h +++ b/revision.h @@ -43,6 +43,7 @@ struct rev_info { lifo:1, topo_order:1, simplify_merges:1, + simplify_by_decoration:1, tag_objects:1, tree_objects:1, blob_objects:1, -- cgit v0.10.2-6-g49f6 From 30c4d7a76a96cf7a2848b752083364c51b051f30 Mon Sep 17 00:00:00 2001 From: Nanako Shiraishi Date: Mon, 10 Nov 2008 18:58:15 +0900 Subject: Document "git log --source" Signed-off-by: Nanako Shiraishi Signed-off-by: Junio C Hamano diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 93a2a22..34cf4e5 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -40,6 +40,10 @@ include::diff-options.txt[] --decorate:: Print out the ref names of any commits that are shown. +--source:: + Print out the ref name given on the command line by which each + commit was reached. + --full-diff:: Without this flag, "git log -p ..." shows commits that touch the specified paths, and diffs about the same specified -- cgit v0.10.2-6-g49f6 From 3fcfd662dc84830d25ee966b8d5325806b7c51b2 Mon Sep 17 00:00:00 2001 From: Nanako Shiraishi Date: Mon, 10 Nov 2008 18:58:17 +0900 Subject: Document "git log --simplify-by-decoration" Signed-off-by: Nanako Shiraishi Signed-off-by: Junio C Hamano diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 966276b..6689238 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -456,6 +456,14 @@ Note the major differences in `N` and `P` over '\--full-history': removed completely, because it had one parent and is TREESAME. -- +The '\--simplify-by-decoration' option allows you to view only the +big picture of the topology of the history, by omitting commits +that are not referenced by tags. Commits are marked as !TREESAME +(in other words, kept after history simplification rules described +above) if (1) they are referenced by tags, or (2) they change the +contents of the paths given on the command line. All other +commits are marked as TREESAME (subject to be simplified away). + ifdef::git-rev-list[] Bisection Helpers ~~~~~~~~~~~~~~~~~ -- cgit v0.10.2-6-g49f6 From 7bc2508bfe0f7e8c0371a68f57ac5b7d4fe7e1f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20B=C3=A9jar?= Date: Wed, 12 Nov 2008 11:51:28 +0100 Subject: rev-list documentation: clarify the two parts of history simplification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One set of options and parameters determine what commits are involved in the simplification process, and another set of options determine how the simplification is done. Clarify their distinction at the beginning. Signed-off-by: Santi BĂ©jar Signed-off-by: Junio C Hamano diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 6689238..78c381a 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -285,8 +285,52 @@ See also linkgit:git-reflog[1]. History Simplification ~~~~~~~~~~~~~~~~~~~~~~ -When optional paths are given, 'git-rev-list' simplifies commits with -various strategies, according to the options you have selected. +Sometimes you are only interested in parts of the history, for example the +commits modifying a particular . But there are two parts of +'History Simplification', one part is selecting the commits and the other +is how to do it, as there are various strategies to simplify the history. + +The following options select the commits to be shown: + +:: + + Commits modifying the given are selected. + +--simplify-by-decoration:: + + Commits that are referred by some branch or tag are selected. + +Note that extra commits can be shown to give a meaningful history. + +The following options affect the way the simplification is performed: + +Default mode:: + + Simplifies the history to the simplest history explaining the + final state of the tree. Simplest because it prunes some side + branches if the end result is the same (i.e. merging branches + with the same content) + +--full-history:: + + As the default mode but does not prune some history. + +--dense:: + + Only the selected commits are shown, plus some to have a + meaningful history. + +--sparse:: + + All commits in the simplified history are shown. + +--simplify-merges:: + + Additional option to '--full-history' to remove some needless + merges from the resulting history, as there are no selected + commits contributing to this merge. + +A more detailed explanation follows. Suppose you specified `foo` as the . We shall call commits that modify `foo` !TREESAME, and the rest TREESAME. (In a diff -- cgit v0.10.2-6-g49f6