Skip to content

tag: keep the message file in case ref transaction fails

Kristoffer Haugsbakk git 3 versions – In review

Get series with b4
b4 am [email protected]

Versions newest first · linked by author and title

  1. v3 Latest3 patches 1 replyIn review
  2. v23 patches 2 repliesSuperseded
  3. v13 patches 11 repliesSuperseded

Patches in v3 No applies recorded yet

#Subject and filesSizeRepliesApplied
1/3doc: tag: document `TAG_EDITMSG`Documentation/git-tag.txt+10 -00 replies
2/3t/t7004-tag: add regression test for successful tag creationt/t7004-tag.sh+9 -00 replies
3/3tag: keep the message file in case ref transaction failsbuiltin/tag.c t/t7004-tag.sh+25 -90 replies

Reviews trailers per patch

No Reviewed-by, Acked-by or Tested-by trailers for v3 yet.

Read the v3 thread

Cover letter [PATCH v3 0/3] tag: keep the message file in case ref transaction fails

§ Introduction (v3)

The first part of this material is the same as v1 and v2; skip to “Based on” and onwards for the new things.

Cheers.

―

The ref transaction can fail after the message has been written using the editor. The ref transaction is attempted after the message file (TAG_EDITMSG) has been unlinked, so there is no backup tag message file to retry the command.[1]

This is unfortunate if someone has written more than e.g. “v1.99.4” in the editor. (I don’t know if people write long tag messages in practice.)

Hold on to the tag message file until after the ref transaction in order to preserve the backup.

† 1: On commit 91428f078b (The eighteenth batch, 2023-05-10)

§ Reproduction script

```
cd /tmp
dir=$(mktemp -d)
cd $dir
git init
git commit --allow-empty -mInit
git tag release/v1
# Fails
git tag -a release
```

Error message:

```
fatal: cannot lock ref 'refs/tags/release': 'refs/tags/release/v1' exists; cannot create 'refs/tags/release'
```

Better error message and behavior:

```
The tag message has been left in .git/TAG_EDITMSG
fatal: cannot lock ref 'refs/tags/release': 'refs/tags/release/v1' exists; cannot create 'refs/tags/release'
```

§ Alternatives considered

My first thought was to find a way to “dry run” the ref update before opening the editor (the edge case of the ref update command succeeding the first time but not the second *real* time seemed incredibly unlikely to happen by happenstance, so I saw no reason to consider that). However that seemed like it would involve more code and conditionals, and I don’t know if the dry-run mode is even supported.

A benefit of this alternative approach would be to error out immediately instead of opening the editor. But trying to create a tag which collides with an existing “namespace” seems very unlikely to happen in practice.[2] Losing a file is much worse than being inconvenienced to retry the command, so I decided to just focus on the former problem.

Most importantly though this approach was within my ability to implement.

† 2: Just observe my “Reproduction script”: one tries to create release after
someone else made release/v1. But what is just “release”? What follows (next version) that? But why am I arguing against my change…

§ Based on (base commit)

v2.40.1

§ Changes compared to the previous round

• Replace ! test_path_exists with test_path_is_missing

Other:

• Drop “Cc” trailers (but keep Cc list)

§ Patches

Same number and order as last round.

1. Document TAG_EDITMSG
2. Test successful tag creation
• New: Use test_path_is_missing
3. The main change plus a regression test

Kristoffer Haugsbakk (3):
doc: tag: document TAG_EDITMSG
t/t7004-tag: add regression test for successful tag creation
tag: keep the message file in case ref transaction fails

 Documentation/git-tag.txt | 10 ++++++++++
 builtin/tag.c             | 24 +++++++++++++++---------
 t/t7004-tag.sh            | 19 +++++++++++++++++++
 3 files changed, 44 insertions(+), 9 deletions(-)

Range-diff against v2:
1: 0e0e592853d ! 1: 882008e32a4 doc: tag: document TAG_EDITMSG
@@ Commit message
in case of error.

- Cc: Jeff King <[email protected]>

2: aabeb4568ee ! 2: d1490b8f0b7 t/t7004-tag: add regression test for successful tag creation

    @@ Commit message
     
         Signed-off-by: Kristoffer Haugsbakk <[email protected]>
     
      ## t/t7004-tag.sh ##
     @@ t/t7004-tag.sh: test_expect_success 'Does --[no-]contains stop at commits? Yes!' '
      	test_cmp expected actual
    @@ t/t7004-tag.sh: test_expect_success 'Does --[no-]contains stop at commits? Yes!'
     +	echo Message >.git/TAG_EDITMSG
     +	EOF
     +	GIT_EDITOR=./fakeeditor git tag -a foo &&
    -+	! test_path_exists .git/TAG_EDITMSG
    ++	test_path_is_missing .git/TAG_EDITMSG
     +'
     +
      test_done

3: e67b6416b7e ! 3: 81bca0673d8 tag: keep the message file in case ref transaction fails
@@ Commit message
Hold on to the message file for a little longer so that it is not unlinked before the fatal error occurs.

- Cc: Jeff King <[email protected]>

@@ builtin/tag.c: int cmd_tag(int argc, const char **argv, const char *prefix)

## t/t7004-tag.sh ##
@@ t/t7004-tag.sh: test_expect_success 'If tag is created then tag message file is unlinked' '
- ! test_path_exists .git/TAG_EDITMSG
+ test_path_is_missing .git/TAG_EDITMSG
'

+test_expect_success 'If tag cannot be created then tag message file is not unlinked' '

Signature · 1 line
2.40.1