On Thu, Feb 15, 2018 at 5:45 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote: > [...] > Update the default (again) for "git merge" that merges a tag object > to (1) --no-ff (i.e. create a merge commit even when side branch > fast forwards) if the tag being merged is not at its expected place > in refs/tags/ hierarchy and (2) --ff (i.e. allow fast-forward update > when able) otherwise. > > Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> > --- > diff --git a/builtin/merge.c b/builtin/merge.c > @@ -1125,6 +1126,42 @@ static struct commit_list *collect_parents(struct commit *head_commit, > +static int merging_a_throwaway_tag(struct commit *commit) > +{ > + const char *tag_ref; > + struct object_id oid; > + > + /* Are we merging a tag? */ > + if (!merge_remote_util(commit) || > + !merge_remote_util(commit)->obj || > + merge_remote_util(commit)->obj->type != OBJ_TAG) > + return 0; > + > + /* > + * Now we know we are merging a tag object. Are we downstream > + * and following the tags from upstream? If so, we must have > + * the tag object pointed at by "refs/tags/$T" where $T is the > + * tagname recorded in the tag object. We want to allow such > + * a "just to catch up" merge to fast-forward. > + */ > + tag_ref = xstrfmt("refs/tags/%s", > + ((struct tag *)merge_remote_util(commit)->obj)->tag); xstrfmt() allocates a new string... > + if (!read_ref(tag_ref, &oid) && > + !oidcmp(&oid, &merge_remote_util(commit)->obj->oid)) > + return 0; ...which is leaked here... > + > + /* > + * Otherwise, we are playing an integrator's role, making a > + * merge with a throw-away tag from a contributor with > + * something like "git pull $contributor $signed_tag". > + * We want to forbid such a merge from fast-forwarding > + * by default; otherwise we would not keep the signature > + * anywhere. > + */ > + return 1; ...and here. > +}