2017-07-05 18 views
0

HEADより前のコミットがいくつかあります。コミットしている間に、私が気づいていなかったいくつかの変化があった。私のgit logを見て、私はこれらの望ましくない変化に気づいた。 googleの'undo changes for an arbitrary commit'を検索すると、コミット全体を元に戻してインデックス内の変更を削除すると、多くの結果が返されます。しかし、この任意のコミットでこれらの変更を削除する方法は何でしょうか?任意のコミットの変更を元に戻す方法は?

+1

コミットを部分的に元に戻したいのですか?履歴を書き換えますか? – jonrsharpe

+1

あなたが探しているコマンドは['git rebase --interactive'](https://git-scm.com/docs/git-rebase#git-rebase---interactive)です。 – axiac

+0

@jonrsharpe私は歴史を書いても構いません。これらはすべてローカルな変更であり、私は元に戻すなどの複雑さを追加したくありません。私は単に '{change1、change2、change3}'から '{change1、change2}'に 'AB3ej'をコミットしたいと思っています。例えば、 –

答えて

1

まず、作業ツリーがきれいであることを確認してください。 git statusこれを見つけるのに役立ちます。コミットを待っている変更は報告しないでください。変更がある場合は、(必要に応じて一時的なブランチに)コミットするか、stashをコミットすることができます。

あなたが作業ツリーがクリーンであることを確認した後、現在のコミットにブランチを作成し、それをチェックアウトしません:

$ git branch backup 

をそれが本当に必要されていない、あなたの代わりにREFLOGを使用することができますが、それこの方法ではより簡単に(そしてより目に見えるように)なります。 backupはブランチのために選んだ名前に過ぎません。それは特別なものではありません。唯一の制約は、すでに存在してはならないということです。あなたは3分の1が過去にコミット変更したいと仮定すると、

、実行します。

$ git rebase --interactive HEAD~4 

Gitはデフォルトのエディタで開き、その内容は、一時ファイルは次のようになります。

pick 7f0c5e794 the commit you want to change 
pick 9f96dcae9 commit message #2 
pick 02ed04062 commit message #3 
pick beac35780 the most recent commit 

これは、 rebaseの計画を立てる。もちろん、最後の3つのコミットのハッシュとサブジェクトが含まれています。それらは時系列順(古いものから順に)の最後の4つのコミット(HEAD~4のため)です。

変更したいコミット行(最初の行)を編集します。 pickeditに変更してファイルを保存し、エディタを終了します。

エディタを終了すると、Gitはリベースを開始します。コミットHEAD~3をチェックアウトして終了し、プランに尋ねたとおりにコミットをeditにすることができます。

必要な変更を行い、それらを実行してからgit commit --amendを実行して、コミット(目標)を変更します。変更を行うための最善の方法を実行することです:

$ git reset --mixed HEAD~1 

これは、変更したいコミットする前にファイルをインデックスに追加作業ツリーとは何も変更して、それは、た状態のレポをもたらします。索引に必要なファイルのみを追加してコミットします(なし、--amend)。これは "編集済み" です。

コミットを編集した後でも、コミットされていない変更が作業ツリーに残っています。コミットするか(元の履歴には存在しなかった新しいコミットを作成する)、それらを隠して(そしてリベースを完了した後に適用する)か、完全に破棄するか(git reset --hard;このコマンドを実行する前にそれらが必要です)。あなたがコミットされていない変更一つの方法または別の問題を解決した後

、実行します。

$ git rebase --continue 

Gitはリベースを継続。他のコミットを計画内で指示したとおりに処理します。私たちの計画では、他のコミットにはpickが記載されています。これはGitが変更したくないこれらのコミットの変更を適用することを意味しています。

すべてがうまくいけば、このコマンドが完了すると、望み通りに新しい履歴行が作成されます。あなたが望むように見えない場合は、実行することができます

$ git reset --hard backup 

ここから始めてやり直してください。

リベースが正常に完了しない場合(競合が発生する可能性があります)、いつでもgit rebase --abortを実行して中止できます。 Gitはすべての変更を元に戻し、どこから始めたのでしょうか(backupブランチが指しているコミット時)。

または、rebaseが完了するまで、競合、コミットおよび実行git rebase --continueを解決できます。

リバースを何らかの方法で終了した後、結果に満足しているか、または過去のコミットを変更する考えが終わったら、git branch -D backupを実行してバックアップブランチを削除します。


Gitのコミットは不変です。コミットを編集することはできません。コミットの「編集」は、実際には、古いコミットの代わりに使用される新しいコミットを作成します。もちろん、新しいコミットはオリジナルとは異なるハッシュを持っています。

古いコミットはまだリポジトリに存在し、そのハッシュまたはブランチを使用してアクセスできます。到達するために使用できるブランチがなく、reflogに参照がない場合、コミットオブジェクトは次のガベージコレクションサイクルで削除されます。

+0

'$ git reset --mixed HEAD〜1'の周りにあなたのステップが少し混乱しています。ある時点で 'git commit --amend'をお勧めしますが、あとでcommitをno amendで実行してください。このrebaseの 'edit commit'に関連して1つか2つのコミットがありますか? –

+0

Gitが停止してコミットを修正すると、編集したいコミットが生成された後**のRepoステータスが**同じです。いくつかの変更を行い、それらを実行して 'git commit --amend'を使って最後のコミット(編集するもの)を変更するか、(' git reset HEAD〜1'を使って)1つのコミットに戻って完全に生成することができます既存のものを編集する代わりに、新しいコミット。最初のオプションは、欠落したファイルを追加したり、小さな修正を加える場合に適しています。 2番目の方法はコミットからの変更を削除する方が効果的です。 – axiac

+0

ああ、 'git commit --ammend'はファイルの追加、変更の追加、コミットメッセージの変更を許可しますが、' git reset HEAD〜1'はコミットの履歴をリセットし、 -add)履歴から消えたいファイルを正常にコミットします。元のコミットは不変なので、新しいコミット(新しいハッシュ)は古いものを置き換えます。それは正しい? –

関連する問題