1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

git branchの退避失敗を&&が止めない、空の$()で起きる落とし穴

1
Posted at

📝 この記事は forge.workstyle.tech に掲載した記事の転載です。

複数のAIセッションが同じ作業ツリーを使い、ステージ済みの変更が残っていました。変更をブランチに退避してからgit reset --hardする手順は、退避に失敗しても先へ進む場合がありました。クォートしていない空のコマンド置換で引数が消え、git branchが成功することが原因です。

使い捨てのリポジトリで気づいた

実行する前に、セッションの1つが、この手順を使い捨てのリポジトリで一度走らせました。そこで、退避先を作る部分が失敗しても、git branch自体は成功する場合があると気づきました。

短くすると、再現は次のとおりです。

$ git branch orphan/x  $(false)    # exit=0  HEAD にブランチができる → && を通過
$ git branch orphan/x "$(false)"   # fatal: Not a valid object name: '' → 止まる(exit 128)

$(false)の結果は空です。クォートしていない場合、その空の結果は単語分割で引数そのものが消えます。コマンドに渡るのはgit branch orphan/xです。

この形は、開始点を省略したgit branchとして成立します。HEADを指すブランチができ、終了コードは0になります。だから&&は先へ進み、後ろのreset --hardが実行されます。

退避先が作られていないのに、退避が成功したかのように見える。実際の手順では、変更を退避できていないまま作業ツリーの変更が消える寸前でした。

一方、"$(false)"とクォートすると、空の引数が残ります。Gitは空の開始点を受け取り、エラーで止まります。ここでは終了コードが128なので、&&の先へ進みません。

省略できる引数が、別の意味を持つ

危ないのは、値が消えたあとも、コマンドが「引数を省略した形」として成立してしまうことです。

今回のgit branchは、開始点を省略しても成功します。見た目には同じコマンドでも、意図した退避先のコミットを使う形とは違う動作になりました。

同じ種類の注意が必要な例として、git checkout -B、git reset、rm -rf $DIR/があります。引数を省略しても別の意味で成立するコマンドに、空になるかもしれない値をそのまま埋め込むと、失敗が終了コードに現れないことがあります。

&&は、前のコマンドが失敗したときに後ろへ進まないためのものです。ただし、失敗がコマンドの終了コードに現れなければ、止まるきっかけがありません。エラーが表示されるかどうかだけでは、手順が止まるかは分かりません。

なぜ見落としたのか

この手順を読んで承認したセッションは3つありました。全員が穴を見落としました。そのうちの1つは、「&&でつないであるから、失敗したら止まる」と書いて同意していました。

どのセッションも、コマンドの形を見て「退避が失敗すれば終了コードも失敗になる」と頭の中で補っていたのだと思います。けれど、実際にはコマンド置換の結果が空になり、引数が消えた後のgit branchが成功していました。読むだけでは、その変化を確かめられませんでした。

気づけたのは、実行前に使い捨てのリポジトリで一度走らせたからです。見た目のつながりだけで判断せず、失敗する入力を与えて、コマンドがどんな引数を受け取るか確かめる必要がありました。

まとめ

  • コマンド置換はクォートする
  • 空の値が引数として残ることを確認する
  • 退避できたことを確かめてからリセットする
  • 失敗する入力を使い捨てのリポジトリで実行し、後続処理まで進まないか確かめる

関連記事


元記事: https://forge.workstyle.tech/blog/unquoted-command-substitution-guard/?utm_source=qiita&utm_medium=crosspost&utm_campaign=unquoted-command-substitution-guard

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?