58

多くのコミットと多くのファイルを含む git ツリーがあります。ここで、ファイルのみに触れる特定のコミットを元に戻したいと思います。説明する:

> git init
Initialized empty Git repository in /home/psankar/specific/.git/
> echo "File a" > a
> git add a ; git commit -m "File a"
[master (root-commit) 5267c21] File a
 1 file changed, 1 insertion(+)
 create mode 100644 a
> echo "File b" > b
> git add b; git commit -m "File b"
[master 7b560ae] File b
 1 file changed, 1 insertion(+)
 create mode 100644 b
> echo "File c" > c
> git add c; git commit -m "File c"
[master fd6c132] File c
 1 file changed, 1 insertion(+)
 create mode 100644 c
> echo "b and c modified" > b ; cp b c
> git commit -a -m "b and c modified"
[master 1d8b062] b and c modified
 2 files changed, 2 insertions(+), 2 deletions(-)
> echo "a modified" > a
> git commit -a -m "a modified"
[master 5b7e0cd] a modified
 1 file changed, 1 insertion(+), 1 deletion(-)
> echo "c modified" > c
> git commit -a -m "c modified"
[master b49eb8e] c modified
 1 file changed, 1 insertion(+), 1 deletion(-)
> git log --pretty=oneline c
> git log --pretty=oneline c | cat
b49eb8e03af331bddf90342af7d076f831282bc9 c modified
1d8b062748f23d5b75a77f120930af6610b8ff98 b and c modified
fd6c13282ae887598d39bcd894c050878c53ccf1 File c

ここで、変更を a . IOW は、ファイル内のコミットのみを元に戻します (異なるファイル内の他の中間コミット (数千になる場合があります) を元に戻すことはありません)。これはどのように可能ですか?

4

2 に答える 2

104

git revertオプションでご利用いただけ--no-commitます。あなたの例では:

$ git revert --no-commit b49eb8e 1d8b062
# Files that were modified in those 2 commits will be changed in your working directory
# If any of those 2 commits had changed the file 'a' then you could discard the revert for it:
$ git checkout a
$ git commit -a -m "Revert commits b49eb8e and 1d8b062"

--no-commitオプションは自動コミットを行わず、独自のコミットメッセージを編集および追加できます

とは異なり、元に戻されたすべてのコミットはまだコミット履歴にあることに注意しgit resetgit revertください

于 2013-12-02T09:57:24.483 に答える
13

ここには 2 つのケースがあります。

  1. すでに git ツリーをどこかにプッシュしていて、履歴を変更したくない場合。この場合、以前のコミットを元に戻す際に行った変更を表す新しいコミットが必要になります。@mamapitufoの回答を使用する必要があります。

  2. 変更があるブランチをプッシュしたことがない場合は、履歴を変更できます。この場合、不要なコミットを完全に削除できます。これは歴史を整理し、同僚や一般の人々に間違った方向転換を押し付けないことを意味します.

2 番目のケースでは、 を実行する必要がありますgit rebase -i。変更したい履歴の前にあるコミットを見つけます。これは、コミットのハッシュ、またはブランチまたはタグの名前である可能性があります。たとえば、次のことができます

git rebase -i 23def8231

または、ブランチから開始して、ブランチorigin/dev_branchで削除するビットを含む作業を行ったdev_branch場合、次のことができます。

git rebase -i origin/dev_branch

ここで、リベースしているすべてのコミットのリストを表示できるエディター ウィンドウに送信されます。これは可能性がありますvim-通常ターミナルで編集しない場合は、デフォルトとして設定できます。その場合は、おそらく vim のクイック スタート ガイドとオープン マインドが必要になるでしょう。

ここで、最も簡単な方法は、コミットを削除することです。これを行うには、行を削除するか#、コメントを示す a を行の先頭に追加します。(ファイルには、説明のためのコメントが既にいくつかあります。これらを無視したり、削除したりしても効果はありません。)

終了したら、ファイルを保存してエディターを終了します。リベースは次のように行われます: git は名前を付けたコミットに戻ります。保存したリストを調べて、そのリスト内の各コミットを再生します。次に、そのプロセスの結果を、元のブランチの新しいバージョンにします。

覚えておくべき重要事項:

  • 行を見失ったり、削除しすぎたりした場合は、ファイル内のすべてのコミット行を削除して保存することで、リベースをキャンセルできます。リベース プロセスは、何も変更されずに終了します。
  • 競合を作成することは可能です。たとえば、ファイルを編集するコミットを削除し、同じ場所を編集する後のコミットに残す場合。後のコミットは正しく適用されず、手動で編集するか、マージ ツールで必要なバージョンを取得する必要があります。

で他の多くの操作を行うこともできますgit rebase -i。たとえば、コミットの順序を変更したり、いくつかを 1 つにまとめたり、コミット間に変更を追加したり、メッセージを変更したりします。とても便利です。古典的な使用例は、ローカル ブランチをクリーンアップしてから、他の人が変更を確認できる場所にプッシュすることです。

于 2015-10-10T23:14:03.553 に答える