24

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?

2 Answers 2

23

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.

0
14

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

 git checkout refs/heads/v1.5.2

or

git checkout refs/tags/v1.5.2
1
  • The semantics with the refs/heads/... name seems not to be the same. This seems not to check out the branch, but the commit the branch currently points to. git "complains": You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch.
    – haui
    Mar 29 at 7:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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