【git tag】プッシュしたtag名を削除・変更してはいけない理由〜manコマンドで読めるgitメンテナの怒り〜

# 一度プッシュしたtagは、名前変更・削除してはならない
プッシュしたtag名を削除・変更してはいけない理由は、git tagのmanコマンドの中で説明されている。

**manコマンドの内容は、コマンドの使い方を淡々と説明している印象**があり、今まであまり読んでこなかった。
しかしgit tagのmanコマンドでは**とても人間味のある文章**が書かれていた。

感情部分だけ要約すると、
**「tag名を変更するのは馬鹿げている！！絶対にするなよ！！
それでもやりたいって？じゃあこうやれ！馬鹿げたやり方だけどな！！
それは面倒だって？やるならこれしかないんだよ！（怒）」**
という筆者の熱い思いが文章で綴られている。

それでは見ていこう。

# manコマンドをみてみる
下記コマンドで該当の記述を読むことが出来る

```
man git-tag
```

web上で見たい場合は[こちら](https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-tag.html)でも。

## 原文
該当の記述はこちら
> On Re-tagging
       What should you do when you tag a wrong commit and you would want to re-tag?
       If you never pushed anything out, just re-tag it. Use "-f" to replace the old one. And you're done.
       But if you have pushed things out (or others could just read your repository directly), then others will have already seen the old tag. In that case you can do one of two things:
        1. The sane thing. Just admit you screwed up, and use a different name. Others have already seen one tag-name, and if you keep the same name, you may be in the situation that two people both have
           "version X", but they actually have different "X"'s. So just call it "X.1" and be done with it.
        2. The insane thing. You really want to call the new version "X" too, even though others have already seen the old one. So just use git tag -f again, as if you hadn't already published the old one.
       However, Git does not (and it should not) change tags behind users back. So if somebody already got the old tag, doing a git pull on your tree shouldn't just make them overwrite the old one.
       If somebody got a release tag from you, you cannot just change the tag for them by updating your own one. This is a big security issue, in that people MUST be able to trust their tag-names. If you
       really want to do the insane thing, you need to just fess up to it, and tell people that you messed up. You can do that by making a very public announcement saying:
           Ok, I messed up, and I pushed out an earlier version tagged as X. I
           then fixed something, and retagged the *fixed* tree as X again.
           If you got the wrong tag, and want the new one, please delete
           the old one and fetch the new one by doing:
                   git tag -d X
                   git fetch origin tag X
           to get my updated tag.
           You can test which tag you have by doing
                   git rev-parse X
           which should return 0123456789abcdef.. if you have the new version.
           Sorry for the inconvenience.
       Does this seem a bit complicated? It should be. There is no way that it would be correct to just "fix" it automatically. People need to know that their tags might have been changed.

# 意訳
怒りの部分が分かるように意訳していく。
## pushしていないtagは変更して良い
`-f`オプションを使って名前を付け替えるだけで良い。

## pushしたけどtag名を変更したくなった場合
push済みの場合、他の作業者がpushしたtagをみている可能性がある。
その場合出来る方法は2つある。

### 1.健全なやり方(sane thing)
まずは**やらかしたことを認めろ。**そして**違うタグ名を使え。**
（わざわざ「健全な」とつけたり、やらかしたことを最初に認めさせたりと**怒りが沸き始めている**）
もし同じ名前で新しい内容でtagを作った場合、同じ`version X`という名前なのに、人によって違う内容を指している状態ができてしまう。
あなたは`version X.1`など別の名前を使いなさい。

### 2.狂気的なやり方(insane thing)
(もう**ワードが強い。怒りに溢れている**)
あなたがどーしても同じtag名で新しい内容を指したいのであれば、
それも既に他の作業者がpushしたtagを既にみているのにどーしてもやりたいのであれば、
**`-f`オプションでforce push**すれば良い。まるでまだtagをpushしていなかったかのようにね。
(**やっても良いと言う割に、節々に嫌味っぽい怒り**を感じる)
#### tagを変更したとしても、他の作業者のtagがあなたの更新で上書かれるわけではない
しかし、Gitはユーザーの見えないところでtagを変更することはしないし、するべきではない。
すなわち、**古いtagが既にある状態で`git pull`をしても、新しいtagが上書かれることはない。**
**同じレポジトリの作業者がtag名を「必ず」信頼出来る状態**でなければならない。
(manコマンドらしく、知るべき前提情報を淡々と説明してある)

### それでも狂気的なやり方をやりたい場合
まず**大騒ぎ**して、他の作業者に**自分がやらかしたことを報告**し、下記の内容をレポジトリの**全ての作業者に大々的に告知**しなければならない。
(**罪を償え！**と言われている気がしてならない)
#### 告知すべき内容
私はやらかしました。
tag Xを新たなバージョンとしてpushしました。
もし間違った(古い)タグを取得してしまい更新する必要がある方は、古いtagを削除し、新しいtagをfetchしてください。
コマンドは下記です。

```
git tag -d X
git fetch origin tag X
```

下記コマンドで最新のtagを取得しているか確認することができます。

```
git rev-parse X
```

正しければ`0123456789abcdef`が表示されます。
ご不便をおかけし申し訳ありません。

# やり方が複雑だって？やるべきだ！
自動的に「修正」する方法なんて他にない。
（「修正」が強調されているのは、**やっていることが修正ではなく「狂気な所業」なので、修正というものばからしい**、のニュアンスが入っている）
他の作業者は**自分が触っているtagが変更されている可能性があるなら知らされるべき**だ。

# manコマンドから感じられた怒りと要点まとめ
とりあえず、**remoteのtagを変更したらgitメンテナがめっちゃ怒る**ことは感じられたと思う。
**git tagでのベストプラクティス**は、

 - tagは**1度pushしたら変更はしない**
 - どうしても変えたくなったら**別のtag名を新たに付与**する

こと。
**理由**は

 - gitの思想的に、**tag名によってtagが一意に決定され存在が保証されるべき**
 - tag変更後他の作業者が**pullをしても、tag名の上書きは行われない**
 - 上書きを行いたかったら、**全ての作業者が取得済みのtagを消してfetchし直す必要**がある

ことである。

もし**「tagを変えたい」**とチーム内で相談されたら、
**「やれないことはないけどめんどくさいよ。
あと、gitメンテナがめっちゃ怒るよ」**
と伝えるようにしよう。

# このmanコマンドを書いた人は何者？
この人間味を溢れる記述を書いたのは、なんと**日本人エンジニア**。
お名前は**濱野純**さん。
該当のコミットは[こちら](https://github.com/git/git/commit/4853534e180c237331cb8395fe87ff6e09bbcf21)からgithub上で見れる。

濱野純さんは**Linuxの生みの親リーナス・トーバルズから信頼**された**Gitメンテナ**であり、**Google**のエンジニアである。
 
>濱野 純 (はまの じゅん、英語: Junio C Hamano) は、カリフォルニア在住[1]の日本のソフトウェア工学者（英語版）である。現在はGoogleに勤務している[2]。最初のリリースから2ヶ月後の2005年7月26日からGitのメンテナであることで知られている[3][4]。リーナス・トーバルズは2012年に、Gitが彼にとっての最大の成功の1つとなったのは、濱野がGitの開発において優秀な開発者であることによると認識しており、メンテナとして彼を信頼していると述べた[5]。

引用:wikipediaより https://ja.wikipedia.org/wiki/%E6%BF%B1%E9%87%8E%E7%B4%94

# まとめ
gitメンテナの怒りを買わないように、**tagは変えずに新しく**作ろう！

# 関連書籍
[GitHub実践入門](https://amzn.to/2DEdyvG)
新卒エンジニア向け課題図書。
結局**gitで難しいのはコマンドの扱い方ではなく、git上での他の作業者との円滑なやり取り**だったりする。
gitを使ったチームでの開発フローに関して、何かしら読んでから現場に入ってもらえるとスムーズに感じる。