Skip to content

Commit c8382c1

Browse files
committed
Merge branch 'jc/rev-list-simplify-merges-first-parent' into maint
When "git log" gets "--simplify-merges/by-decoration" together with "--first-parent", the combination of these options makes the simplification logic to use in-core commit objects that haven't been examined for relevance, either producing incorrect result or taking too long to produce any output. Teach the simplification logic to ignore commits that the first-parent traversal logic ignored when both are in effect to work around the issue. * jc/rev-list-simplify-merges-first-parent: revision: ignore side parents while running simplify-merges revision: note the lack of free() in simplify_merges() revision: "simplify" options imply topo-order sort
2 parents a101eb4 + 6e513ba commit c8382c1

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

revision.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,11 +1358,13 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
13581358
revs->topo_order = 1;
13591359
} else if (!strcmp(arg, "--simplify-merges")) {
13601360
revs->simplify_merges = 1;
1361+
revs->topo_order = 1;
13611362
revs->rewrite_parents = 1;
13621363
revs->simplify_history = 0;
13631364
revs->limited = 1;
13641365
} else if (!strcmp(arg, "--simplify-by-decoration")) {
13651366
revs->simplify_merges = 1;
1367+
revs->topo_order = 1;
13661368
revs->rewrite_parents = 1;
13671369
revs->simplify_history = 0;
13681370
revs->simplify_by_decoration = 1;
@@ -1947,15 +1949,18 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
19471949
}
19481950

19491951
/*
1950-
* Do we know what commit all of our parents should be rewritten to?
1951-
* Otherwise we are not ready to rewrite this one yet.
1952+
* Do we know what commit all of our parents that matter
1953+
* should be rewritten to? Otherwise we are not ready to
1954+
* rewrite this one yet.
19521955
*/
19531956
for (cnt = 0, p = commit->parents; p; p = p->next) {
19541957
pst = locate_simplify_state(revs, p->item);
19551958
if (!pst->simplified) {
19561959
tail = &commit_list_insert(p->item, tail)->next;
19571960
cnt++;
19581961
}
1962+
if (revs->first_parent_only)
1963+
break;
19591964
}
19601965
if (cnt) {
19611966
tail = &commit_list_insert(commit, tail)->next;
@@ -1968,8 +1973,13 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
19681973
for (p = commit->parents; p; p = p->next) {
19691974
pst = locate_simplify_state(revs, p->item);
19701975
p->item = pst->simplified;
1976+
if (revs->first_parent_only)
1977+
break;
19711978
}
1972-
cnt = remove_duplicate_parents(commit);
1979+
if (!revs->first_parent_only)
1980+
cnt = remove_duplicate_parents(commit);
1981+
else
1982+
cnt = 1;
19731983

19741984
/*
19751985
* It is possible that we are a merge and one side branch
@@ -2013,25 +2023,31 @@ static struct commit_list **simplify_one(struct rev_info *revs, struct commit *c
20132023

20142024
static void simplify_merges(struct rev_info *revs)
20152025
{
2016-
struct commit_list *list;
2026+
struct commit_list *list, *next;
20172027
struct commit_list *yet_to_do, **tail;
2028+
struct commit *commit;
20182029

2019-
if (!revs->topo_order)
2020-
sort_in_topological_order(&revs->commits, revs->lifo);
20212030
if (!revs->prune)
20222031
return;
20232032

20242033
/* feed the list reversed */
20252034
yet_to_do = NULL;
2026-
for (list = revs->commits; list; list = list->next)
2027-
commit_list_insert(list->item, &yet_to_do);
2035+
for (list = revs->commits; list; list = next) {
2036+
commit = list->item;
2037+
next = list->next;
2038+
/*
2039+
* Do not free(list) here yet; the original list
2040+
* is used later in this function.
2041+
*/
2042+
commit_list_insert(commit, &yet_to_do);
2043+
}
20282044
while (yet_to_do) {
20292045
list = yet_to_do;
20302046
yet_to_do = NULL;
20312047
tail = &yet_to_do;
20322048
while (list) {
2033-
struct commit *commit = list->item;
2034-
struct commit_list *next = list->next;
2049+
commit = list->item;
2050+
next = list->next;
20352051
free(list);
20362052
list = next;
20372053
tail = simplify_one(revs, commit, tail);
@@ -2043,9 +2059,10 @@ static void simplify_merges(struct rev_info *revs)
20432059
revs->commits = NULL;
20442060
tail = &revs->commits;
20452061
while (list) {
2046-
struct commit *commit = list->item;
2047-
struct commit_list *next = list->next;
20482062
struct merge_simplify_state *st;
2063+
2064+
commit = list->item;
2065+
next = list->next;
20492066
free(list);
20502067
list = next;
20512068
st = locate_simplify_state(revs, commit);

0 commit comments

Comments
 (0)