I have a project with a git branching model that roughly follows that of nvie's git-flow.

Our release branches are named in a SemVer format, e.g. v1.5.2

Once a release branch is given the green light for production, we close the branch, by merging it into master, applying a tag, and then deleting the branch.

As we immediately delete the release branch, we've been using the same identifier for tagging the branch, e.g. v1.5.2

Here's the commands we'd use to close a release branch:

$ git checkout master
$ git merge v1.5.2
$ git tag -a v1.5.2 -m "Version 1.5.2 - foo bar, baz, etc"
$ git branch -d v1.5.2
$ git branch -dr origin/v1.5.2
$ git push origin :v1.5.2
$ git push
$ git push --tags

This seems to work in the majority of cases, however it's causing an issue in the scenario where another instance of the git repo (e.g. another dev machine, or staging environment) has a local checkout of the v1.5.2 branch.

The git push origin :v1.5.2 command will delete the branch in the remote, but does not delete the local version of the branch (if it exists) in all repos.

This leads to an ambiguous reference, when trying checkout v1.5.2 in those repos:

$ git checkout v1.5.2
warning: refname 'v1.5.2' is ambiguous.

Can this be avoided without using a different syntax for the branches, e.g. release-v1.5.2, or v1.5.2-rc?

Or is it unavoidable, and therefore a fundamentally bad idea to create a tag with the same name as a deleted branch?


If you absolutely want to keep this naming scheme, you might:

Decide that you don't care about these warnings

That is, if you're happy with the fact that:

  • git checkout <ref> will check out refs/heads/<ref> over refs/tags/<ref> (see git-checkout)
  • other commands will use refs/tags/<ref> over refs/heads/<ref> (see gitrevisions)

For example, in this test repository, the v1.5.2 branch points to commit B, but the v1.5.2 tag points to commit A.

% git log --oneline --decorate
8060f6f (HEAD, v1.5.2, master) commit B
0e69483 (tag: v1.5.2) commit A

git checkout prefers branch names:

% git checkout v1.5.2
warning: refname 'v1.5.2' is ambiguous.
Switched to branch 'v1.5.2'
% git log --decorate --oneline -1
8060f6f (HEAD, v1.5.2, master) commit B

but git log will use the tag name:

% git log --decorate --oneline -1 v1.5.2
warning: refname 'v1.5.2' is ambiguous.
0e69483 (tag: v1.5.2) commit A

This could be confusing.

Train people to delete their local branches when they see a new tag

This might be hard/awkward depending on the size of your organisation.

Write a wrapper around "git pull" and "git fetch"

That is, write a wrapper that checks if there are any tags that shadow branch names, and warn about (or delete) those branches. This sounds painful, and it could be undesirable if the shadowed branch is currently checked out.

Unfortunately, it sounds like the easiest way to solve this problem might be to change the way you name your branches. The link you posted uses different naming schemes for tags and branches: if you're already mostly following that method, adopting its naming scheme might be the easiest solution.

  • Thanks for the response. Very helpful. Your first bullet states that git checkout will check out the tag over the branch when there is an ambigious reference, however this is not the behaviour I'm seeing, ref: gist.github.com/tommarshall/9376724 . Is this something that changed in a more modern version of git? Is there a flag I can set in gitconfig in order to get this behaviour? Mar 5 '14 at 21:14
  • You're right, I got this completely wrong. Sorry! I've fixed my answer and added an example.
    – benj
    Mar 6 '14 at 12:12

You can explicitly specify whether you want a branch or a tag by using full name:

 git checkout refs/heads/v1.5.2


git checkout refs/tags/v1.5.2

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.