Gitで1つのファイルの作業コピーの変更を元に戻しますか?


1634

最後のコミット後、作業コピー内の一連のファイルを変更しましたが、最新のコミットと同じ状態にリセットする場合のように、それらのファイルの1つに対する変更を元に戻したいです。

ただし、その1つのファイルだけの作業コピーの変更のみを元に戻したいので、それ以外には何もしません。

それ、どうやったら出来るの?

回答:


2215

使用できます

git checkout -- file

--(nimrodmで提案されているように)なしでも実行できますが、ファイル名がブランチやタグ(または他のリビジョンID)のように見える場合、混乱する可能性があるため、使用するの--が最善です。

ファイルの特定のバージョンをチェックアウトすることもできます。

git checkout v1.2.3 -- file         # tag v1.2.3
git checkout stable -- file         # stable branch
git checkout origin/master -- file  # upstream master
git checkout HEAD -- file           # the version from the most recent commit
git checkout HEAD^ -- file          # the version before the most recent commit

34
HEADとHEAD ^の違いは何ですか?
hasen 2009年

62
HEADは現在のブランチでの最新のコミットで、HEAD ^は現在のブランチでのその前のコミットです。あなたが説明する状況では、git checkout HEAD-filenameを使用できます。
ポール

16
要するに、「git checkout sha-reference-filename」。ここで、sha-referenceは、任意の形式(ブランチ、タグ、親など)でのコミットのshaへの参照です
Lakshman Prasad

29
注:ファイルが既にステージングされている場合は、まずそれをリセットする必要があります。 git reset HEAD <filename> ; git checkout -- <filename>
Olie

14
@gwhoはい、HEAD^^最新のコミットから2コミット、またはHEAD^^^3コミット前に行うことができます。HEAD~2またはHEAD~3、を使用することもできます。これは、より多くのコミットを戻したい場合に便利ですが、HEAD^2「このコミットの2番目の親」を意味します。マージコミットのため、コミットは前のコミットを複数持つことができるためHEAD^、数値を指定するとそれらの親のどれが選択されるか、数値を指定するとHEAD~常に最初の親が選択されますが、その数のコミットが戻ります。詳細についてはgit help rev-parse、を参照してください。
ブライアンキャンベル

139

使うだけ

git checkout filename

これにより、ファイル名が現在のブランチの最新バージョンに置き換えられます。

警告:変更は破棄されます—バックアップは保持されません。


22
@duckxファイル名からブランチ名を明確にすることです。あなたが言ってgit checkout x、xがファイル名と同様にブランチ名である場合、デフォルトの動作が何であるかはわかりませんが、gitはブランチxに切り替えたいと思います。あなたが使用--するとき、あなたは以下がファイル名であると言っています。
Hasen

1
icそれを片付けてくれてありがとう。誰もがあなたが何を知っていると思い込んでいます-彼らがあなたに例を示すときを意味します。簡単にグーグルできるものではありません。
Patoshiパトシ

1
回答を編集してから削除し--たようです。まだ正しいですが、@ hasenが指摘しているように、ファイル名とブランチ名のあいまいさがあると、非常に望ましくない動作が発生する可能性があります。
BrainSlugs83 2015年

2
私はそれがそうであるように、それなしで--、素晴らしくて簡単です。ファイル名を使用してブランチに名前を付ける場合、どこかに悪い考えがあるはずです...
Marco Faustinelli 2017

133
git checkout <commit> <filename>

drupal 6.10にアップグレードしたとき、私のファビコンが数回前のコミットで上書きされていることに気付いたので、今日使用したので、それを元に戻す必要がありました。これが私がしたことです:

git checkout 088ecd favicon.ico

1
"git log --stat"出力のスクロールスロートンを除いて、(以前に削除されたファイルの)コミットを取得するにはどうすればよいですか?
Alex

4
IMOコマンドラインでgitsログをスキャンして適切なファイルを見つけるのは、ちょっと難しいです。sourcetreeapp.com
neoneye

6
git log --oneline <filename> よりコンパクトなログが得られ、特定のファイルへの変更のみが含まれます
rjmunro

1
または、次の方法も使用できますgit reflog <filename>
ygesher

70

ファイルが既にステージングされている場合(ファイルの編集後にgit addなどを実行した場合に発生します)、変更をステージング解除します。

使用する

git reset HEAD <file>

その後

git checkout <file>

まだ上演されていない場合は、

git checkout <file>

2
これは、受け入れられたものよりも役に立ちました。ステージングされた変更とそうでない変更を忘れるのは簡単なので、リセットすると役立ちました。以前にも「git reset --hard」を試しましたが、「git reset HEAD」のようにはいませんでした。なんでかしら?
Arman Bimatov 2014年

20

その1つのファイルに対する以前のコミットの変更を取り消すだけの場合は、次のように試すことができます。

git checkout branchname^ filename

これにより、前回のコミットの前と同じようにファイルがチェックアウトされます。もう少しコミットを取り戻したい場合は、branchname~n表記法を使用してください。


これは変更をコミットから削除せず、HEADのバージョンに差分を適用するだけです。
FernandoEscher

2
真実ではありますが、元の投稿者は自分の作業コピーの変更を元に戻したいと思っていました(私が思うに)、最後のコミットからの変更を元に戻しませんでした。元の投稿者の質問は少し不明瞭だったので、混乱を理解できます。

多分OPの使用ではないかもしれませんが、私は私のブランチをマスターのコピーで上書きする方法を探していました-これは置き換えるときに非常にうまく機能しますbranchname^
Alex

15

git bashを完了しました。

(use "git checkout -- <file>..." to discard changes in working directory)

  1. Gitステータス。[そのため、1つのファイルが変更されているのを見てきました。]
  2. git checkout-index.html [私はindex.htmlファイルで変更しました:
  3. git status [これらの変更は削除されました]

ここに画像の説明を入力してください


8

私はいつもこれに戸惑うので、ここにリマインダテストケースを示します。bashテストするこのスクリプトがあるとしましょうgit

set -x
rm -rf test
mkdir test
cd test
git init
git config user.name test
git config user.email test@test.com
echo 1 > a.txt
echo 1 > b.txt
git add *
git commit -m "initial commit"
echo 2 >> b.txt
git add b.txt
git commit -m "second commit"
echo 3 >> b.txt

この時点では、変更はキャッシュにステージングされていないため、次のようになりgit statusます。

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

この時点から、私たちはそうするならgit checkout、結果はこれです:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

代わりにを実行するgit resetと、結果は次のようになります。

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

だから、この場合-変更が上演されていない場合は、git resetしばらくは、違いはありませんgit checkout変更を上書きします。


ここで、上記のスクリプトからの最後の変更がステージング/キャッシュされたとしましょう。つまり、最後に変更したとしましょうgit add b.txt

この場合、git statusこの時点で:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   b.txt

この時点から、私たちはそうするならgit checkout、結果はこれです:

$ git checkout HEAD -- b.txt
$ git status
On branch master
nothing to commit, working directory clean

代わりにを実行するgit resetと、結果は次のようになります。

$ git reset HEAD -- b.txt
Unstaged changes after reset:
M   b.txt
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   b.txt

no changes added to commit (use "git add" and/or "git commit -a")

したがって、この場合-変更が段階的である場合、git reset基本的に段階的変更が非段階的変更にgit checkoutなりますが、変更は完全に上書きされます。


7

この回答は、同じまたは複数のフォルダー(またはディレクトリ)内の複数の特定のファイルにあるローカルの変更を元に戻すために必要なコマンド用です。これは、ユーザーが複数のファイルを持っているが、ユーザーがすべてのローカル変更を元に戻したくないという質問に具体的に回答します。

1つ以上のファイルがある場合、次のgit checkout -- fileようにスペースで区切られたそれぞれの場所をリストすることにより、それらの各ファイルに同じコマンド()を適用できます。

git checkout -- name1/name2/fileOne.ext nameA/subFolder/fileTwo.ext

上記のname1 / name2 / fileOne.extとnameA / subFolder / fileTwo.extの間のスペースに注意してください

同じフォルダー内の複数のファイルの場合:

特定のディレクトリにあるすべてのファイルの変更を破棄する必要がある場合は、次のようにgitチェックアウトを使用します。

git checkout -- name1/name2/*

上記のアスタリスクは、name1 / name2の下のその場所にあるすべてのファイルを元に戻すトリックです。

また、同様に、以下は複数のフォルダのすべてのファイルの変更を取り消すことができます。

git checkout -- name1/name2/* nameA/subFolder/*

もう一度、上記のname1 / name2 / * nameA / subFolder / *の間のスペースに注意してください。

注:name1、name2、nameA、subFolder-これらのサンプルフォルダー名はすべて、問題のファイルが存在する可能性のあるフォルダーまたはパッケージを示します。


5

SHA IDを使用してファイルを復元します。 git checkout <sha hash id> <file name>



2

まだコミットをプッシュしていないか、コミットを共有していない場合:

git diff --stat HEAD^...HEAD | \
fgrep filename_snippet_to_revert | cut -d' ' -f2 | xargs git checkout HEAD^ --
git commit -a --amend

0

すでにコミットされている場合は、ファイルの変更を元に戻して再度コミットし、最後のコミットで新しいコミットを押しつぶすことができます。


1
使用する特定のコマンドを追加すると、元のポスターと将来の訪問者に役立ちます。
エイドリアン

0

理由はわかりませんが、コードを入力しようとすると、画像として表示されます。

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.