1. ホーム
  2. Web プログラミング
  3. その他全般

[解決済み】複数のgitコミットを元に戻すには?

2021-12-28 09:36:39

質問

次のようなgitリポジトリがあります。

A <- B <- C <- D <- HEAD

ブランチのヘッドがAを指すように、つまりB、C、D、HEADが消えて、ヘッドがAと同義になるようにしたいのです。

リベースを試みるか(間に変更をプッシュしているので当てはまらない)、リバートするかのどちらかだと思われます。しかし、複数のコミットをどのようにリバートすればいいのでしょうか?一度に一つずつリバートするのでしょうか?順番は重要ですか?

解決方法は?

コメントで書いたことを拡大解釈する

一般的なルールとして、自分が公開した履歴を書き換えてはいけないと言われています。もしあなたが歴史を書き換えたら、彼らの変更をマージしたり、彼らのために更新したりする際に問題が生じるでしょう。

そこで、解決策として 新規コミット どの 変更の取り消し を削除することができます。これを行うには git リバート コマンドを実行します。

次のような状態になっています。

A <-- B <-- C <-- D <-- master <-- HEAD

(ここでいう矢印とは、ポインタの向きのことで、コミットの場合は "parent" 参照、ブランチヘッド (branch ref) の場合はトップコミット、HEAD 参照の場合はブランチの名前です)。

作成する必要があるのは、以下のものです。

A <-- B <-- C <-- D <-- [(BCD)

-1

] <-- マスター <-- HEAD

ここで [(BCD)^-1] は、コミット B、C、D の変更を取り消すコミットを意味します。数学では (BCD) -1 = D -1 C -1 B -1 ということで、以下のコマンドで必要な状況を得ることができます。

$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message for all of them"

マージコミット以外のすべてのコミットに対して機能します。


別の解決策としては チェックアウト 内容 をコミットし、この状態をコミットします。また、マージコミットでも動作します。ただし、追加されたファイルは削除されません。ローカルでの変更点がある場合 git stash を先に実行します。

$ git checkout -f A -- . # checkout that revision over the top of local files
$ git commit -a

そうすると、次のような状態になります。

A <-- B <-- C <-- D <-- A' <-- master <-- HEAD

コミットA'はコミットAと同じ内容ですが、別のコミットです(コミットメッセージ、親、コミット日)。


オルタネート 解決策:Jeff Ferland、修正:Charles Bailey は、同じアイデアを基にしたものですが ギットリセット . ここでは、この方法を少し修正し、あらゆるものに対応できるようにしています。

$ git reset --hard A
$ git reset --soft D # (or ORIG_HEAD or @{1} [previous location of HEAD]), all of which are D
$ git commit