[git 2.43リリース] git revertを2回するとコミットメッセージがReapplyと表示される
こんにちは、M-Yamashitaです。
この記事は、Money Forward Engineering 1 Advent Calendar 2023 11日目の投稿です。前回はOno Toshikiさんの記事でした。
今回の記事は、git 2.43リリースに含まれていたgit revert
コマンドのアップデートの話です。
公式ドキュメントでは変更概要が軽く触れてある程度でしたが、私にとっては結構ありがたい変更と感じました。そのため、どう変わったのかを確認するとともに、前バージョンを跨いだ場合の動作パターンを確認してみました。
この記事で伝えたいこと
-
git revert
コマンドで2回revertすると、コミットメッセージがReapplyに変わる - 過去のGitを使って対象コミットを1回revertしていると、最新gitの
git revert
でコミットメッセージがReapplyに変わる - 過去のGitを使って対象コミットを2回revertしていると、最新gitの
git revert
でもコミットメッセージがRevert Revertとなる。Reapplyにならない
git 2.43リリースによるgit revertコマンドの変更
git 2.43リリース記事から引用します。
Beginning in Git 2.43, Git will realize when it’s about to perform a double-revert, and instead produce the much more pleasing message:
$ git revert --no-edit HEAD >/dev/null $ git revert --no-edit HEAD >/dev/null $ git log --oneline a300922 (HEAD -> main) Reapply "fix bug" 0050730 Revert "fix bug" b290810 fix bug [...]
説明にあるように、2回revertをすると、Reapplyのprefixがコミットメッセージに追加されるようです。
ちなみにここからさらにrevertしたとき、つまり3回revertしたときの挙動も記事にあります。
If you decide to revert for a third time, Git will produce a commit message like Revert "Reapply "fix bug", causing the length of the commit message to grow at a much more reasonable rate over many reverts.
3回Revertすると、Reapplyメッセージに対して、Revertのprefixが追加されます。
実際にやってみる
今回は、適当なファイル作成のコミット1回と、それに対するrevertを4回実施しました。
❯ git log --oneline
0f03ae1 (HEAD -> main) Reapply "Reapply "Create test.txt""
2358c19 Revert "Reapply "Create test.txt""
0eae994 Reapply "Create test.txt"
9410b2e Revert "Create test.txt"
36ef48b Create test.txt
記事通り、2回目のgit revert
ではReapplyのコミットメッセージとなっています。また3回目以降はRevertがつき、それがReapplyに変わるようになっています。
gitバージョンをまたがったrevertの場合
git 2.43ではReapplyになることが分かりました。それではgitのバージョンをまたがったrevertの場合を確認してみます。
git 2.43未満のgitを使って、revertを1回実行していた場合と、revertを2回実行していた場合を比較します。
ここで、"git 2.43未満のgit"については、今回は2.39.3のgitで試します。
❯ git version
git version 2.39.3 (Apple Git-145)
git 2.43未満でgit revertを1回実施
以下手順で確認します。
- git 2.43未満のgitを使用
- 適当なコミットを1回実施し、
git revert
を1回実施 - git 2.43のgitを使用
- 2のrevertコミットに対し、2回revertする
結果は以下のとおりです。最新gitでgit revert
したe4f7791
のコミットメッセージを見ると、Reapplyのメッセージとなっていることが分かります。
❯ git log --oneline
2645012 (HEAD -> main) Revert "Reapply "Create test.txt""
e4f7791 Reapply "Create test.txt"
5d57d73 Revert "Create test.txt"
cb03863 Create test.txt
git 2.43未満でgit revertを2回実施
以下手順で確認します。
- git 2.43未満のgitを使用
- 適当なコミットを1回実施し、
git revert
を2回実施 - git 2.43のgitを使用
- 2のrevertコミットに対し、2回revertする
結果は以下のとおりです。過去のgitでgit revert
を2回実施後、最新gitでgit revert
した1b96691
のコミットでは、ReapplyとならずRevertコメントが続く事がわかります。
❯ git log --oneline
65dd2eb (HEAD -> main) Revert "Revert "Revert "Revert "Create test.txt""""
1b96691 Revert "Revert "Revert "Create test.txt"""
6596121 Revert "Revert "Create test.txt""
089644f Revert "Create test.txt"
cb03863 Create test.txt
考察
なぜ、2.43未満のgitを使って2回revertを実施していると、Reapplyとはならず、Revertが続くのでしょうか。
この仕様は、2.43リリース時のgitのコードで表されています。
if (command == TODO_REVERT) {
const char *orig_subject;
base = commit;
base_label = msg.label;
next = parent;
next_label = msg.parent_label;
if (opts->commit_use_reference) {
strbuf_addstr(&msgbuf,
"# *** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
} else if (skip_prefix(msg.subject, "Revert \"", &orig_subject) &&
/*
* We don't touch pre-existing repeated reverts, because
* theoretically these can be nested arbitrarily deeply,
* thus requiring excessive complexity to deal with.
*/
!starts_with(orig_subject, "Revert \"")) {
strbuf_addstr(&msgbuf, "Reapply \"");
strbuf_addstr(&msgbuf, orig_subject);
} else {
私はCのコードの知識をあまり持っていませんが、このelseif
にて以下条件を満たした場合に、コミットメッセージがReapplyに変わるようです。
- コミットメッセージが"Revert ""で始まること
- 残りのコミットメッセージが"Revert ""で始まらない
つまり厳密には、gitのバージョンに関わらず、コミットメッセージによって挙動が異なるようです。
今回の場合、2.43未満のgitを使ってgit revert
を2回実施したため、2つ目の条件に引っかかりませんでした。そのため、Revertのコミットメッセージが追加されたと思われます。
おわりに
今回はgit 2.43リリースに含まれていたgit revert
の話をしました。
Reapplyとなったことでコミット内容が結構わかりやすくなったのではないかなと思います。
この記事が誰かのお役に立てれば幸いです。
Discussion