質問
スクリプトに変更を加えてコミットしました。次に、他のいくつかの変更を加え、それらをリモートリポジトリなどにプッシュしました。
その後、私が最初に述べた変更は愚かであり、それを元に戻したいと気づきました。差分を手動でコピー/ペーストせずにコミットしますか?
例:a.py
とb.py
の2つのファイルがあります:
Commit 1:
I delete a function in a.py
Commit 2:
I change a few lines in b.py
Commit 3:
I change the docstring in a.py
その関数の削除を元に戻し、<!> quot; commit 4 <!> quot;として表示させることはできますか? (コミット1を削除するのではなく)
解決
はい、これには git revert を使用できます。詳細については、このgitマニュアルセクションをご覧ください。
要点は、あなたが言うことができるということです:
git revert 4f4k2a
4f4k2aは、取り消したいコミットのIDで、取り消しを試みます。
他のヒント
コメントのみ:
git revert aCommit
all コミットを元に戻します(<!> quot; すべてのファイルコミットの一部 quot;など):
リバースパッチを計算し、HEADに適用してコミットします。
ここで2つの問題(最初の問題は簡単に解決できます):
- 常にコミットするため、
-no-commit
オプションを追加することをお勧めします:<!> quot;git revert --no-commit aCommit
<!> quot ;:これは、複数のコミットを元に戻すときに便利です。インデックスに連続して作用します。 - 特定のファイルには適用されません(a.pyが、元に戻したくない1000個の変更を含むコミットの一部だった場合)?
そのため、別のコミットで特定のファイルを抽出したい場合は、 が表示されるはずです。git-checkout
、具体的にはgit checkout <commit> <filename>
構文(ただし、この場合に必要なものではありません)
Easy Git (Elijah Newren)は、さらに<!> quot;完全な復帰<!> quot; Gitメーリングリストへ。しかし、あまり成功していません:
時折、<!> quot;変更を元に戻す<!> quot;を望む人がいます。
現在、これは次のようになっています:
- 32〜29リビジョン前の変更点、
- 最後のコミット以降のすべての変更である可能性があります、
- 3コミット前からの変更、または
- 特定の1つのコミットのみである可能性があります。
- ユーザーは、そのような復帰を特定のファイルのみにサブセットしたい場合があります、
(eg revert
はここに記載ですが、私はそれが現在の分布の一部であるかどうかわからないなど)
しかし、それはすべて<!> quot;元に戻す変更<!> quot;最終的には。
eg revert --since HEAD~3 # Undo all changes since HEAD~3
eg revert --in HEAD~8 # much like git revert HEAD~8, but nocommit by default
eg revert --since HEAD foo.py # Undo changes to foo.py since last commit
eg revert foo.py # Same as above
eg revert --in trial~7 bar.c baz. # Undo changes made in trial~7 to bar.[ch]
これらの種類の<!> quot; reverting data <!> quot;本当に非常に異なるため、異なるコマンドが必要なのでしょうか、またはこれらの操作の一部は単純な復帰コマンドでサポートされないのでしょうか?
もちろん、ほとんどのユーザーはほとんどの場合<!> quot;eg revert FILE1 FILE2...
<!> quot;を使用します。 フォームですが、追加の機能をサポートしても害はありませんでした。また、コアgitがこのような動作を採用できないようにする基本的なものはありますか?
エリヤ
注:デフォルトのコミットは、一般化された
revert
コマンド、および<!> quot;git revert REVISION
<!> quot;には意味がありません。指示でエラーが発生します(ユーザーに--inフラグを追加するように指示します)。
50個のコミットされたファイルのうち、20個のファイルがあるとしましょう。古いコミットXは、実行すべきではない変更を導入したことに気付きます。
少し配管が整っています。
必要なのは、元に戻す
に必要な特定のファイルをすべてリストする方法です
( <!> quot;のように、コミットXで行われた変更をキャンセルし、その後のすべての変更を保持します<!> quot; )、
そして、それらのそれぞれについて:
git-merge-file -p a.py X X^
ここでの問題は、a.py内の後続のすべての変更を消去せずに失われた機能を回復することです。
この手法は、<!> quot;ネガティブマージ<!> quot;と呼ばれることもあります。
git merge-file <current-file> <base-file> <other-file>
から意味:
<base-file>
から<other-file>
に至るすべての変更を<current-file>
に組み込む場合、すべての変更を組み込むことを言って、削除された機能を復元できます。
- from:X(関数が削除された場所)
- to:X ^(Xの前の以前のコミットで、関数がまだあった場所)
注: '-p
' 引数を使用すると、curで何もせずに最初に変更を確認できますファイルをレンタルします。確信したら、そのオプションを削除してください。
注: git merge-file
はそれほど単純ではない:ファイルの以前のバージョンをそのように参照することはできません。
(イライラするようなメッセージが何度もあります: error: Could not stat X
)
必要なこと:
git cat-file blob a.py > tmp/ori # current file before any modification
git cat-file blob HEAD~2:a.py > tmp/X # file with the function deleted
git cat-file blob HEAD~3:a.py > tmp/F # file with the function which was still there
git merge-file a.py tmp/X tmp/F # basically a RCS-style merge
# note the inversed commit order: X as based, then F
# that is why is is a "negative merge"
diff -u a.py tmp/ori # eyeball the merge result
git add a.py
git commit -m "function restored" # and any other changes made from X are preserved!
以前のコミット内の多数のファイルに対してこれを行う場合...いくつかのスクリプトが順番に並んでいます;)
VonC が指摘したように、checkout
ブランチ(マスターまたはトランクまたはその他)をdiff
元に戻し、新しいコミットとして処理するファイルのバージョンを指定します:
$ git checkout trunk
$ git checkout 4f4k2a^ a.py
$ git add a.py
$ git diff #verify I'm only changing what I want; edit as needed
$ git commit -m 'recover function deleted from a.py in 4f4k2a'
おそらくこれを直接行う配管コマンドがありますが、知っている場合は使用しません。 Gitを信頼していないわけではありませんが、自分自身を信頼していません-そのコミット以降、そのファイルで何が変更されたかを見ずに知っていたことを信頼しません。そして、一度見てみると、<=>を編集して新しいコミットを作成する方が簡単です。おそらくそれは単なる個人的なワークスタイルです。
このgit revertをご覧ください質問。 最新のコミットを含む連続したシーケンスでない場合、古いコミットを元に戻す問題があるようです。