[{"data":1,"prerenderedAt":876},["ShallowReactive",2],{"i-lucide:sun-moon":3,"i-lucide:menu":8,"post-\u002Fblog\u002F2025-11-26-using-git-tags":10,"surround-\u002Fblog\u002F2025-11-26-using-git-tags":863,"i-lucide:arrow-left":874},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 2v2m2.837 12.385a6 6 0 1 1-7.223-7.222c.624-.147.97.66.715 1.248a4 4 0 0 0 5.26 5.259c.589-.255 1.396.09 1.248.715M16 12a4 4 0 0 0-4-4m7-3l-1.256 1.256M20 12h2\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 5h16M4 12h16M4 19h16\"\u002F>",{"id":11,"title":12,"authors":13,"body":14,"date":853,"description":24,"extension":854,"meta":855,"navigation":517,"path":856,"seo":857,"stem":858,"tags":859,"toc":6,"__hash__":862},"blog\u002Fblog\u002F2025-11-26-using-git-tags.md","Using Git Tags: A Practical Guide",[],{"type":15,"value":16,"toc":829},"minimark",[17,21,25,30,33,40,46,50,55,58,84,88,91,115,129,133,136,159,166,170,173,185,188,205,208,222,225,239,243,250,254,271,275,278,294,297,313,317,320,324,327,343,349,357,361,364,382,385,401,404,408,411,439,443,446,460,463,482,486,489,583,587,590,607,610,625,629,632,646,649,666,670,715,719,722,822,825],[18,19,12],"h1",{"id":20},"using-git-tags-a-practical-guide",[22,23,24],"p",{},"Tags in Git are references that point to specific points in your repository's history. They're commonly used to mark release points (v1.0, v2.0, etc.) and provide a way to bookmark important commits. Unlike branches, tags don't change once created — they're fixed pointers to a specific commit.",[26,27,29],"h2",{"id":28},"types-of-tags","Types of Tags",[22,31,32],{},"Git supports two types of tags:",[22,34,35,39],{},[36,37,38],"strong",{},"Lightweight tags"," are simply a pointer to a commit. They're quick to create but contain no additional information.",[22,41,42,45],{},[36,43,44],{},"Annotated tags"," are stored as full objects in the Git database. They contain the tagger's name, email, date, and a tagging message. They can also be signed and verified with GPG. For releases and any tags you want to share, annotated tags are recommended.",[26,47,49],{"id":48},"creating-tags","Creating Tags",[51,52,54],"h3",{"id":53},"creating-a-lightweight-tag","Creating a Lightweight Tag",[22,56,57],{},"To create a lightweight tag on the current commit:",[59,60,65],"pre",{"className":61,"code":62,"language":63,"meta":64,"style":64},"language-bash shiki shiki-themes github-light github-dark-default","git tag v1.0.0\n","bash","",[66,67,68],"code",{"__ignoreMap":64},[69,70,73,77,81],"span",{"class":71,"line":72},"line",1,[69,74,76],{"class":75},"sYRkA","git",[69,78,80],{"class":79},"sNbzA"," tag",[69,82,83],{"class":79}," v1.0.0\n",[51,85,87],{"id":86},"creating-an-annotated-tag","Creating an Annotated Tag",[22,89,90],{},"To create an annotated tag with a message:",[59,92,94],{"className":61,"code":93,"language":63,"meta":64,"style":64},"git tag -a v1.0.0 -m \"Release version 1.0.0\"\n",[66,95,96],{"__ignoreMap":64},[69,97,98,100,102,106,109,112],{"class":71,"line":72},[69,99,76],{"class":75},[69,101,80],{"class":79},[69,103,105],{"class":104},"sPgVT"," -a",[69,107,108],{"class":79}," v1.0.0",[69,110,111],{"class":104}," -m",[69,113,114],{"class":79}," \"Release version 1.0.0\"\n",[22,116,117,118,121,122,125,126,128],{},"The ",[66,119,120],{},"-a"," flag specifies an annotated tag, and ",[66,123,124],{},"-m"," provides the tag message. If you omit ",[66,127,124],{},", Git will open your editor for you to write a message.",[51,130,132],{"id":131},"tagging-a-specific-commit","Tagging a Specific Commit",[22,134,135],{},"If you need to tag a commit that isn't the current HEAD, specify the commit hash:",[59,137,139],{"className":61,"code":138,"language":63,"meta":64,"style":64},"git tag -a v1.0.0 -m \"Release version 1.0.0\" 9fceb02\n",[66,140,141],{"__ignoreMap":64},[69,142,143,145,147,149,151,153,156],{"class":71,"line":72},[69,144,76],{"class":75},[69,146,80],{"class":79},[69,148,105],{"class":104},[69,150,108],{"class":79},[69,152,111],{"class":104},[69,154,155],{"class":79}," \"Release version 1.0.0\"",[69,157,158],{"class":79}," 9fceb02\n",[22,160,161,162,165],{},"You can find commit hashes using ",[66,163,164],{},"git log --oneline",".",[26,167,169],{"id":168},"listing-tags","Listing Tags",[22,171,172],{},"To list all tags in your repository:",[59,174,176],{"className":61,"code":175,"language":63,"meta":64,"style":64},"git tag\n",[66,177,178],{"__ignoreMap":64},[69,179,180,182],{"class":71,"line":72},[69,181,76],{"class":75},[69,183,184],{"class":79}," tag\n",[22,186,187],{},"To filter tags by pattern:",[59,189,191],{"className":61,"code":190,"language":63,"meta":64,"style":64},"git tag -l \"v1.*\"\n",[66,192,193],{"__ignoreMap":64},[69,194,195,197,199,202],{"class":71,"line":72},[69,196,76],{"class":75},[69,198,80],{"class":79},[69,200,201],{"class":104}," -l",[69,203,204],{"class":79}," \"v1.*\"\n",[22,206,207],{},"To see tag details along with commit information:",[59,209,211],{"className":61,"code":210,"language":63,"meta":64,"style":64},"git tag -n\n",[66,212,213],{"__ignoreMap":64},[69,214,215,217,219],{"class":71,"line":72},[69,216,76],{"class":75},[69,218,80],{"class":79},[69,220,221],{"class":104}," -n\n",[22,223,224],{},"For more detailed information about a specific tag:",[59,226,228],{"className":61,"code":227,"language":63,"meta":64,"style":64},"git show v1.0.0\n",[66,229,230],{"__ignoreMap":64},[69,231,232,234,237],{"class":71,"line":72},[69,233,76],{"class":75},[69,235,236],{"class":79}," show",[69,238,83],{"class":79},[26,240,242],{"id":241},"pushing-tags-to-remote","Pushing Tags to Remote",[22,244,245,246,249],{},"By default, ",[66,247,248],{},"git push"," doesn't transfer tags to remote servers. You need to explicitly push them.",[51,251,253],{"id":252},"push-a-single-tag","Push a Single Tag",[59,255,257],{"className":61,"code":256,"language":63,"meta":64,"style":64},"git push origin v1.0.0\n",[66,258,259],{"__ignoreMap":64},[69,260,261,263,266,269],{"class":71,"line":72},[69,262,76],{"class":75},[69,264,265],{"class":79}," push",[69,267,268],{"class":79}," origin",[69,270,83],{"class":79},[51,272,274],{"id":273},"push-all-tags","Push All Tags",[22,276,277],{},"To push all your local tags at once:",[59,279,281],{"className":61,"code":280,"language":63,"meta":64,"style":64},"git push origin --tags\n",[66,282,283],{"__ignoreMap":64},[69,284,285,287,289,291],{"class":71,"line":72},[69,286,76],{"class":75},[69,288,265],{"class":79},[69,290,268],{"class":79},[69,292,293],{"class":104}," --tags\n",[22,295,296],{},"If you only want to push annotated tags (not lightweight tags):",[59,298,300],{"className":61,"code":299,"language":63,"meta":64,"style":64},"git push origin --follow-tags\n",[66,301,302],{"__ignoreMap":64},[69,303,304,306,308,310],{"class":71,"line":72},[69,305,76],{"class":75},[69,307,265],{"class":79},[69,309,268],{"class":79},[69,311,312],{"class":104}," --follow-tags\n",[26,314,316],{"id":315},"deleting-tags","Deleting Tags",[22,318,319],{},"Sometimes you need to remove a tag — perhaps you tagged the wrong commit or made a typo in the tag name.",[51,321,323],{"id":322},"delete-a-local-tag","Delete a Local Tag",[22,325,326],{},"To delete a tag from your local repository:",[59,328,330],{"className":61,"code":329,"language":63,"meta":64,"style":64},"git tag -d v1.0.0\n",[66,331,332],{"__ignoreMap":64},[69,333,334,336,338,341],{"class":71,"line":72},[69,335,76],{"class":75},[69,337,80],{"class":79},[69,339,340],{"class":104}," -d",[69,342,83],{"class":79},[22,344,117,345,348],{},[66,346,347],{},"-d"," flag stands for delete. You'll see output confirming the deletion:",[59,350,355],{"className":351,"code":353,"language":354},[352],"language-text","Deleted tag 'v1.0.0' (was 9fceb02)\n","text",[66,356,353],{"__ignoreMap":64},[51,358,360],{"id":359},"delete-a-remote-tag","Delete a Remote Tag",[22,362,363],{},"Deleting locally doesn't affect the remote. To delete a tag from the remote repository:",[59,365,367],{"className":61,"code":366,"language":63,"meta":64,"style":64},"git push origin --delete v1.0.0\n",[66,368,369],{"__ignoreMap":64},[69,370,371,373,375,377,380],{"class":71,"line":72},[69,372,76],{"class":75},[69,374,265],{"class":79},[69,376,268],{"class":79},[69,378,379],{"class":104}," --delete",[69,381,83],{"class":79},[22,383,384],{},"Alternatively, you can use the older syntax:",[59,386,388],{"className":61,"code":387,"language":63,"meta":64,"style":64},"git push origin :refs\u002Ftags\u002Fv1.0.0\n",[66,389,390],{"__ignoreMap":64},[69,391,392,394,396,398],{"class":71,"line":72},[69,393,76],{"class":75},[69,395,265],{"class":79},[69,397,268],{"class":79},[69,399,400],{"class":79}," :refs\u002Ftags\u002Fv1.0.0\n",[22,402,403],{},"Both commands achieve the same result. The first is more readable; the second pushes an empty reference to the remote tag, effectively deleting it.",[51,405,407],{"id":406},"delete-both-local-and-remote","Delete Both Local and Remote",[22,409,410],{},"To completely remove a tag, run both commands:",[59,412,414],{"className":61,"code":413,"language":63,"meta":64,"style":64},"git tag -d v1.0.0\ngit push origin --delete v1.0.0\n",[66,415,416,426],{"__ignoreMap":64},[69,417,418,420,422,424],{"class":71,"line":72},[69,419,76],{"class":75},[69,421,80],{"class":79},[69,423,340],{"class":104},[69,425,83],{"class":79},[69,427,429,431,433,435,437],{"class":71,"line":428},2,[69,430,76],{"class":75},[69,432,265],{"class":79},[69,434,268],{"class":79},[69,436,379],{"class":104},[69,438,83],{"class":79},[26,440,442],{"id":441},"checking-out-tags","Checking Out Tags",[22,444,445],{},"To view the code at a specific tag, you can check it out:",[59,447,449],{"className":61,"code":448,"language":63,"meta":64,"style":64},"git checkout v1.0.0\n",[66,450,451],{"__ignoreMap":64},[69,452,453,455,458],{"class":71,"line":72},[69,454,76],{"class":75},[69,456,457],{"class":79}," checkout",[69,459,83],{"class":79},[22,461,462],{},"This puts you in a \"detached HEAD\" state — you're not on any branch. If you want to make changes based on a tag, create a new branch:",[59,464,466],{"className":61,"code":465,"language":63,"meta":64,"style":64},"git checkout -b release-1.0-hotfix v1.0.0\n",[66,467,468],{"__ignoreMap":64},[69,469,470,472,474,477,480],{"class":71,"line":72},[69,471,76],{"class":75},[69,473,457],{"class":79},[69,475,476],{"class":104}," -b",[69,478,479],{"class":79}," release-1.0-hotfix",[69,481,83],{"class":79},[26,483,485],{"id":484},"renaming-a-tag","Renaming a Tag",[22,487,488],{},"Git doesn't have a direct rename command for tags. Instead, you create a new tag pointing to the same commit, then delete the old one:",[59,490,492],{"className":61,"code":491,"language":63,"meta":64,"style":64},"# Create new tag pointing to the same commit as old tag\ngit tag new-tag old-tag\n\n# Delete old tag locally\ngit tag -d old-tag\n\n# Delete old tag from remote\ngit push origin --delete old-tag\n\n# Push new tag to remote\ngit push origin new-tag\n",[66,493,494,500,512,519,525,536,541,547,560,565,571],{"__ignoreMap":64},[69,495,496],{"class":71,"line":72},[69,497,499],{"class":498},"sPyeA","# Create new tag pointing to the same commit as old tag\n",[69,501,502,504,506,509],{"class":71,"line":428},[69,503,76],{"class":75},[69,505,80],{"class":79},[69,507,508],{"class":79}," new-tag",[69,510,511],{"class":79}," old-tag\n",[69,513,515],{"class":71,"line":514},3,[69,516,518],{"emptyLinePlaceholder":517},true,"\n",[69,520,522],{"class":71,"line":521},4,[69,523,524],{"class":498},"# Delete old tag locally\n",[69,526,528,530,532,534],{"class":71,"line":527},5,[69,529,76],{"class":75},[69,531,80],{"class":79},[69,533,340],{"class":104},[69,535,511],{"class":79},[69,537,539],{"class":71,"line":538},6,[69,540,518],{"emptyLinePlaceholder":517},[69,542,544],{"class":71,"line":543},7,[69,545,546],{"class":498},"# Delete old tag from remote\n",[69,548,550,552,554,556,558],{"class":71,"line":549},8,[69,551,76],{"class":75},[69,553,265],{"class":79},[69,555,268],{"class":79},[69,557,379],{"class":104},[69,559,511],{"class":79},[69,561,563],{"class":71,"line":562},9,[69,564,518],{"emptyLinePlaceholder":517},[69,566,568],{"class":71,"line":567},10,[69,569,570],{"class":498},"# Push new tag to remote\n",[69,572,574,576,578,580],{"class":71,"line":573},11,[69,575,76],{"class":75},[69,577,265],{"class":79},[69,579,268],{"class":79},[69,581,582],{"class":79}," new-tag\n",[26,584,586],{"id":585},"comparing-tags","Comparing Tags",[22,588,589],{},"To see what changed between two tags:",[59,591,593],{"className":61,"code":592,"language":63,"meta":64,"style":64},"git diff v1.0.0 v2.0.0\n",[66,594,595],{"__ignoreMap":64},[69,596,597,599,602,604],{"class":71,"line":72},[69,598,76],{"class":75},[69,600,601],{"class":79}," diff",[69,603,108],{"class":79},[69,605,606],{"class":79}," v2.0.0\n",[22,608,609],{},"To see the commits between two tags:",[59,611,613],{"className":61,"code":612,"language":63,"meta":64,"style":64},"git log v1.0.0..v2.0.0\n",[66,614,615],{"__ignoreMap":64},[69,616,617,619,622],{"class":71,"line":72},[69,618,76],{"class":75},[69,620,621],{"class":79}," log",[69,623,624],{"class":79}," v1.0.0..v2.0.0\n",[26,626,628],{"id":627},"fetching-remote-tags","Fetching Remote Tags",[22,630,631],{},"To fetch all tags from a remote:",[59,633,635],{"className":61,"code":634,"language":63,"meta":64,"style":64},"git fetch --tags\n",[66,636,637],{"__ignoreMap":64},[69,638,639,641,644],{"class":71,"line":72},[69,640,76],{"class":75},[69,642,643],{"class":79}," fetch",[69,645,293],{"class":104},[22,647,648],{},"If remote tags have been deleted and you want to sync your local tags:",[59,650,652],{"className":61,"code":651,"language":63,"meta":64,"style":64},"git fetch --prune --prune-tags\n",[66,653,654],{"__ignoreMap":64},[69,655,656,658,660,663],{"class":71,"line":72},[69,657,76],{"class":75},[69,659,643],{"class":79},[69,661,662],{"class":104}," --prune",[69,664,665],{"class":104}," --prune-tags\n",[26,667,669],{"id":668},"best-practices","Best Practices",[671,672,673,680,697,703,709],"ol",{},[674,675,676,679],"li",{},[36,677,678],{},"Use annotated tags for releases"," — they contain metadata that helps with tracking who created the tag and when.",[674,681,682,685,686,689,690,689,693,696],{},[36,683,684],{},"Follow semantic versioning"," — use a consistent naming scheme like ",[66,687,688],{},"v1.0.0",", ",[66,691,692],{},"v1.0.1",[66,694,695],{},"v1.1.0"," to make versions meaningful.",[674,698,699,702],{},[36,700,701],{},"Write meaningful tag messages"," — document what's included in the release.",[674,704,705,708],{},[36,706,707],{},"Don't move tags after pushing"," — if a tag has been pushed to a shared remote, treat it as immutable. Create a new tag instead.",[674,710,711,714],{},[36,712,713],{},"Use lightweight tags for temporary or private markers"," — they're perfect for bookmarking commits during development.",[26,716,718],{"id":717},"summary","Summary",[22,720,721],{},"Git tags are a simple but powerful feature for marking important points in your project's history. The key commands to remember:",[723,724,725,738],"table",{},[726,727,728],"thead",{},[729,730,731,735],"tr",{},[732,733,734],"th",{},"Operation",[732,736,737],{},"Command",[739,740,741,752,762,772,782,792,802,812],"tbody",{},[729,742,743,747],{},[744,745,746],"td",{},"Create annotated tag",[744,748,749],{},[66,750,751],{},"git tag -a v1.0.0 -m \"message\"",[729,753,754,757],{},[744,755,756],{},"Create lightweight tag",[744,758,759],{},[66,760,761],{},"git tag v1.0.0",[729,763,764,767],{},[744,765,766],{},"List tags",[744,768,769],{},[66,770,771],{},"git tag",[729,773,774,777],{},[744,775,776],{},"Push single tag",[744,778,779],{},[66,780,781],{},"git push origin v1.0.0",[729,783,784,787],{},[744,785,786],{},"Push all tags",[744,788,789],{},[66,790,791],{},"git push origin --tags",[729,793,794,797],{},[744,795,796],{},"Delete local tag",[744,798,799],{},[66,800,801],{},"git tag -d v1.0.0",[729,803,804,807],{},[744,805,806],{},"Delete remote tag",[744,808,809],{},[66,810,811],{},"git push origin --delete v1.0.0",[729,813,814,817],{},[744,815,816],{},"Checkout tag",[744,818,819],{},[66,820,821],{},"git checkout v1.0.0",[22,823,824],{},"With these commands in your toolkit, you'll be able to effectively manage releases and important milestones in your Git repositories.",[826,827,828],"style",{},"html pre.shiki code .sYRkA, html code.shiki .sYRkA{--shiki-default:#6F42C1;--shiki-dark:#FFA657}html pre.shiki code .sNbzA, html code.shiki .sNbzA{--shiki-default:#032F62;--shiki-dark:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sPgVT, html code.shiki .sPgVT{--shiki-default:#005CC5;--shiki-dark:#79C0FF}html pre.shiki code .sPyeA, html code.shiki .sPyeA{--shiki-default:#6A737D;--shiki-dark:#8B949E}",{"title":64,"searchDepth":514,"depth":514,"links":830},[831,832,837,838,842,847,848,849,850,851,852],{"id":28,"depth":428,"text":29},{"id":48,"depth":428,"text":49,"children":833},[834,835,836],{"id":53,"depth":514,"text":54},{"id":86,"depth":514,"text":87},{"id":131,"depth":514,"text":132},{"id":168,"depth":428,"text":169},{"id":241,"depth":428,"text":242,"children":839},[840,841],{"id":252,"depth":514,"text":253},{"id":273,"depth":514,"text":274},{"id":315,"depth":428,"text":316,"children":843},[844,845,846],{"id":322,"depth":514,"text":323},{"id":359,"depth":514,"text":360},{"id":406,"depth":514,"text":407},{"id":441,"depth":428,"text":442},{"id":484,"depth":428,"text":485},{"id":585,"depth":428,"text":586},{"id":627,"depth":428,"text":628},{"id":668,"depth":428,"text":669},{"id":717,"depth":428,"text":718},"2025-01-15","md",{},"\u002Fblog\u002F2025-11-26-using-git-tags",{"title":12,"description":24},"blog\u002F2025-11-26-using-git-tags",[76,860,861],"version-control","development","-SU_4kGsdmyxnKloEvYRWFW6FbSNNjUx7tJ2KyIhhjA",[864,869],{"title":865,"path":866,"stem":867,"date":868,"children":-1},"Automating Tasks with systemd timers","\u002Fblog\u002F2024-05-15-using-systemd-timers","blog\u002F2024-05-15-using-systemd-timers","2024-05-15",{"title":870,"path":871,"stem":872,"date":873,"children":-1},"Signing git commits with SSH keys","\u002Fblog\u002F2025-04-23-signing-git-commits-with-ssh-keys","blog\u002F2025-04-23-signing-git-commits-with-ssh-keys","2025-04-23",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":875},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"m12 19l-7-7l7-7m7 7H5\"\u002F>",1783616164565]