13 ms·
Proper use of Git tags
- CamelRocketFish 4y agoThe author suggest prepending v to a tag name for the sake of shell completion. This assumes that everyone will be interacting with git tags using a shell. I disagree that a v should be prepended for that reason.
- silverwind 4y agoYes, this practice of adding a v is common, yet pointless. I prefer my git tags to be valid semvers.
- wnoise 4y agoThis works iff you never want to tag anything but semvers. This is an unusual and strict policy. As soon as you want the ability to move outside this you need something like namespacing. Prepending v is a pretty lightweight way to do this.
- inetknght 4y ago> The author suggest prepending v to a tag name for the sake of shell completion. This assumes that everyone will be interacting with git tags using a shell. I would argue that any tool (such as a GUI app) which doesn't provide the depth of usability that a shell offers is, in fact, a deficiency in the GUI or tool. If your GUI doesn't offer completions similar to a shell then your GUI tool is inferior to a shell.
- V-2 4y agoThis is usually the case. GUIs are superior in some aspects (eg. visualization of complex branch structures), inferior in others (eg. add more friction - many operations can be done faster from the console). As far as Git goes, I see GUI clients as complementary rather than full-scale substitute for the terminal.
- Tyr42 4y agoGitHub let's you do a partial filter. So it helps there too.
- ed25519FUUU 4y agoI don’t like semantic versioning because it’s difficult to sort. E.g. 1.2 is more than 1.100, and that doesn’t even include fix versions. Has there been a better proposal to semantic tags which makes organizing and sorting them easier?
- paol 4y agoSemantic versions can't be sorted trivially, it's true. For projects that benefit from the "semantic" part of semantic versioning the benefits outweigh that minor inconvenience. But not everything needs semantic versioning.
- ssully 4y agoIt's not semantic versioning, but a project I am on started using calendar versioning[1]. I was hesitant to try it at first, but it's kind of growing on me. It's really easy to organize and sort. We have a pretty regular release cadence so it was easy to implement, but I could see it being more complicated for certain projects. [1]: https://calver.org/ https://calver.org/
- klysm 4y agoI think calver is good for things that don't really have an API per se. Stuff like GUI applications.
- pizza234 4y agoSort in which context? Unix has `sort -V`. Of the other languages I use, they all have either built-in functionalities, or small libraries to do it.
- infogulch 4y agoThat's a good point. With the omnipresence of semver, you'd think that more interfaces would support sorting tags with a semver comparison instead of lexically. I searched for a bit and found that github does this ( e.g. https://github.com/TryGhost/Ghost/tags https://github.com/TryGhost/Ghost/tags ). Also there is a git config that sets this globally for the git cli: `git config --global tag.sort version:refname` ( found here: https://gist.github.com/loisaidasam/b1e6879f3deb495c22cc https://gist.github.com/loisaidasam/b1e6879f3deb495c22cc ). That's another git config going onto every machine I use...
- CalChris 4y agoHow do I pull something like LLVM 14.0.0 by tag?
- abdusco 4y agogit clone -b $tag $repo_url
- AceJohnny2 4y agoCouple ways, for example on the github page [1] , click the "tags" link [2] above the file list, find the tag for release 14.0.0, which is llvmorg-14.0.0, and now you can do any commit operation with that name instead of a commit. If you have a checkout, you can find the tag name by doing a git tag -l *14* and looking through the output; I'm intentionally providing a very general glob because one may not know beforehand their exact tag name conventions. [1] https://github.com/llvm/llvm-project https://github.com/llvm/llvm-project [2] https://github.com/llvm/llvm-project/tags https://github.com/llvm/llvm-project/tags
- captn3m0 4y agoAnother important reason to use annotated tags: Tags without annotation are just a reference to a commit and cannot contain any metadata, such as the release date or the release authorship information.
- globular-toast 4y agoLightweight tags are not supposed to be pushed. They are meant to be used to help with scripts and stuff. It's a great example of weird git UI that lightweight tags are the default when 99% of of users would never want to create one.
- bmon 4y agoI can't agree with having a source file include the tag. It is an eternal source of merge conflicts and pain, unless you take steps to automate it. And in that case, does the file add much value anymore? My personal experience with go modules and versioning has been really positive. In that ecosystem - you only define your major version in the mod file and rely on the VCS for everything else.
- da-x 4y agoI don't think that it poses an issue with merge conflicts. It is likely not an issue as long as the tagging is only made on the main branch by the release managers. I know it is working well for Linux kernel hackers. Linus does all the tagging, and I don't recall issues with merge conflicts on the top Makefile with the part that holds the version.
- zbuf 4y agoI think you're assuming that all software results in a single "release manager". In many environments, multiple branches of software are deployed and maintained at the same time. Even your example with Linux; I don't think that is correct -- Linus doesn't tag the stable branches, and others. There is a centralised agreement of how the version numbers are maintained though.
- da-x 4y agoMy example is relevant to tagging in branches that may merge back into the main one. The stable branches in Linux are cherry-pick branches that don't get merged back and therefore creating tags there is harmless.
- zbuf 4y agoYes, having a version number centralised in source code is exactly the thing Git helped us many times to avoid. Also ties in with the author's recommendation to begin tags with "v". My experience is that excluding it is better. Then a simple "git describe" readily gives the version number in scripts with no sed or reprocessing. I've seen many conventions with Git. It's interesting to hear some rationale, but a stretch to describe these suggestions as the "proper" way.
- TekMol 4y agoWhat are the pros and cons of branches+merge-commits vs tags? So instead of a "v4.11-rc7-87" tag you would have a "v4.11-rc7-87" branch and a merge commit that holds the meta info about that branch.
- da-x 4y agoThese are not mutually exclusive. Tags relate to commits irrespective of the containing branch or the merge history.
- Hackbraten 4y agoBranches are mutable, tags aren’t. You can add a commit to `v4.11-rc7-87` anytime. Now your branch has grown past the merge commit. Confusion ensues. Compared to a tag, you’d have to deliberately go out of your way to move a tag (`git tag -f`). Generally, you should be able to trust your team members not to move a tag.
- WorldMaker 4y agoAnnotated Tags hold meta info for the tag. (git tag -a) That's why a lot of advice is to always use annotated tags. They look like a commit with an author, a message, and can be signed, etc. Branches can change over time, whereas tags are largely immutable. A change to a tag always requires a force push and if you've got branch protection tools in your repository host's arsenal you can often entirely prevent tag changes. I'd also like to point out that often if you are using merge commits as your "version management tool" there's a lot of people that use "branch per environment" strategies and need to merge between environments. There's a lot more risk in that approach than a tag-based approach: if a tag doesn't change after it is applied, then you don't need to rebuild binaries to deploy it again. If you don't rebuild binaries between environments you have to make sure the same binaries work in all environments, which is good practice. I've seen too many times "branch-per-environment" strategies wind up with per-environment code that is difficult to untangle and makes testing and debugging difficult and merge conflicts more likely and more complicated and increases the risk of per-environment bugs.
- ww520 4y agoThey are for different purposes. Branch is for working on the code. Once done, use tag to snapshot a release. The branch can move forward as needed.
- azundo 4y ago> The commit that changed the version in source is the one to be tagged I've never understood this practice of not immediately bumping the version in source after a release. We update the version in source to the next logical version (usually a patch bump with an alpha0 pre-release tag) immediately after tagging and publishing a release. This way you just need to look at the version in source to understand where you're at in a release process, and only a single commit has the full release version in source, which is also tagged as such. This doesn't seem to be a common pattern, so shat are the downsides of this approach? Am I missing something?
- da-x 4y agoOP here. I agree with this as well, you are not missing anything. I was meaning to write another post about a similar approach. To illustrate to readers, let's say we are developing over a tag `v1.2-pre` in `main`, and now the code has stabilized. The idea is to release a tagged `v1.2`, then in the `main` branch immediately release a tagged `v1.3-pre` that follows it. We obtain the following: 1) `main` branch commits look like `v1.3-pre-<number>-g<hash>` in `git-describe`. 2) A maintenance branch may have been forked from the commit that was tagged with `v1.2`, so for the commits in that `release/1.2` branch you automatically get `v1.2-<number>-g<hash>` as output of `git describe`.
- Hackbraten 4y agoI feel that both variants have their merits. One possible downside (of version bumping immediately after release) is that if you use the major/minor/patch scheme, you can never be sure that you’re actually bumping the correct number. The upcoming release may be a major, a minor, or a patch release, and it might take you a while until you know enough about completed work items so you can make up your mind which one it’s going to be.
- tjoff 4y agoNot sure why that is a downside? Once you realize you need to update minor or whatever then update it, done. As a bonus you have great visibility into why and when the minor needed to update.
- junon 4y agoPlease don't prefix version tags with "v"...
- recursive 4y agoI'm not stopping until you give me a reason. So far it hasn't caused any problems.
- foobarbaz33 4y agoI guess it contributes to global warming. Not in a significant way. But it literally does take more energy to write an extra character to a disk.
- patmorgan23 4y agoWhy?
- Groxx 4y ago>Tag push permissions Agreed entirely on restricting tags (they tend to have meaning and expected semantics outside the repo, which makes them risky), but also! Teach people more about git, or unix CLI patterns in general. `git log test` is ambiguous about it being a tag (or branch) or file/folder, but `git log -- test` is not. `--` as an ambiguity-preventer is a very common pattern, it works in many, many CLI tools. --- One that hasn't been included here: don't rely on tags for any kind of business logic, if you have literally any way to avoid it. Tags are mutable, and do not have a history of when you changed them. They're plenty handy for "human, enter a thing to use" purposes, but you should immediately turn that into a commit sha and then only use that commit sha.
- avgcorrection 4y agoWait. Aren't tags immutable?
- colonwqbang 4y agoNope. A tag is just a file in the .git directory. Delete the file, delete the tag. $ rm .git/refs/tags/v1.0 or in git syntax $ git tag -d v1.0 For this reason one should never use tags when pulling code from untrusted repos, instead use the SHA1 hash which is much harder to forge.
- avgcorrection 4y agoUm okay. That is not what anyone means when they talk about immutable objects or refs in Git. I can delete a commit from `.git` but they are still considered immutable. A branch is mutable since you can push it forward without `--force` as long as the current commit becomes an ancestor of the next tip. Can you change a remote tag without `--force`? I don't know off the top of my head. But I doubt it.
- TobTobXX 4y agoChecked it for you: To /tmp/foo1/ ! [rejected] ddd -> ddd (already exists) error: failed to push some refs to '/tmp/foo1/' hint: Updates were rejected because the tag already exists in the remote. I think any ref is 'mutable' by these standards, and any hash is immutable (that's the entire point of a hash).
- unholiness 4y agoOur company uses a tag, quite improperly, to indicate our "last successful build" on each branch, so our local builds can pull e.g. compiled .o files from that build and speed up the local build process. A tag is improper since it needs to move with every successful build. All relevant commands need --force to update it and it can rarely create headaches when machines disagree. I believe the right thing functionally is a child branch, updated automatically with either a merge or a force-push on new successful builds. But it feels not quite right conceptually, and it's harder to explain to new developers (who can already get overwhelmed with handling multiple branches). Is there a non-branch solution for having a moving unique label?
- avar 4y agoDon't clobber the branch or tag, instead create dated tags with a name like built-YYYYMMDD-HHMMSS. Then have downstream systems pick whatever the latest tag is. You can force push it, but why not keep a trail of what your past state was?
- unholiness 4y agoBecause the "downstream systems" you mention are just all local git commands. It is necessary to branch from these points, so creating branches and checking state requires them. So e.g. `git diff lsb/master` becomes `git diff lsb/master/built-YYYYMMDD-HHMMSS` or at least `git diff $(git merge-base master)`. That doesn't seem better than the occasional --force.
- avar 4y agoIt's better because you might be looking at the output of that, and then your co-worker tries to do the same, except you're looking at different because you force-pushed it. And you furthermore have no immutable record of what happened anymore. You can always create one tag that you force-push to point to the "latest tag" to make it convenient for one-liners, but not force-push any of the "real" ones.
- Robin_Message 4y agoSince the OP is here, I am confused. In the first section, are you saying that: a) tags can and should be named to include the sha at the end; and b) git commands silently discard everything before "-g" if what follows is a sha? I feel like I've missed something as I find b) very surprising. (Consider giving someone the string $LATEST_VERSION_NUMBER-g$MALICIOUS_VERSION_SHA; I can't work out an exact exploit but it seems wrong to only process the SHA.)
- da-x 4y agoI'll try to clarify. The `<tag>-g<hash>` string is _not_ the name of the tag, it's a string emitted by `git describe` based on the existence of `<tag>` in the history. Of course I'm not suggesting that tag names should include the hash. The existence of the tag `v4.11-rc7` allows other commits to have nicer derived names. EDIT: Also to your last inquiry, it may be indeed a surprise that Git resolves `<anystring>-g<githash>` to `<githash>`, but some may argue it's a feature, not a bug :)
- WorldMaker 4y agoAlso, git describe's output is not just <tag>-g<hash>, it is <tag>-<commitcount>-g<hash>. That number of commits since the tag counter can be handy in its own way (such as it is sometimes handy when trying to figure out which branch the <hash> is most likely from). I'm curious if the git resolution algorithm that accepts describe strings also verifies/checks the commit count matches. Glancing at the documentation [1] it says that it specifically matches describe output strings (the docs call it <describeOutput>) and not just "<anything>-g<hash>", so it may actually check the tag existence and verify the commit count. [1] https://git-scm.com/docs/gitrevisions https://git-scm.com/docs/gitrevisions
- nickjj 4y agoAnnotated tags are a good idea, they also happen to be a requirement when signing tags. You can create empty message signed annotated tags with `git tag -sm "" v123-my-signed-tag`. I once made a blog post / video around signing and verifying your commits and tags at: https://nickjanetakis.com/blog/signing-and-verifying-git-commits-on-the-command-line-and-github https://nickjanetakis.com/blog/signing-and-verifying-git-com...
- vim-guru 4y agoAlthough not git-tag specific, if you want to see a great rant on semantic versioning, I can highly recommend Rich Hickey's. https://www.youtube.com/watch?v=oyLBGkS5ICk&t=30m https://www.youtube.com/watch?v=oyLBGkS5ICk&t=30m
- deleted 4y ago[deleted]