The rights and wrongs of git push with tags

My employer uses tags for versioning builds.

git push && git push — tags
I’m guessing this is standard practice, but we’ve been running into an issue with our build server — Atlassian’s Bamboo — picking up commits without their tags. The reason was obvious: we’ve been using git push && git push — tags, pushing tags after the commits, and Bamboo doesn’t trigger builds on tags, only on commits. This means that every build would be versioned with the previous version’s tag!

The solution should have been obvious, too: push tags with the commits. Or before the commits? Recently, we played around with an experimental repo and learned the following:

git push — tags && git push
To the uninitiated (like us), the result of running git push — tags can be quite surprising! We created a commit locally, tagged it*, and ran git push — tags. This resulted in the commit being pushed to the server (Bitbucket, in our case) along with its tag, but the commit was rendered invisible. Not even git ls-remote — tags origin would return it, and it was not listed under the commits on its branch, although it showed up with its commit on Bitbucket’s feature to search commits by tag quite clearly:

* All tags are annotated, automatically, courtesy of SourceTree. If you’re not using SourceTree then you should be, and I promise you I’m not being paid to say that. If you must insist on the barbaric practice of using the command line, just add -a (and -m to specify the message inline if you don’t want the editor to pop up, check out the documentation for more details).

Pushing a tag first isn’t the end of the world — simply pushing the commit with git push afterwards puts everything in order — unless someone else pushes a different commit first. At that point the original commit will need to be merged, with merge conflicts to be expected. Alternatively — and relevant for us — any scripts that perform commits automatically might fail between pushing the tags and their commits, leading to “lost” commits.

git push — tags origin refs/heads/develop:refs/heads/develop
This ugly-to-type command does what we want it to do: it pushes the commit and its tags together. From the documentation:

When the command line does not specify what to push with <refspec>… arguments or — all, — mirror, — tags options, the command finds the default…

Adam Fisher / fisher king (@therightstuff)

Software developer and writer of words, currently producing a graphic novel adaptation of Shakespeare's Sonnets! See for details.