次のようなgitリポジトリがあります。
A -> B -> C -> D -> HEAD
ブランチのヘッドがAを指すようにしたい、つまり、B、C、D、およびHEADを非表示にして、ヘッドをAと同義にしたい。
私はリベースを試みるか(間に変更をプッシュしたため適用されない)、または元に戻すことができるようです。しかし、どうすれば複数のコミットを元に戻すことができますか?一度に1つ元に戻しますか?順序は重要ですか?
git revert
。
次のようなgitリポジトリがあります。
A -> B -> C -> D -> HEAD
ブランチのヘッドがAを指すようにしたい、つまり、B、C、D、およびHEADを非表示にして、ヘッドをAと同義にしたい。
私はリベースを試みるか(間に変更をプッシュしたため適用されない)、または元に戻すことができるようです。しかし、どうすれば複数のコミットを元に戻すことができますか?一度に1つ元に戻しますか?順序は重要ですか?
git revert
。
回答:
コメントで書いたことを拡張する
一般的なルールは、誰かが自分の作業に基づいている可能性があるため、公開した履歴を書き換える(変更する)べきではないということです。履歴を書き換える(変更する)と、それらの変更のマージと更新が問題になります。
したがって、解決策は、削除したい変更を元に戻す新しいコミットを作成することです。これはgit revertコマンドを使用して行うことができます。
次の状況があります。
A <-B <-C <-D <-マスター<-HEAD
(ここでの矢印は、ポインタの方向を指します:コミットの場合は「親」参照、ブランチヘッド(ブランチ参照)の場合はトップコミット、HEADリファレンスの場合はブランチの名前)。
作成する必要があるのは次のとおりです。
A <-B <-C <-D <-[(BCD)^-1] <-マスター<-ヘッド
ここで、「[(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"
代替ソリューションは、コミットAの内容をチェックアウトし 、この状態をコミットすることです。
$ git checkout -f A -- .
$ git commit -a
次に、次のような状況になります。
A <-B <-C <-D <-A '<-マスター<-ヘッド
コミットA 'の内容はコミットAと同じですが、コミット(コミットメッセージ、親、コミット日)が異なります。
チャールズ・ベイリーによって変更ジェフFerlandによって溶液は、同じ考えに基づいて構築されますが、使用してgitのリセットを:
$ git reset --hard A
$ git reset --soft @{1} # (or ORIG_HEAD), which is D
$ git commit
git checkout -f A -- .
これらは削除されません。手動で行う必要があります。私は今この戦略を適用しました、ありがとうJakub
git checkout foo
チェックアウトブランチ foo
(ブランチに切り替える)またはチェックアウトファイル foo(インデックスから)を意味する場合があります。--
曖昧さをなくすために使用されgit checkout -- foo
ます。たとえば、常にファイルについてです。
git revert --no-commit D C B
git revert
、複数のコミットを受け入れませんでした。それはかなり新しい追加です。
便利だと思った綺麗な方法
git revert --no-commit HEAD~3..
このコマンドは、最後の3つのコミットを1つのコミットだけで元に戻します。
また、履歴を書き換えません。
git commit
そこから実際にコミットします。
HEAD~3..
と同じHEAD~3..HEAD
そのためには、復帰したいコミットの範囲を指定して、復帰コマンドを使用する必要があります。
あなたの例を考慮に入れると、これを行う必要があります(ブランチ「マスター」にいると仮定します):
git revert master~3..master
これにより、B、C、およびDの逆コミットでローカルに新しいコミットが作成されます(つまり、これらのコミットによって導入された変更が取り消されます)。
A <- B <- C <- D <- BCD' <- HEAD
git revert --no-commit HEAD~2..
それを行うには、もう少し慣用的な方法です。masterブランチを使用している場合は、masterを再度指定する必要はありません。この--no-commit
オプションを使用すると、履歴に複数のrevert commit ...
メッセージが散らばるのではなく、gitがすべてのコミットを一度に元に戻そうとします(それがあなたが望むものであると仮定します)。
master~3
。
--no-commit
(つまり、復帰するたびに個別のコミットを取得する)ことであり、その後、インタラクティブなリベースでそれらすべてをまとめて潰します。結合されたコミットメッセージにはすべてのSHAが含まれ、お気に入りのコミットメッセージエディタを使用して好きなようにSHAを配置できます。
Jakubの回答と同様に、これにより、復帰する連続したコミットを簡単に選択できます。
# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD
$ git commit -m 'message'
B^..HEAD
、そうでない場合はBが除外されています。
git revert --no-commit B^..HEAD
またはgit revert --no-commit A..HEAD
git reset --hard a
git reset --mixed d
git commit
それは、一度にそれらすべての復帰として機能します。適切なコミットメッセージを提供します。
HEAD
のように見えるようにA
、その後、彼はおそらく、インデックスが一致させたいので、git reset --soft D
おそらくより適切です。
git checkout A
その後、git commit
上記はうまくいきませんでしたが、この答えはうまくいきました。
git reset --mixed D
必要なのですか?具体的にはなぜreset
ですか?Dにリセットしないと、HEADがAをポイントし、B、C、Dが「ぶら下がり」ガベージコレクションされてしまうためです。しかし、なぜ--mixed
ですか?あなたは既に「答え--soft
この方法は、A -作業ディレクトリは、Aの変更が含まれていますしながら、リセットは、インデックスを移動しません...」だから、インデックスを移動することで、この手段インデックスは、D'sの変更が含まれていますgit status
か、git diff
インデックスを比較する([D]へワーキングディレクトリ[A])は物質を表示します。そのユーザーはDからAに戻りますか?
まず、作業コピーが変更されていないことを確認してください。次に:
git diff HEAD commit_sha_you_want_to_revert_to | git apply
その後、コミットします。元に戻す理由を文書化することを忘れないでください。
error: cannot apply binary patch to 'some/image.png' without full index line error: some/image.png: patch does not apply
git diff --binary HEAD commit_sha_you_want_to_revert_to | git apply
git revert A..Z
すると、次のようになりますerror: commit X is a merge but no -m option was given.
この質問には答えられないほどイライラしています。他のすべての質問は、どのように正しく復帰し、履歴を保存するかに関するものです。この質問は、「ブランチのヘッドが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人の人に、最近の数時間の変更と最新のテストからのワイプ/再ブランチをよりよく記録することを伝えました。物語の終わり。
git push --force-with-lease
、気化するコミットの後またはコミットの範囲内で他の誰もブランチにコミットしていない場合にのみ履歴を書き換えます。他の人がブランチを使用した場合、その履歴は決して書き換えられるべきではなく、コミットは単に目に見える形で戻されるべきです。
これは、Jakubの回答で提供されているソリューションの1つを拡張したものです。
ロールバックするのに必要なコミットがいくらか複雑で、いくつかのコミットはマージコミットであり、履歴の書き換えを避ける必要があるという状況に直面しました。git revert
追加された復帰変更の間に最終的に競合が発生したため、一連のコマンドを使用できませんでした。私は次の手順を使用して結局しました。
まず、HEADをブランチの先端に残したまま、ターゲットコミットの内容を確認します。
$ git checkout -f <target-commit> -- .
(-は<target-commit>
ファイルではなくコミットとして解釈されます。.は現在のディレクトリを指します。)
次に、ロールバックされているコミットにどのファイルが追加されたのか、したがって削除する必要があるのかを判断します。
$ git diff --name-status --cached <target-commit>
追加されたファイルは、行の先頭に「A」が表示され、その他の違いはないはずです。次に、ファイルを削除する必要がある場合は、これらのファイルを削除のためにステージングします。
$ git rm <filespec>[ <filespec> ...]
最後に、復帰をコミットします。
$ git commit -m 'revert to <target-commit>'
必要に応じて、目的の状態に戻っていることを確認します。
$git diff <target-commit> <current-commit>
違いはないはずです。
git
ブランチの先端だけでヘッドできると確信していますか?
共有リポジトリでコミットのグループを元に戻す簡単な方法(git revert
ユーザーが使用し、履歴を保持したい)は、gitと組み合わせて使用することrev-list
です。後者はコミットのリストを提供し、前者はそれ自体を元に戻します。
それには2つの方法があります。単一のコミットで複数のコミットを元に戻す場合:
for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done
これにより、必要なコミットのグループが元に戻りますが、すべての変更は作業ツリーに残りますので、通常どおりすべてコミットしてください。
別のオプションは、元に戻された変更ごとに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
どれもうまくいかなかったので、元に戻すには3つのコミット(最後の3つのコミット)があったので、次のようにしました。
git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash
魅力のように働いた:)
私の意見では、非常に簡単でクリーンな方法は次のとおりです。
git checkout -f A
git symbolic-ref HEAD refs/heads/master
git commit
git checkout master; git reset --hard A
ですか?または、これが何をするかについてもう少し説明できませんか?
機能のコミットを一時的に元に戻す場合は、次の一連のコマンドを使用できます。
git log --pretty = oneline | grep 'feature_name' | カット-d '' -f1 | xargs -n1 git revert --no-edit
git push -f HEAD~4:master
(リモートブランチがマスターであると想定)。はい、そのようなコミットをプッシュできます。