1331

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

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

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

リベースを試みるか (その間に変更をプッシュしたため、適用されません)、元に戻すことができるようです。しかし、複数のコミットを元に戻すにはどうすればよいでしょうか? 一度に 1 つずつ元に戻しますか? 順番は重要ですか?

4

16 に答える 16

1757

コメントに書いたことを展開する

原則として、公開した履歴を書き換える (変更する) べきではありません。履歴を書き換える (変更する) と、それらの変更をマージしたり、更新したりするときに問題が発生します。

したがって、解決策は、削除したい変更を元に戻す新しいコミットを作成することです。git revertコマンドを使用してこれを行うことができます。

次の状況があります。

A <-- B <-- C <-- D <-- マスター <-- HEAD

(ここでの矢印はポインターの方向を示します。コミットの場合は「親」参照、ブランチ ヘッド (ブランチ リファレンス) の場合はトップ コミット、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"

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


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

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

次に、次のような状況になります。

A <-- B <-- C <-- D <-- A' <-- マスター <-- HEAD

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


Charles Bailey によって変更された Jeff Ferland による代替ソリューションは、同じアイデアに基づいていますが、git resetを使用しています。ここではわずかに変更されています。この方法はすべてに対応しています。

$ git reset --hard A
$ git reset --soft D # (or ORIG_HEAD or @{1} [previous location of HEAD]), all of which are D
$ git commit
于 2009-09-24T08:44:40.757 に答える
269

そのためには、revertコマンドを使用して、元に戻したいコミットの範囲を指定するだけです。

あなたの例を考慮して、これを行う必要があります(ブランチ「マスター」にいると仮定します):

git revert master~3..master

またはgit revert B...Dまたはgit revert D C B

これにより、B、C、および D の逆コミットを使用して、ローカルに新しいコミットが作成されます (つまり、これらのコミットによって導入された変更が取り消されます)。

A <- B <- C <- D <- BCD' <- HEAD
于 2012-07-31T15:00:45.823 に答える
90
git reset --hard a
git reset --mixed d
git commit

これは、それらすべてを一度に元に戻す機能を果たします。適切なコミット メッセージを送信します。

于 2009-09-23T00:45:31.410 に答える
84

Jakub の回答と同様に、これにより、連続したコミットを簡単に選択して元に戻すことができます。

# revert all commits from and including B to HEAD, inclusively
$ git revert --no-commit B^..HEAD  
$ git commit -m 'message'
于 2014-07-31T18:49:15.610 に答える
65

まず、作業コピーが変更されていないことを確認してください。それで:

git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply

そしてコミットするだけです。元に戻す理由を文書化することを忘れないでください。

于 2014-09-09T13:13:27.470 に答える
56

この質問に答えられないことにとてもイライラしています。他のすべての問題は、正しく元に戻して履歴を保存する方法に関連しています。この質問は、「ブランチのヘッドが A を指すようにしたい。つまり、B、C、D、および HEAD を消し、ヘッドを A と同義にしたい」というものです。

git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f

私は Jakub の投稿を読んで多くのことを学びましたが、会社の誰か (Pull-Request なしで "testing" ブランチにプッシュするアクセス権を持つ) は、5 回前にコミットした間違いを修正し、修正しようとして、5 つの悪いコミットのようにプッシュしました。それだけでなく、1 つまたは 2 つのプル リクエストが受け入れられました。忘れてください。最後の適切なコミット (abc1234) を見つけて、基本的なスクリプトを実行しました。

git checkout testing
git reset --hard abc1234
git push -f

このレポで作業している他の 5 人に、過去数時間の変更を記録し、最新のテストからワイプ/再分岐することを伝えました。話の終わり。

于 2016-07-11T23:29:24.287 に答える
9

共有リポジトリ(人々が使用し、履歴を保持したい)のコミットのグループを元に戻す簡単な方法はgit revert、gitと組み合わせて使用​​することrev-listです。後者はコミットのリストを提供し、前者はそれ自体を元に戻します。

これを行うには2つの方法があります。1回のコミットで複数のコミットを元に戻すには、次のようにします。

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-commit $i; done

これにより、必要なコミットのグループが元に戻りますが、すべての変更は作業ツリーに残されます。その後、通常どおりすべてをコミットする必要があります。

もう1つのオプションは、元に戻された変更ごとに1つのコミットを行うことです。

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done

たとえば、次のようなコミットツリーがある場合

 o---o---o---o---o---o--->    
fff eee ddd ccc bbb aaa

eeeからbbbへの変更を元に戻すには、を実行します

for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done
于 2011-08-04T11:29:23.127 に答える
-8

機能のコミットを一時的に元に戻したい場合は、次の一連のコマンドを使用できます。

これがどのように機能するかです

git ログ --pretty=oneline | grep 'feature_name' | カット -d ' ' -f1 | xargs -n1 git revert --no-edit

于 2016-02-11T18:47:34.390 に答える