0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[origin/私][9章]force-pushしてはいけない日がある

0
Last updated at Posted at 2026-06-26

目次

──「心をgitで管理する世界」の物語で、過去を編み直す自由はどこまで許されるのか

8章へ

〈ショートストーリー〉

私は昔から、過去を整えるのがうまかった。

git rebase -i。自分の履歴を開いて、並べ直す。恥ずかしい寄り道をsquashして、一つにまとめる。順番を入れ替えて、行き当たりばったりだった日々を、まるで最初から一本の筋が通っていたように見せる。

嘘ではない。どのcommitも本当にあったことだ。ただ、散らかっていたのを片づけるだけ。少しだけ自分をよく見せるだけ。


新しい恋人に会う、前の夜だった。

私は自分の枝をrebaseした。情けない夜更かしのcommitを目立たない場所へ送る。長すぎた回り道を一つの「いろいろあって」にsquashする。散らかった二十代を清潔な一本に編み直した。

少し背伸びだったと思う。でも、誰にも見せていない私だけの枝だ。pushもしていない。だから、これは許される。ただのささやかな自己演出。

恋人は、整えた私の話を聞いて、笑った。「あなた、ちゃんと考えて生きてきたんだね」。

照れくさかった。本当は、もっとぐちゃぐちゃだったのに。それでも、その夜の私の手つきは、誰も傷つけなかった。整えたのは、私だけの過去だったから。


恋人は、妻になった。

二人の履歴ができた。私だけの枝ではない。共有した二人の枝。旅行も、喧嘩も、引っ越しも、二人でcommitして、二人でpushした。同じログを二人で持っている。

結婚してすぐの頃。私は、妻を旅行に連れて行こうとして、盛大に背伸びをした。

身の丈に合わない、洒落た宿を予約した。完璧な旅程を組んだ。ところが当日、電車を乗り間違え、雨に降られ、自慢の宿の夕食は、私には立派すぎて味も分からなかった。私は一日中、「ごめん、ごめん」と妻に謝っていた。気の利いたことなんて、何一つできなかった。

なのに、妻は、その旅行がいちばん好きだと言った。

「あなたが、あんなに慌ててるの、初めて見たから」。雨の中で道に迷って、二人で傘もささずに笑った、あのcommit。私が見栄を張って、みごとに失敗した、あの一連のcommitを、妻はときどきcheckoutしては、笑っていた。


何年か経った。

私は、仕事でつまずいていた。自分が、何者でもない気がしていた。そんな夜、ふと、あの旅行のログを開いてしまった。

道に迷う私。謝ってばかりの私。立派な夕食に気後れしている私。── 急に、それが惨めに思えた。こんなにかっこ悪い男だったのか、私は。

いつもの手つきが、出た。

git rebase -i。共有した、二人の履歴を。

乗り間違えた電車をdropした。雨のcommitで手を止めて、中身を晴れに書き換えた。謝ってばかりの私をsquashして「スマートにエスコートする私」に編み直した。私だけの枝に、何度もやったのと同じ手つきで。きれいな、見栄えのいい思い出に。

そして、git push --force

二人の共有リモートに、私の版を上書きした。

妻が、fetchした。

しばらく、画面を見ていた。それから、私を見た。怒ってはいなかった。ただ、寂しそうだった。

 ! [rejected]   私たちの旅行 (non-fast-forward)

「……雨、消しちゃったんだ」

妻は、それだけ言った。

私が「かっこ悪い」と思って消した、その一つひとつを妻は覚えていた。雨も、乗り間違えた電車も、謝ってばかりの私も。私が恥じたその全部を。

「私、こっちのほうが、好きだったのにな」

妻は、自分の手元の枝を、私に見せた。彼女のリポジトリには、まだ、元の旅行がぜんぶ残っていた。私がforce-pushしても、それは消えなかった。妻は、私の上書きを受け取らなかった。「こっちのまま、置いとくね」と。

私は、何も言えなかった。

私が、見栄を張って整えた、きれいな旅行。それを「好きだ」と言った人は、誰もいなかった。妻が大切にしていたのは、私が消したかった、あのかっこ悪い私のほうだった。

恋人の前で背伸びしたときは、誰も傷つかなかった。私だけの枝だったから。

でも、これは、二人の枝だった。整えていいのは、私だけの過去だけ、だったのに。

幸い、と言っていいのか分からない。私がいくら上書きしても、妻の手元には、本当の旅行がまだ残っていた。書き換えたcommitのauthorの欄にも、あの日、確かに慌てていた私の名前が残っていた。gitは、私の見栄に、最後まで付き合ってはくれなかった。

そのことに、私は少しだけ救われた。

その週末、私たちはもう一度、あの宿に泊まりに行った。今度は、わざと安い、近場の宿に。また、道に迷えばいい、と思った。


〈技術ノート〉── rebaseの功罪

ノートは答え合わせではない。物語が嘘をついた、ちょうどその場所の地図である。
ただし本章では、嘘は一点にない。嘘と本当の境界線そのものが、主題だ。

同じ操作が、可にも不可にもなる

git rebaseは、commitを付け替えて履歴を編み直す操作だ。interactive(-i)なら、並べ替え(reorder)・統合(squash)・削除(drop)・メッセージの書き換え(reword)、そして中身そのものの書き換え(edit+git commit --amend まで、思いのままにできる。結果、commitのハッシュは、すべて新しくなる

ここを、取り違えやすい。rewordは、commitのメッセージしか変えない。物語で「雨を晴れに」変えたように、記録された出来事そのものを書き換えるのはedit ── そのcommitでrebaseを止め、ファイル(=中身)を書き換えてamendする。rewordが見出しの差し替えなら、editは本文の捏造だ。rebaseは、そこまでできる。 だから、共有後に使えば、凶器になる。

この道具は、履歴を最も美しく整える最良の手段であり、使う場所を間違えれば、最悪の凶器になる。同じ手つきが、だ。境界は、たった一つ。

そのcommitを、まだ自分しか持っていないか。

  • 第一場(可) ── まだpushしていない、自分だけの枝。rebaseで過去を整えても、誰も困らない。誰も、その履歴に依存していないからだ。ただの自己編集。健全な、ささやかな背伸び。
  • 第二場(不可) ── すでにpushし、相手も持っている共有の枝。これをrebaseで書き換え、git push --forceで上書きすると、相手がfetchしたとき、non-fast-forward(自分の知っている過去の続きでは、もうない)として現れる。

主人公の罪は、誰かを陥れたことではない。見栄から、二人で持っていた思い出を、自分の見栄えのいい版に差し替えようとしたこと。動機が背伸びでも、共有履歴を書き換えれば、結果は同じ ── これがgitのゴールデンルール(push済み・他者が依存する履歴はrebase / force-pushするな)であり、そのまま、関係の倫理でもある。

gitは、完全な改竄を許さない(だからこそ、救いになる)

ここが、本章の肝だ。force-pushしても、元は、消えない。理由は三つ。

  1. 相手のrepoは、こちらのforce-pushでは消せない。 force-pushが上書きするのは、共有リモートのrefだけ。相手がfetchすると、自分の手元の枝とリモートが分岐した(diverged) と分かる。相手は、あなたの版にresetして乗り換えることも、乗り換えずに自分の版を持ち続けることもできる。妻が「こっちのまま置いとく」と言えたのは、これだ。本当の旅行は、妻の手元に、まるごと残る。
  2. authorは、保持される。 rebaseで書き換わるのは、message・順番・committer・ハッシュ・日付。だがauthor(書いた人)だけは、--reset-authorでもしない限り、残る。「あの日、慌てていた私」の名前は、書き換えたcommitにも残ってしまう。
  3. reflogが覚えている。 あなたの手元のreflogには、rebase前のcommitが、しばらく残る。

過去を整えることは、gitは許す。だが過去をなかったことには、させてくれない。物語ではそれが、消したかった「かっこ悪い私」=妻が愛していた私を、結果的に守った。

正しい名前

物語の言葉 gitの正名
過去を整える・並べ直す rebase -i=commitを付け替えて履歴を編み直す(reorder/squash/drop/reword/edit)。ハッシュは新しくなる
雨を晴れに書き換える edit+commit --amend=そのcommitで止め、中身(記録された出来事)を書き換える。reword(メッセージのみ)より深い改変
私だけの枝・pushしていない 未共有履歴=書き換えてよい(ゴールデンルールの「可」)
二人でpushした共有の枝 共有履歴=書き換えてはいけない(「不可」)
上書きした git push --force=リモートのrefを自分の版で上書き。相手のfetchはnon-fast-forwardを検出(※ --force-with-leaseなら、相手が先にpushしていた場合は拒否され、より安全)
妻の手元に元が残っていた 相手のローカルは上書きされない=force-pushが変えるのは共有リモートだけ。各自の手元の版は、本人が乗り換えない限り残る
authorの欄に名前が残る rebaseはauthorを保持=書き換わるのはcommitter・ハッシュ・日付だけ。由来は残る

要点

  1. rebaseは最良の整形具にして、共有後は最悪の凶器。 境界は一つ ── そのcommitを、まだ自分しか持っていないか。動機が悪意でも背伸びでも、共有履歴を書き換えれば結果は同じ。
  2. force-pushが上書きするのは共有リモートだけ。 相手の手元の版は消せない。相手には、乗り換えない自由がある。
  3. 完全な改竄はできない。 authorは保持され、reflogと相手のrepoは元を覚えている。gitが過去を守りきるから、消したかった「本当」が、生き残る。

10章へ

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?