リモートブランチからいくつかのコミットを永久に削除する方法


490

ヤダヤダ悪い歴史の書き直しです。

しかし、リモートブランチからいくつかのコミットを永久に削除するにはどうすればよいですか?


96
ええ、それは本当に悪いヤダヤダですが、なぜか私はそれを好きにする必要があります。
James Morris

44
私はこれが愚かであることを知っていますが、ログインをテストしたり、コードでプレーンテキストのパスワードを使用したりするなど、たまに起こることがあります。これは、実際のログイン資格情報です。そして、おっと...
2013

6
実際のログイン資格情報..うん、いくつかのwhooposを思い出させる
Hello Universe


2
これがどれほど危険で、それを決してすべきではないかについてのこの学術的な熱心さにうんざりしています。gitの履歴からデータを削除し、他の開発者との競合/破壊に対処する方がはるかに優れている場合があります。とても簡単です。これを無視する人々は、おそらく教室の外で働いたことはないでしょう。
つぶす

回答:


369

あなたgit reset --hardワーキングツリーとインデックスからの変更を削除し、あなたのためにあなたのローカルブランチgit push --forceリモートに自分の改訂ローカルブランチを。(ここ他の解決策、リモートブランチを削除してそれを再プッシュすることを含む)

このSOの回答は、特に人々が自分のローカルリポジトリのリモート履歴に依存している場合、そのようなコマンドの危険性を示しています。マニュアルページの「UPSREAM REBASE
からの復旧」セクションに人々を指摘する準備をする必要がありgit rebaseます。


Git 2.23(2019年8月、9年後)では、新しいコマンドを使用しますgit switch
つまり:(削除するコミットの数に 置き換えます)git switch -C mybranch origin/mybranch~n
n

これにより、インデックスと作業ツリーが復元されますgit reset --hard


奇妙な。私はすでにそれを試したような気がします。いくつかのリベースと一緒に-魅力のように動作します。ありがとう。
Arnis Lapsa 2010

7
@Arnis:完璧、それから;)push --force離れて
VonC

私はBFG Repo-Cleanerを使用して機密データを削除しました。これにより、元のファイルが含まれる「名前のない」ブランチが残りました。最後に必要なコミットにリセットし、元の場所に強制的にプッシュした後、すべてうまく
いきました

コミットのURLはまだ存続していることに注意してください(少なくともしばらくの間)。誰かがコミットのURLを持っている場合(あなたが神にそれを与えた理由を知っている)、彼らはコードにアクセスできるようになります。
Mosh Feu

1
@MoshFeu True:git gcリモート側で常に十分な頻度で実行されるとは限りません。たとえば、GitHubの場合:twitter.com/githubhelp/status/387926738161774592
lang

248

last_working_commit_id機能していないコミットを元に戻すときは、

git reset --hard <last_working_commit_id>

したがって、必要のないものにリセットしcommit_idてはなりません。

次に、リモートブランチにプッシュする必要があります。

git push --force

10
完璧で、エレガントで、シンプルな答え。リモートとローカルの両方で必要な最後のStabeコミットに戻しました
lauWM '13 / 12/17

2
これにより、ローカルの変更も失われました。私はそれを期待していませんでした。しかし、まあ、リポジトリを機能させるために個人のパスワードをコミットするよりはましです。
Airwavezx

3
git stash ....いくつかのことを行ってローカルの変更を保存できます....とgit stash pop(ローカルの変更が戻ってきました)
MonTea

これにより、「リモート:エラー:早送りではないrefs / heads / masterを拒否します(最初にプルする必要があります)」というエラーが発生します
Saurabhcdt

@Airwavezxはgit reset --hard、実行することになっています。
ルーク

146

重要:「git push -f」でどのブランチを指定するかを確認してください。そうしないと、他のブランチを誤って変更してしまう可能性があります。[*]

このチュートリアルには3つのオプションがあります。リンクが切れた場合は、ここで主な手順を行います。

  1. 完全なコミットを元に戻す
  2. 最後のコミットを削除する
  3. リストからコミットを削除する

1完全なコミットを元に戻す

git revert dd61ab23

2最後のコミットを削除する

git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>

または、ブランチがローカルで利用可能な場合

git reset HEAD^ --hard
git push <<remote>> -f

ここで、+ dd61 ...はコミットハッシュであり、gitはx ^をxの親として解釈し、+は強制的な高速でないプッシュとして解釈します。

3リストからコミットを削除する

git rebase -i dd61ab23^

これが開き、すべてのコミットのリストを示すエディターが表示されます。取り除きたいものを削除します。リベースを終了し、フォースをレポにプッシュします。

git rebase --continue
git push <remote_repo> <remote_branch> -f

5
"git push <remote_repo> <remote_branch> -f"でどのブランチを指定するかを確認してください。そうしないと、他のブランチを誤って変更してしまう可能性があります。
Nigel Sheridan-Smith

ステップ1と2だけが仕事をして、元の質問に答えました。(ステップ3は実行しないでください)
Saad Benbouzid

これらは、実行する手順ではなく、さまざまなシナリオのオプションです。私の場合、インタラクティブなリベース(オプション3)は私が探していたものを実行しました。
Steve Blackwell

私はステップ3をしなければならなかった。なぜこれを@Saadに実行すべきではないのですか?幸運なことに、私の<< remote >>は単にデフォルトの 'origin'であり、<remote_branch>はデフォルトの 'master'でした
Bart

30

たとえば最後の3コミットを削除する場合は、次のコマンドを実行して、ローカルブランチのファイルシステム(作業ツリー)とコミット履歴(インデックス)から変更を削除します。

git reset --hard HEAD~3

次に、ローカルマシンで次のコマンドを実行して、リモートブランチにその履歴を強制的に書き換えさせます。

git push --force

おめでとう!全部終わった!

いくつかのメモ:

次のコマンドを実行すると、目的のコミットIDを取得できます

git log

そして、あなたは置き換えることができHEAD~N<desired-commit-id>、このように:

git reset --hard <desired-commit-id>

ファイルシステムの変更を保持し、インデックス(コミット履歴)を変更するだけの場合は、などの--softフラグを使用しますgit reset --soft HEAD~3。次に、最新の変更を確認し、それらのすべてまたは一部を保持または削除する機会があります。後者の場合、runnig git statusはから変更されたファイルを表示します<desired-commit-id>--hardオプションを使用git statusすると、ローカルブランチがリモートブランチとまったく同じであることを通知します。--hardnorを使用しない--soft場合、デフォルトのモードであるが使用されます--mixed。このモードでgit help resetは、言う:

インデックスをリセットしますが、作業ツリーはリセットしません(つまり、変更されたファイルは保持されますが、コミットのマークは付けられません)。更新されていないものを報告します。


10

これは遅すぎるかもしれませんが、私を助けたのはクールに聞こえる「核」オプションです。基本的にこのコマンドfilter-branchを使用すると、ファイルを削除したり、git履歴全体で多数のファイルを変更したりできます。

ここで最もよく説明されています


9
手遅れではありません。同様の問題を抱える放浪者に役立つかもしれ
ません

9

同様にこのブログ投稿に基づいて、pctrollの回答から簡略化します。

# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote

2
うまくいきました、ありがとう。そして、私はリモートブランチ履歴から1つのコミット(たとえばpwdを含む)を永久に削除したいのですが、どうすればいいですか?
笑顔

1
私にも有効ですが、Smilesと同じ質問があります。自分のコミット/リバーを履歴に表示したくないのですが、どうすれば削除できますか?
Roberto Rodriguez

4

この問題を修正する最も簡単な方法は、コードが適切であることがわかっている場所から新しいブランチを作成することです。その後、後でそこから他のコミットを選択する必要がある場合に備えて、誤ったブランチ履歴をそのままにしておくことができます。これにより、コミット履歴も失われなくなりました。

ローカルの誤ったブランチから:

git log

ブランチを配置したいコミットハッシュをコピーしてgitログを終了します

git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch

これで、思い通りの方法で新しいブランチができました。

新しいブランチにないエラーのあるブランチからの特定のコミットも保持する必要がある場合は、必要な特定のコミットを簡単に選択できます。

git checkout the_errant_branch
git log

適切なブランチにプルし、gitログを終了するために必要な1つのコミットのコミットハッシュをコピーします。

git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied

背中をなでます。


非常に簡単で、行き止まりの枝があるかどうかは誰が気にしますか?新しいブランチを作ってそれで終わります!
アンドリューフォックス

これは本当に素晴らしい答えです。コミットを選択したり、リモートブランチを操作したりする代わりに、これを行ってよかったです。
Magnilex

0
 git reset --soft commit_id
 git stash save "message"
 git reset --hard commit_id
 git stash apply stash stash@{0}
 git push --force
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.