GITで部分的な復元を実行できますか


156

複数ファイルのコミットで単一ファイルまたはファイルの特定の変更のみを元に戻すことは可能ですか?

全文 私はたくさんのファイルをコミットしました。名前のないままになる誰か(JACK !!!)によるコミットの後で、ファイルをリポジトリにコピーしていくつかのファイルをコミットし、私が行った変更の一部を上書きしました。破損した1つ以上のファイルを元に戻したいのですが、そのファイルの2つの変更を元に戻します。プルおよびプッシュされたため、これは個別の復帰コミットである必要があります。


ブライアンは私を正しい軌道に乗せた。最終的にgit add --patchを使用してから、patch内の編集機能を使用して必要なものを取得しました。
クラッチ

2
ゲームにはかなり遅れましたが、「正しい」答えを見つけと思います
ntc2 14年

@ ntc2奇妙なことに、受け入れられた回答は、リンクした回答よりもはるかにうまく機能しました。パッチの適用に失敗するのではなく、解決するためにマージの競合が発生しました。
Iiridayn

@liridayn答えは全部読んだ?「バリエーション」セクションでは、--3wayパッチの適用に失敗するのではなく、追加するとマージの競合が発生すると主張しています。
ntc2

回答:


204

'--no-commit'オプションを追加すると、新しいコミットを作成せずにコミットを元に戻すことができます。これにより、元に戻されたすべてのファイルがステージング領域に残ります。そこから、ソフトリセットを実行し、本当に必要な変更を追加します。ワークフローの例:

git revert <sha-of-bad-commit> --no-commit
git reset   // This gets them out of the staging area
<edit bad file to look like it should, if necessary>
git add <bad-file>
git checkout . // This wipes all the undesired reverts still hanging around in the working copy
git commit

42
ソフトリセット後、git add -pファイル全体ではなくファイルのチャンクを選択して追加できるインタラクティブセッションを開始することもできます。(git reset -p変更を選択的にアンステージングすることもあります。知っておくと便利ですが、このシナリオではおそらく望んでいないことです。)
StéphanKochen

1
これはまさに私が探していたものでした:作業コピーに戻し、対話的にhunkを選択し、コミットします。あなたはそのために大きな塩味の男の
スモーチに値し

この1に触発別の解決策は、になりrevertresetstash -p、(スタッシュは「私はactualyしたくないことをキャンセルする」) add、残りcommit
シリルCHAPON

82

checkoutコマンドを使用して、ファイルの古いバージョンをインタラクティブに適用できます。

たとえば、COMMIT追加するコードが削除された場所がわかっている場合は、次のコマンドを実行できます。

git checkout -p COMMIT^ -- FILE_TO_REVERT

Gitは、現在のバージョンのファイルから欠落しているハンクを追加するように要求します。を使用eして、変更を適用する前に変更のパッチを作成できます。


ファイルの一部のみを元に戻したい場合に非常に役立ちます。基本的に、頭からチャンクを取得するにはgit checkout -p path/to/file
falstaff 2014年

40

を使用して、元に戻したいファイルの古くて良い内容を手動でチェックアウトできますgit checkout。あなたは戻したい場合たとえば、my-important-fileそれはバージョンにあったバージョンにabc123、あなたが行うことができます

git checkout abc123 -- my-important-file

これでmy-important-fileback の古い内容が手に入りました。必要に応じて編集することもでき、通常どおりコミットして、彼が行った変更を元に戻すコミットを作成します。彼のコミットの一部だけを元に戻したい場合は、を使用git add -pして、コミットしているパッチから少数のハンクのみを選択します。


19
これはではなく、revert単にファイルの古いバージョンを取り戻すだけです。適切なrevertものは、ファイル内の不正なコミットの変更を削除します。たとえ不正なコミット以降に何度か変更されていて、それらの変更を失いたくない場合です。
2013年

2
トーター、私の答えを見てください。'-p'を使用して変更を保存できます。答えはこれに非常に近いです。
cmcginty 2013

1
または、これをに組み合わせることもできますgit checkout -p
レオ・ラム

31

Gitメーリングリストでこれを行う方法を見つけました。

git show <commit> -- <path> | git apply --reverse

出典:http : //git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html#a6064406

バリエーション

パッチが適切に適用されない場合、そのコマンドは失敗します(変更は発生しません)が、--3way代わりに競合が発生し、手動で解決できます(この場合、Caseyの答えがより実用的かもしれません)。

git show <commit> -- <path> | git apply --reverse --3way

これを使用して、複数のコミットを部分的に元に戻すこともできます。例:

git log -S<string> --patch | git apply --reverse

<string>コミットで一致する変更を含むファイルを元に戻します。これはまさに私のユースケースで必要なものです(いくつかの個別のコミットにより、別のファイルに同様の変更が導入され、他のファイルも無関係に変更したため、元に戻したくありませんでした)。

diff.noprefix=true設定している場合は、コマンド~/.gitconfigに追加-p0する必要がありますgit apply。たとえば、

git show <commit> -- <path> | git apply -p0 --reverse

この回答は、受け入れられた回答よりもはるかに優れています。「さらに良いことに、そのファイルの2つの変更を元に戻します」。
2014年

コミットの一部のみを元に戻したかったので、次のようにしました:(1) git show ... > foo.txt (2)foo.txt元に戻したくない差分を削除するために編集(3) git apply --reverse foo.txtにリストされている差分を元に戻しfoo.txtます。
cxw 2018年

git showパートに--binary --full-indexを追加することも、有用なバリエーションになる可能性があります
Laurynas Biveinis
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.