最後のコミットの後、作業コピー内の多数のファイルを変更しましたが、最新のコミットと同じ状態にリセットするなど、それらのファイルの 1 つに対する変更を元に戻したいと考えています。
ただし、その1つのファイルのみの作業コピーの変更を元に戻したいだけで、他には何もありません。
それ、どうやったら出来るの?
最後のコミットの後、作業コピー内の多数のファイルを変更しましたが、最新のコミットと同じ状態にリセットするなど、それらのファイルの 1 つに対する変更を元に戻したいと考えています。
ただし、その1つのファイルのみの作業コピーの変更を元に戻したいだけで、他には何もありません。
それ、どうやったら出来るの?
使用できます
git checkout -- file
(nimrodm で提案されているように)なしで実行できます--
が、ファイル名がブランチまたはタグ (またはその他のリビジョン識別子) のように見える場合、混乱する可能性があるため、使用する--
のが最適です。
ファイルの特定のバージョンをチェックアウトすることもできます。
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
使うだけ
git checkout filename
これにより、ファイル名が現在のブランチの最新バージョンに置き換えられます。
警告: 変更は破棄されます — バックアップは保持されません。
git checkout <commit> <filename>
drupal 6.10にアップグレードしたときに、ファビコンが数コミット前に上書きされていることに気付いたため、今日これを使用しました。そのため、ファビコンを元に戻す必要がありました。これが私がしたことです:
git checkout 088ecd favicon.ico
ファイルが既にステージングされている場合 (ファイルの編集後に git add などを実行すると発生します)、変更をステージング解除します。
使用する
git reset HEAD <file>
それで
git checkout <file>
まだステージングされていない場合は、そのまま使用してください
git checkout <file>
その 1 つのファイルに対する以前のコミットの変更を元に戻したい場合は、次のようにします。
git checkout branchname^ filename
これにより、最後のコミット前と同じようにファイルがチェックアウトされます。さらにいくつかのコミットをさかのぼりたい場合は、branchname~n
表記法を使用してください。
私はいつもこれに混乱するので、ここにテストケースを思い出してください。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
は基本的にステージングされた変更をステージングされていない変更にします - whilegit checkout
は変更を完全に上書きします。
SHA ID を使用してファイルを復元します。git checkout <sha hash id> <file name>
コミットをまだプッシュまたは共有していない場合:
git diff --stat HEAD^...HEAD | \
fgrep filename_snippet_to_revert | cut -d' ' -f2 | xargs git checkout HEAD^ --
git commit -a --amend