diff options
-rw-r--r-- | Documentation/git-log.txt | 4 | ||||
-rw-r--r-- | Documentation/rev-list-options.txt | 56 | ||||
-rw-r--r-- | builtin-log.c | 5 | ||||
-rw-r--r-- | builtin-rev-list.c | 2 | ||||
-rw-r--r-- | log-tree.c | 10 | ||||
-rw-r--r-- | log-tree.h | 2 | ||||
-rw-r--r-- | revision.c | 45 | ||||
-rw-r--r-- | revision.h | 3 |
8 files changed, 113 insertions, 14 deletions
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 93a2a227c4..34cf4e5811 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 <path>..." shows commits that touch the specified paths, and diffs about the same specified diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 68a253f977..6d7cf6d51f 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 <path>. 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: + +<paths>:: + + Commits modifying the given <paths> 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 <paths>. We shall call commits that modify `foo` !TREESAME, and the rest TREESAME. (In a diff @@ -456,6 +500,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 ~~~~~~~~~~~~~~~~~ diff --git a/builtin-log.c b/builtin-log.c index 75d698f0ce..b164717379 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,9 @@ 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 die("unrecognized argument: %s", arg); } diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 06cdeb7ebe..857742a14f 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 cec3c06136..5444f0860b 100644 --- a/log-tree.c +++ b/log-tree.c @@ -52,11 +52,15 @@ 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); + if (!opt->show_decorations) + return; decoration = lookup_decoration(&name_decoration, &commit->object); if (!decoration) return; @@ -279,7 +283,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 +356,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 3c8127bb7c..f2a90084ae 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 2f646deab0..9dc55d4003 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; @@ -199,6 +200,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; } @@ -292,10 +295,31 @@ 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 (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; @@ -306,12 +330,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; @@ -345,7 +370,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; } @@ -365,7 +390,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)) { @@ -385,7 +410,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 @@ -484,6 +509,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; @@ -1033,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 2fdb2dd0ff..7cf848771b 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, @@ -53,6 +54,8 @@ struct rev_info { left_right:1, rewrite_parents:1, print_parents:1, + show_source:1, + show_decorations:1, reverse:1, reverse_output_stage:1, cherry_pick:1, |