1

I'm expecting Git to create a merge commit when I merge a signed or annotated tag but instead it fast-forwards the branch pointer. I'm using Git version 2.17.0 on openSUSE Tumbleweed that comes with it.

According to the manpage of git-merge(1) it should create a merge commit in case of merging a signed/annotated tag:

--no-ff Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag that is not stored in its natural place in refs/tags/ hierarchy.

The sequence of commands which I issued looks like this:

git init foobar
cd foobar
git commit --allow-empty -m 'Empty root commit'
git checkout -b feature
git commit --allow-empty -m 'Feature one commit ahead of master'
git tag -a -m 'Feature ready for non fast-forward merge' ready-to-merge-feature
git checkout master
git merge ready-to-merge-feature

Unfortunately and unexpectedly the merge of the annotated tag ready-to-merge-feature does result in a fast-forward merge instead of creating a merge commit. The same unexpected behavior I observe with a signed instead of an annotated tag.

Are my assumptions wrong? Am I doing something wrong? What would be a solution?

0

Note the part of the manpage that you'd quoted that I've bolded below:

This is the default behaviour when merging an annotated (and possibly signed) tag that is not stored in its natural place in refs/tags/ hierarchy.

With the command sequence that you gave, the tag would be in its natural place, so the conditions for that default wouldn't apply.

This default was put in place to aid fetching a tag from a contributors repository as FETCH_HEAD in the maintainer's repository. Such tags are likely to be ephemeral, so if they have content (an annotation and/or signature) it's usually good to preserve that information in a merge commit. But, tags that are already under refs/tags/ are likely to be part of the permanent state of the project, and thus the content should remain available without needing to be transferred to a commit.

The simplest solution would probably be to explicitly use the --no-ff option.

  • I noticed the text in bold too but cannot make any sense out of it. Shouldn't tags stored under the location refs/tags be the standard and thus the --no-ff behavior apply? – Tim Friske Jun 5 '18 at 15:15
  • @TimFriske Yes tags under refs/tags are the standard, which is why they aren't considered for this. This is designed to preserve the content of ephemeral tags that are used by a contributor requesting the project maintainer to pull code in a given state. Tags that are already accessible under the refs/tags are likely to be part of the permanent state of the project, and thus not in danger of being lost. – qqx Jun 5 '18 at 22:11
  • Where would Git then expect ephemeral tags – that are used by a contributor requesting the project maintainer to pull code in a given state – in order to trigger a non-fast-forward merge by default embedding the signature of the possibly signed tag into the resulting merge commit, i.e. without explicitly passing to Git or configuring no-ff behavior for it? – Tim Friske Jul 9 '18 at 19:03
  • 1
    @TimFriske that type of ephemeral tag would usually be stored temporarily as FETCH_HEAD. But typically that would be internal to running git pull <remote> <tag-name>. – qqx Jul 11 '18 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.