227

git 履歴が次のようになっているとします。

1 2 3 4 5

1 ~ 5 は個別のリビジョンです。1、2、4、および 5 を維持したまま 3 を削除する必要があります。これはどのように行うことができますか?

削除するリビジョンの後に何百ものリビジョンがある場合、効率的な方法はありますか?

4

9 に答える 9

137

このコメントによると(これが正しいことを確認しました)、 radoの答えは非常に近いですが、gitは切り離された状態のままです。代わりに、HEADこれを削除して使用し<commit-id>、現在のブランチから削除します。

git rebase --onto <commit-id>^ <commit-id>
于 2012-11-15T00:50:55.973 に答える
126

削除したい<commit-id>のみを知って、特定の を非対話的に削除する方法を次に示します。<commit-id>

git rebase --onto <commit-id>^ <commit-id> HEAD
于 2010-09-14T00:12:35.417 に答える
79

リビジョン3と4を1つのリビジョンに結合するには、gitrebaseを使用できます。リビジョン3の変更を削除する場合は、インタラクティブリベースモードで編集コマンドを使用する必要があります。変更を1つのリビジョンに結合する場合は、スカッシュを使用します。

私はこのスカッシュテクニックをうまく使用しましたが、以前にリビジョンを削除する必要はありませんでした。「コミットの分割」の下にあるgit-rebaseのドキュメントは、うまくいけば、それを理解するのに十分なアイデアを提供するはずです。(または他の誰かが知っているかもしれません)。

gitドキュメントから:

そのまま保持したい最も古いコミットから開始します。

git rebase -i <after-this-commit>

エディターは、現在のブランチのすべてのコミット(マージコミットを無視)で起動されます。これは、指定されたコミットの後に発生します。このリストのコミットを心ゆくまで並べ替えたり、削除したりできます。リストは多かれ少なかれ次のようになります。

デッドビーを選ぶこのコミットの1行
ピックfa1afe1次のコミットの1行
..。

1行の説明は、純粋にあなたの喜びのためです。git-rebaseはそれらを確認しませんが、コミット名(この例では「deadbee」と「fa1afe1」)を確認するため、名前を削除または編集しないでください。

コマンド「pick」をコマンド「edit」に置き換えることで、そのコミットを適用した後にgit-rebaseに停止するように指示できます。これにより、ファイルやコミットメッセージを編集し、コミットを修正して、リベースを続行できます。

2つ以上のコミットを1つに折りたたむ場合は、2番目以降のコミットでコマンド「pick」を「squash」に置き換えます。コミットに異なる作成者がいた場合、押しつぶされたコミットは最初のコミットの作成者に帰属します。

于 2008-08-31T23:46:33.880 に答える
77

前に述べたように、git-rebase(1)はあなたの友達です。コミットがmasterブランチにあると仮定すると、次のようになります。

git rebase --onto master~3 master~2 master

前:

1---2---3---4---5  master

後:

1---2---4'---5' master

git-rebase(1)から:

コミットの範囲は、リベースで削除することもできます。次のような状況の場合:

E---F---G---H---I---J  topicA

次にコマンド

git rebase --onto topicA~5 topicA~3 topicA

コミットFとGが削除されます。

E---H'---I'---J'  topicA

これは、FとGに何らかの欠陥がある場合、またはtopicAの一部であってはならない場合に役立ちます。--ontoの引数とパラメーターは、任意の有効なcommit-ishにすることができることに注意してください。

于 2010-11-05T23:34:04.550 に答える
23

リビジョン 3 で行われた変更を削除するだけの場合は、git revert を使用することをお勧めします。

Git revert は、元に戻すリビジョンのすべての変更を元に戻す変更を含む新しいリビジョンを作成するだけです。

これが意味することは、不要なコミットと、それらの変更を削除するコミットの両方に関する情報を保持するということです。

元に戻すことは基本的に単なる標準的なコミットであるため、その間に誰かがあなたのリポジトリからプルした可能性がある場合、これはおそらくはるかに友好的です。

于 2008-09-05T16:16:32.763 に答える
19

これまでのすべての回答は、後続の懸念に対処していません。

削除するリビジョンの後に何百ものリビジョンがある場合、効率的な方法はありますか?

手順は次のとおりですが、参考までに、次の履歴を想定してみましょう。

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]

C : 削除するコミットの直後にコミットする (クリーン)

R : 削除するコミット

B : 削除するコミットの直前のコミット (ベース)

「何百ものリビジョン」という制約があるため、次の前提条件を想定しています。

  1. あなたが存在しないことを望むいくつかの恥ずかしいコミットがあります
  2. その恥ずかしいコミットに実際に依存する後続のコミットはゼロです(復帰時の競合はありません)
  3. 何百もの介在するコミットの「コミッター」としてリストされてもかまいません (「作成者」は保持されます)。
  4. リポジトリを共有したことがない
    • または、そのコミットを含む履歴を複製したことのあるすべての人々に対して、あなたの新しい履歴を使用するよう説得するのに十分な影響力を実際に持っています。
    • そしてあなたは歴史を書き換えることを気にしません

これはかなり制限的な制約のセットですが、このコーナー ケースで実際に機能する興味深い答えがあります。

手順は次のとおりです。

  1. git branch base B
  2. git branch remove-me R
  3. git branch save
  4. git rebase --preserve-merges --onto base remove-me

本当に競合がない場合は、これ以上中断することなく続行する必要があります。対立がある場合は、それらを解決するrebase --continueか、恥ずかしさと一緒に暮らすことを決定できますrebase --abort

これで、コミットRmasterがなくなった状態になるはずです。和解したい場合に備えて、ブランチは以前の場所を指しています。save

新しい歴史への他の全員の転送をどのように手配したいかは、あなた次第です。stashreset --hard、およびに精通している必要がありcherry-pickます。baseそして、、、remove-meおよびsaveブランチを削除できます

于 2012-09-24T15:11:16.060 に答える
0

rado と kareem の回答は私には何もしません (「Current branch is up to date.」というメッセージのみが表示されます)。これは、Windows コンソールで '^' 記号が機能しないために発生する可能性があります。ただし、このコメントによると、「^」を「~1」に置き換えると問題が解決します。

git rebase --onto <commit-id>^ <commit-id>
于 2017-09-14T07:51:57.550 に答える