@@ -137,6 +137,36 @@ function gitTagExists(tagName) {
137137 return result . status === 0 ;
138138}
139139
140+ function gitRefCommit ( ref ) {
141+ const result = spawnSync ( "git" , [ "rev-parse" , "--verify" , `${ ref } ^{}` ] , {
142+ cwd : root ,
143+ encoding : "utf-8" ,
144+ shell : false ,
145+ } ) ;
146+ if ( result . status !== 0 ) {
147+ fail ( `Unable to resolve git ref: ${ ref } ` ) ;
148+ }
149+ return result . stdout . trim ( ) ;
150+ }
151+
152+ function canReuseExistingTag ( tagName ) {
153+ if ( gitRefCommit ( tagName ) === gitRefCommit ( "HEAD" ) ) {
154+ return true ;
155+ }
156+
157+ const result = spawnSync ( "git" , [ "diff" , "--name-only" , `${ tagName } ^{}` , "HEAD" ] , {
158+ cwd : root ,
159+ encoding : "utf-8" ,
160+ shell : false ,
161+ } ) ;
162+ if ( result . status !== 0 ) {
163+ fail ( `Unable to compare existing tag ${ tagName } with HEAD.` ) ;
164+ }
165+
166+ const changedPaths = result . stdout . split ( "\n" ) . filter ( Boolean ) ;
167+ return changedPaths . length > 0 && changedPaths . every ( ( filePath ) => filePath === "scripts/prepare-package.js" ) ;
168+ }
169+
140170// ── Parse args ───────────────────────────────────────────────────────────────
141171
142172const args = process . argv . slice ( 2 ) ;
@@ -404,12 +434,16 @@ if (!dryRun) {
404434 }
405435
406436 if ( gitTagExists ( tagName ) ) {
407- fail ( `Git tag already exists: ${ tagName } ` ) ;
437+ if ( ! canReuseExistingTag ( tagName ) ) {
438+ fail ( `Git tag already exists and does not match the current release contents: ${ tagName } ` ) ;
439+ }
440+ log ( ` Reusing existing tag ${ tagName } ` ) ;
441+ } else {
442+ run ( "git" , [ "tag" , tagName ] , {
443+ label : `git tag ${ tagName } ` ,
444+ } ) ;
445+ ok ( `Created tag ${ tagName } ` ) ;
408446 }
409- run ( "git" , [ "tag" , tagName ] , {
410- label : `git tag ${ tagName } ` ,
411- } ) ;
412- ok ( `Created tag ${ tagName } ` ) ;
413447} else {
414448 log ( "\n (dry-run) git add + commit + tag" ) ;
415449}
0 commit comments