The loop iterating over the parent commits in the name_rev() function contains two xstrfmt() calls, and their result is leaked if the parent commit is not processed further (because that parent has already been visited before, and this further visit doesn't result in a better name for its ancestors). Make sure that the result of those xstrfmt() calls is free()d if the parent commit is not processed further. This results in slightly but measurably lower memory usage: the avarage maximum resident size of 5 'git name-rev --all' invocations in 'linux.git' shrinks from 3256124kB to 319990kB, just about 2% less. Signed-off-by: SZEDER Gábor <szeder.dev@xxxxxxxxx> --- builtin/name-rev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/builtin/name-rev.c b/builtin/name-rev.c index f867d45f0b..d65de04918 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -139,6 +139,7 @@ static void name_rev(struct commit *start_commit, struct commit *parent = parents->item; const char *new_name; int generation, distance; + const char *new_name_to_free = NULL; parse_commit(parent); if (parent->date < cutoff) @@ -158,6 +159,7 @@ static void name_rev(struct commit *start_commit, new_name = xstrfmt("%.*s^%d", (int)len, name->tip_name, parent_number); + new_name_to_free = new_name; generation = 0; distance = name->distance + MERGE_TRAVERSAL_WEIGHT; } else { @@ -171,6 +173,8 @@ static void name_rev(struct commit *start_commit, from_tag)) last_new_parent = commit_list_append(parent, last_new_parent); + else + free((char*) new_name_to_free); } *last_new_parent = list; -- 2.23.0.331.g4e51dcdf11