Tag는 한 순간을 고정하고 release는 metadata를 더해
Branch는 움직이지만 tag는 움직이지 않아. Tag는 특정 commit에 붙인 이름이고 한 번 정하면 pointer가 영원히 바뀌지 않아. 대표적인 용도는 release야. ship한 commit에 v2.4.0 tag를 붙이면 누구나 나중에 git checkout v2.4.0으로 정확히 그 운영 release 자리로 갈 수 있어. 고객이 'v2.3.7에서' bug를 재현했다고 할 때 몇 초 안에 같은 상태를 열 수 있지.
중요한 type은 둘이야. Lightweight tag(git tag v2.4.0)는 metadata 없는 pointer file이고, annotated tag(git tag -a v2.4.0 -m "Release 2.4.0")는 author, 날짜, message, 선택적인 GPG 서명을 가진 온전한 Git object야. 실제 release에는 annotated tag를 써. 서명은 권한 있는 사람이 만든 release인지 확인하고 message는 audit trail이 되며, git describe는 v2.4.0-12-g3f4a5d6처럼 사람이 읽을 수 있는 commit ID를 만들어.
git push --tags는 tag를 remote로 보내. plain git push에는 tag가 포함되지 않는다는 점을 놓치기 쉬워. git config --global push.followTags true를 두면 push하는 commit을 가리키는 tag가 일반 push를 따라가. git tag -d <name>은 로컬 tag를, git push origin --delete <name>은 remote tag를 지워. 다만 remote tag 삭제는 거의 옳지 않아. 이미 fetch한 사람의 머신에는 여전히 남기 때문이야.
GitHub Releases는 annotated tag에 UI를 더해 release note, tarball이나 binary 같은 asset, pre-release 표시를 제공해. CLI에서는 gh release create v2.4.0 --notes "..."로 만들 수 있고 tag를 push한 뒤 web UI를 써도 돼. semantic-release와 Conventional Commits를 결합하면 release가 merge의 자동 결과가 되어 사람이 매번 release note를 쓰지 않아도 돼.