ファイルを特定のリビジョンにリセットまたは戻すにはどうすればよいですか?


4517

ファイルのグループの一部として数回コミットされたファイルにいくつかの変更を加えましたが、その変更をリセット/元のバージョンに戻したいと思います。

私が行っているgit logと一緒にgit diff、私は必要な改正を見つけることが、ちょうど過去に元の状態にファイルを取り戻すためにどのようには考えています。


11
元に戻した後--cached、確認するときに忘れないでくださいgit diffリンク
Geoffrey Hale

5
私が私のグーグル検索をしたとき、私はあなたの質問を見つけました。しかし、解決策を読んだ後、ログをチェックしたところ、thouseの変更をスタンドアロンコミットとして行ったので、そのコミットに対してgit revertを実行しました。解決策ではなく、時々それを行うための別の方法です。
sudo97 2017

回答:


6136

あなたが望むコミットのハッシュを仮定するとc5f567

git checkout c5f567 -- file1/to/restore file2/to/restore

詳細については、git checkoutの manページを参照してください。

c5f567にコミットに戻したい場合は、追加します~1(1は、戻りたいコミットの数です。何でもかまいません)。

git checkout c5f567~1 -- file1/to/restore file2/to/restore

余談ですが、このコマンドは通常のこと(ブランチ間の変更)と異常で破壊的なもの(作業ディレクトリの変更を破棄すること)の両方に使用されるため、私は常にこのコマンドに不快でした。


12
@shadowhand:それを逆にする方法はありますか?それで、それは直後のバージョンです?
aliteralmind 2014

16
@aliteralmind:いいえ、残念ながら、Git履歴のショートカット表記は履歴内で逆方向にしか進みません。
グレッグ・ヒューギル2014

46
あなたがのためにブランチ名を使用するつもりならABCDE(例えばdevelopあなたが欲しいよ)git checkout develop -- file/to/restore(ダブルダッシュに注意してください)
オハッドシュナイダー

8
@aliteralmind:実際には、はい、それを行う方法があります: "git log --reverse -1 --ancestry-path yourgitrev..master"そして、適切なオプションを使用してgit revを取得します。--ancestry-pathは2つのコミットの間に「線を引き」、-1は1つのバージョンのみを表示し、-reverseは最初に発行されたエントリが最も古いものであることを確認します。
Chris Cogdon、2014年

6
個人的には、HEAD ^は
HEAD〜1

606

diffコマンドを使用して、ファイルに加えられた変更をすばやく確認できます。

git diff <commit hash> <filename>

次に、特定のファイルをそのコミットに戻すには、resetコマンドを使用します。

git reset <commit hash> <filename>

--hardローカルの変更がある場合は、このオプションを使用する必要がある場合があります。

ウェイポイントを管理するための適切なワークフローは、タグを使用してタイムラインのポイントを明確にマークすることです。私はあなたの最後の文を完全に理解することはできませんが、あなたが望むかもしれないのは、前の時点からブランチを分岐させることです。これを行うには、便利なチェックアウトコマンドを使用します。

git checkout <commit hash>
git checkout -b <new branch name>

これらの変更をマージする準備ができたら、メインラインに対してリベースできます。

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

7
'git checkout <commit hash>'コマンドを使用すると、サンクスクリスを検索していたプロジェクトの以前のバージョンが返されます。
vidur punj 2013年

48
ファイルを元に戻すgit checkout <commit hash> <filename>方が私にとってはうまくいきましたgit reset
Motti Strom

3
コピー/貼り付けを不適切に選択して150行を上書きしてしまったため、単一ファイルの初期バージョンが必要でした。 git checkout <commit hash> <filename>私のために働いた。これは受け入れられた答えではありません、私見。 git resetしませんでした。
harperville、2014

24
を使用git resetして単一のファイルをリセットすることはできません。エラーが発生しますfatal: Cannot do hard reset with paths
slier

13
スライアーが言ったこと:あなたはできませんgit reset --hard <commit hash> <filename>。これは、fatal: Cannot do hard reset with paths.Motti Stromの発言に誤りがあります。使用git checkout <commit hash> <filename>
Hawkeye Parker、

366

SHA-1を含めて、gitコミットへの参照を使用できます。ポイントは、コマンドが次のようになることです。

git checkout [commit-ref] -- [filename]


22
を持っているこの答えと持っ--ていない受け入れられた答えの違いは何ですか?
2rs2ts 2014年

80
gitでは、ファイルリストの前の「-」は、次のすべての引数をブランチ名やその他のものではなく、ファイル名として解釈する必要があることをgitに伝えます。それは時々役立つ曖昧さ回避手段です。
foxxtrot 2014年

49
'-'はgitの規則であるだけでなく、* nixコマンドラインのさまざまな場所で見つけられるものです。 rm -- -f(という名前のファイルを削除する-f)は、標準的な例のようです。詳細はこちら
ホークアイパーカー

7
@HawkeyeParkerの発言に追加するだけで、 rmコマンドはgetopt(3)を使用して引数を解析します。getoptコマンド引数を解析するコマンドです。gnu.org/software/libc/manual/html_node/Getopt.html
Devy

2
@ハニーはい、それが私の言いたいことです。そうです、おそらく一般的ではありません。私はその例をさまざまな場所で見たことがあります。おそらくそれを一種の記憶に残るようにするためです。rm-fは怖い/危険なことで有名です。ただし、要点は、* nixではファイル名「-」で始めることができるため、「-」が表示されたときにコマンドオプションが続くことを期待するさまざまなコマンドラインインタープリターが混乱することです。'-'で始まる任意のファイルを指定できます。例:「-mySpecialFile」。
Hawkeye Parker

288
git checkout -- foo

これはfooHEADにリセットされます。あなたもすることができます:

git checkout HEAD^ foo

1つのリビジョンのバックなど


12
何か特別なもの(ディレクトリやと呼ばれるファイルなど)があるgit checkout -- foo場合fooは、間違いを避けるために構文を使用することをお勧めします-f。gitでは、不明な場合は、常にすべてのファイルとディレクトリの前に特別な引数を付けます--
Mikko Rantalainen 2013年

8
Mikkoのコメントへの追加のメモ:--gitコマンドではなく、gitに特別ではありません。これは、コマンドオプションの終わりを示すbashビルトインです。他の多くのbashコマンドでも使用できます。
matthaeus 2016年

14
@matthaeusは、bashやシェル機能に固有のものでもありません。これは、多くの異なるコマンドで実装された規則です(getoptでサポートされています)。
グレッグヒューギル2016年

2
いいえ、--ありません bashの中に組み込み、特別な言葉。しかし、これは多くのコマンドラインパーサーでサポートされ、gitを含む多くのCLIで使用される一般的な規則です。
Emil Lundberg、

123

そして、最も頻繁に必要とされる最後にコミットされたバージョンに戻すには、この単純なコマンドを使用できます。

git checkout HEAD file/to/restore

2
これ(git checkout HEAD file / to / restore)とgit reset --hard file / to / restoreの違いは何ですか?
Motti Shneor 16年

2
1)より一般的な方法で覚えやすい2)ファイル名を入力する前にEnterキーを押す心配はありません
Roman Susi

105

私は今同じ問題を抱えていましたが、この答えが最もわかりやすいと思いました(commit-ref戻りたいログの変更のSHA値です)。

git checkout [commit-ref] [filename]

これにより、古いバージョンが作業ディレクトリに配置され、必要に応じてそこからコミットできます。


91

戻る必要があるコミットの数がわかっている場合は、以下を使用できます。

git checkout master~5 image.png

これは、masterブランチ上にいて、必要なバージョンが5コミット戻っていることを前提としています。


80

私はそれを見つけたと思います...... http://www-cs-students.stanford.edu/~blynn/gitmagic/ch02.htmlから

すべてが間違っているため、特定の時点を過ぎたすべての変更を忘れてしまいたい場合があります。

皮切りに:

$ git log

最近のコミットとそのSHA1ハッシュのリストが表示されます。

次に、次のように入力します。

$ git reset --hard SHA1_HASH

状態を特定のコミットに復元し、新しいコミットをすべてレコードから完全に消去します。


24
Gitは何も削除しません。あなたの古いコミットはまだそこにありますが、それらを指すブランチのヒントがない限り、それらはもう到達できません。git reflogは、git-gcでリポジトリをクリーンアップするまで引き続き表示します。
Bombe

1
@ボンベ:情報ありがとうございます。古いバージョンのファイルをチェックアウトしました。コメントを読んだ後、「gitref」を使用して部分的なSHA1ハッシュを検索し、「checkout」を使用して最新バージョンに戻すことができました。他のgitユーザーは、この情報が役立つ場合があります。
ウィンストンC.ヤン

4
後にaが続く可能性がありますgit push --force
bshirley

4
コミットされていない変更がある場合、git reset --hard
Bokluciusを

5
@Bombe-「Gitは何も削除しません。古いコミットはまだ残っていますが、それらを指すブランチのヒントがない限り、それらはもう到達できません。」-しかし、このようなコミットは一定の時間の経過後に枝刈りされるため、「Gitは何も削除しない」は正しくありません。
Bulwersator 2014

61

これは私のために働きました:

git checkout <commit hash> file

次に、変更をコミットします。

git commit -a

54

「ロールバック」と言うときは注意が必要です。コミット$ Aで1つのバージョンのファイルを使用していて、後で2つの異なるコミット$ Bと$ Cで2つの変更を行った場合(表示されているのはファイルの3番目の反復です)、「最初のロールバックに戻したい」という意味ですか?

2番目と3番目の両方の変更を取り除きたい場合は、非常に簡単です。

$ git checkout $A file

そして結果をコミットします。コマンドは、「コミット$ Aによって記録された状態からファイルをチェックアウトしたい」と尋ねます。

一方、あなたが意図したのは、2回目の反復(つまり$ Bのコミット)によってもたらされた変更を取り除くことであり、$ Cがファイルに対して行ったコミットを維持しながら、$ Bを元に戻したいと思うでしょう。

$ git revert $B

コミット$ Bを作成した人は、あまり規律がよくなく、まったく関係のない変更を同じコミットでコミットした可能性があることに注意してください。この復帰は、問題のある変更が表示されているファイル以外のファイルに影響を与える可能性があるため、実行後に結果を慎重に確認することをお勧めしますそう。


私はこれを行いましたが、「git log file」は私が元のコミットであるHEADにいたと言います。「git checkout」が失敗したようです。ただし、gitステータスはファイルが実際に変更されたことを示し、「git diff --staged file」は実際の変更を示します。また、「git status」はファイルが変更されたことも示しています。したがって、ここで「git log」を使用して、変更されたファイルを追跡しないでください。
Frederick Ollinger

37

面白いgit checkout fooことに、作業コピーがという名前のディレクトリにある場合は機能しませんfoo。しかし、両方git checkout HEAD foogit checkout ./fooなります:

$ pwd
/Users/aaron/Documents/work/foo
$ git checkout foo
D   foo
Already on "foo"
$ git checkout ./foo
$ git checkout HEAD foo

26
またはgit checkout -- foo
knittl 2010年

32

仕組みrebaseは次のとおりです。

git checkout <my branch>
git rebase master
git checkout master
git merge <my branch>

あなたが持っていると仮定します

---o----o----o----o  master
    \---A----B       <my branch>

最初の2つのコマンド... commit git checkout git rebase master

...ブランチに適用する変更のブランチをチェックアウトしますmasterrebaseコマンドは、コミットから取る<my branch>(で発見されていないmaster)との頭部に再適用してmaster。つまり、最初のコミットの親は<my branch>master履歴の以前のコミットではなく、現在のヘッドですmaster。2つのコマンドは次のものと同じです。

git rebase master <my branch>

「base」ブランチと「modify」ブランチの両方が明示的であるため、このコマンドを覚えておくと便利です。

。最終的な履歴結果は次のとおりです。

---o----o----o----o   master
                   \----A'----B'  <my branch>

最後の2つのコマンド...

git checkout master
git merge <my branch>

...早送りマージを実行して、すべての<my branch>変更をに適用しますmaster。この手順がないと、リベースコミットはに追加されませんmaster。最終結果は次のとおりです。

---o----o----o----o----A'----B'  master, <my branch>

master<my branch>両方の参照B'。また、この時点から<my branch>参照を削除しても安全です。

git branch -d <my branch>

26

git v2.23.0以降、新しいgit復元メソッドがあり、原因となっているものの一部を引き受けることになってgit checkoutいます(受け入れられた回答でさえ、git checkoutかなり混乱していると述べています)。githubブログで変更点のハイライトをご覧ください。

このコマンドのデフォルトの動作は、sourceパラメーター(この場合はコミットハッシュ)からのコンテンツで作業ツリーの状態を復元することです。

したがって、Greg Hewgillの回答(コミットハッシュがであると想定c5f567)に基づいて、コマンドは次のようになります。

git restore --source=c5f567 file1/to/restore file2/to/restore

または、c5f567の前に1つのコミットの内容に復元する場合:

git restore --source=c5f567~1 file1/to/restore file2/to/restore

24

ターゲットファイルの最初のリセットヘッド

git reset HEAD path_to_file

そのファイルの2番目のチェックアウト

git checkout -- path_to_file

4
+1、ただしHEADをリセットする意図は不明。必要な場合と必要でない場合があります。私のような状況で私は無傷で残っているローカルでの変更を保つた(リポジトリ内のバージョンにある特定のファイルを元に戻すしたかっただけでは、上記第2のステップは私のために十分であった実行している。
FKL

はい、2番目のコマンドを実行するだけで済みます。例-> shellhacks.com/git-revert-file-to-previous-commit
javaPlease42

22

git-aliases、awk、shell-functionsが役に立ちます!

git prevision <N> <filename>

ここ<N>で、fileに対してロールバックするファイルのリビジョンの数です<filename>
たとえば、1つのファイルの直前のリビジョンをチェックアウトするには、次のコマンドx/y/z.cを実行します。

git prevision -1 x/y/z.c

git previsionはどのように機能しますか?

以下をあなたに追加してください gitconfig

[alias]
        prevision = "!f() { git checkout `git log --oneline $2 |  awk -v commit="$1" 'FNR == -commit+1 {print $1}'` $2;} ;f"

コマンドは基本的に

  • git log指定されたファイル に対してを実行し、
  • ファイルの履歴から適切なcommit-idを選択し、
  • git checkout指定されたファイルのcommit-idに対してa を実行します。

基本的に、この状況で手動で行うことはすべて、1
つの美しく効率的なgitエイリアスにまとめられます-git-prevision


20

私はここにEasyGitを接続する必要があります。これは、熟練したユーザーを混乱させることなく、初心者がgitをより親しみやすくするためのラッパーです。それが行うgit revertことの一つは、より多くの意味を与えることです。この場合、次のように言うだけです。

eg revert foo/bar foo/baz


1
それはあるはずですeg revert --in REVISON -- FILENAME--in重要です。Windowsユーザーの場合:git bashを開きます。を実行しecho %PATHます。最初のパスは、ユーザーディレクトリの末尾がである必要がありますbin。そのパスを作成します。保管などがあります。名前を付けegます。ないeg.txt
koppor 16

20

ファイルを以前のコミットに戻したい場合(そしてすでにコミットされているファイルを戻したい場合)は、

git checkout HEAD^1 path/to/file

または

git checkout HEAD~1 path/to/file

次に、「新しい」バージョンをステージングしてコミットします。

マージの場合、コミットは2つの親を持つことができるという知識で武装して、HEAD ^ 1が最初の親であり、HEAD〜1が2番目の親であることを知っている必要があります。

ツリーに親が1つしかない場合はどちらでも機能します。


19

ここでは、ほとんどがに沿った多くの提案がありますgit checkout $revision -- $file。いくつかのあいまいな代替案:

git show $revision:$file > $file

また、特定のバージョンを一時的に表示するためだけに、これを頻繁に使用しています。

git show $revision:$file

または

git show $revision:$file | vim -R -

(OBS:機能$fileするため./の相対パスの場合は、プレフィックスを付ける必要がありますgit show $revision:$file

そしてさらに奇妙な:

git archive $revision $file | tar -x0 > $file

1
これは、どのコミットバージョンが必要かわからず、作業ディレクトリを上書きせずに「調べる」必要がある場合に便利な代替手段です。
wisbucky 2018

18

ただし、git checkout ./fooおよびgit checkout HEAD ./foo でない、正確に同じこと。適例:

$ echo A > foo
$ git add foo
$ git commit -m 'A' foo
Created commit a1f085f: A
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 foo
$ echo B >> foo
$ git add foo
$ echo C >> foo
$ cat foo
A
B
C
$ git checkout ./foo
$ cat foo
A
B
$ git checkout HEAD ./foo
$ cat foo
A

(2番目addはインデックス内のファイルをステージングしますが、コミットされませ。)

Git checkout ./fooインデックス./fooからパスを元に戻すことを意味します。追加HEADすることで、Gitに、インデックス内のそのパスをHEADリビジョンに戻すように指示します 。


14

私にとって返事は本当にはっきりしているようには見えなかったので、とても簡単に思える私のものを追加したいと思います。

私はコミットしていてabc1、その後、ファイルにいくつか(または1つの変更)を加えましたfile.txt

今、私はファイルの何かを台無しにしたfile.txtので、以前のコミットに戻りたいと言いますabc1

1 git checkout file.txt.:ローカルの変更が不要な場合は、これを削除します

2.:git checkout abc1 file.txtこれにより、ファイルが必要なバージョンになります

3 git commit -m "Restored file.txt to version abc1".:これにより、復帰がコミットされます。

  1. git push :これはすべてをリモートリポジトリにプッシュします

もちろん、ステップ2と3の間で、git status何が起こっているのかを理解することができます。通常は、file.txtすでに追加されているはずgit addです。そのため、の必要はありません。


2
OK私は、ステップ1と2を推測するように、相互に排他的です:ABC1があなたの最後であれば2の必要がない、あなたが直接2.を行うことができますABC1後、他のコミットがあった場合にコミット
ジャンポール

13
  1. Gitはファイルを特定のコミットに戻します
git checkout Last_Stable_commit_Number -- fileName

2.gitはファイルを特定のブランチに戻します

git checkout branchName_Which_Has_stable_Commit fileName

11

ファイルの以前のコミットバージョンに移動するには、コミット番号を取得します。次にeb917a1と入力します。

git checkout eb917a1 YourFileName

最後にコミットしたバージョンに戻る必要がある場合

git reset HEAD YourFileName
git checkout YourFileName

これにより、ファイルの最後にコミットされた状態に移動します



10

多くのここでの回答の請求に使用するgit reset ... <file>か、git checkout ... <file>そうすることによって、あなたは上のすべての変更を失うことになる<file>あなたは戻したいコミット後にコミット。

あなたは1から変更を元に戻したい場合のみ、単一のファイルにコミットし、同じようにgit revertやるだけ一つのファイル(またはファイルをコミットのサブセットを言う)のためでしょう、私は両方を使用することをお勧めgit diffしてgit apply(その等と<sha>の=ハッシュ元に戻したいコミット):

git diff <sha>^ <sha> path/to/file.ext | git apply -R

基本的には、元に戻したい変更に対応するパッチを最初に生成し、次にパッチを逆適用してそれらの変更を削除します。

もちろん、元に戻された行が<sha1>and 間のコミットHEAD(競合)によって変更された場合は機能しません。


それが承認された答えになるはずです。:私は少し単純化したバージョン示唆するかもしれないgit show -p <sha> path/to/file.ext|git apply -R
アモリーD

<sha>^!代わりに使用できます<sha>^ <sha>
派手な

8

使用git log後、特定のバージョンおよび使用のためのハッシュキーを取得しますgit checkout <hashkey>

注:最後のハッシュの前にハッシュを入力することを忘れないでください。最後のハッシュは現在の位置(HEAD)を指し、何も変更しません。


7

明らかに誰かがgitでわかりやすい本を書く必要があるか、gitはドキュメントでよりよく説明する必要があります。これと同じ問題に直面しました

cd <working copy>
git revert master

最後のコミットを元に戻します。

イアン


7

あなたは4つのステップでそれを行うことができます:

  1. 具体的に元に戻したいファイルでコミット全体を元に戻します-ブランチに新しいコミットが作成されます
  2. コミットをソフトリセット-コミットを削除し、変更を作業領域に移動します
  3. ファイルをハンドピックして、元に戻してコミットする
  4. 他のすべてのファイルを作業領域にドロップします

端末に入力する必要があるもの

  1. git revert <commit_hash>
  2. git reset HEAD~1
  3. git add <file_i_want_to_revert> && git commit -m 'reverting file'
  4. git checkout .

幸運を


すべての変更を元に戻しませんか?
arcee123 2018年

1
@ arcee123はい。ただし、その後のリセットにより、すべての変更が元に戻されます。問題はgit-revertリポジトリ全体でしか機能しないため、それを補うために他のすべてを元に戻す必要があるということです。
ティモシー

2
私は以下を使用することをお勧めします:1. git revert --no-commit <commit_hash>2. git reset HEADこれにより、余分なコミットが回避され、すべての変更が作業ディレクトリでのみ行われます。
ティモシー

@ greg-hewgillの回答の方が優れており、的確です。これはひどいので使用しないでください。
Daniel Tranca

これはまさに、特定のファイルの真の復帰に必要なものです。すでにリモートリポジトリにプッシュされている、以前のコミットからのいくつかのファイルへの変更を元に戻す必要がありました。結果を元に戻し、リセットしてコミットしました git revert _oldcommit_ --no-commit git reset -- _unchanged1_ _unchanged2_ ... git commit -m "branch without changes to specific files"。新しいブランチのヒントには、元に戻したファイルを除くすべての変更が反映されていました。
Suncat2000

7

これは非常に簡単な手順です。ファイルを必要なコミットIDにチェックアウトします。ここでは前に1つのコミットIDを使用し、次にgit commit amendを実行するだけです。

# git checkout <previous commit_id> <file_name>
# git commit --amend

これはとても便利です。コミットの先頭にある以前のコミットIDにファイルを移動したい場合は、簡単に実行できます。


5
git revert <hash>

指定されたコミットを元に戻します。git revert最近のコミットにのみ影響を与えると思われるようです。

特定のファイルの変更を元に戻し、そのコミットがそのファイルよりも多く変更された場合、問題は解決しません。


5

最後のコミットで間違ったファイルをコミットした場合は、次の指示に従ってください:

  1. オープンソースツリー、このコミットに変更

オープンソースツリー

  1. 行を変更し、間違ったファイルがコミットとして送信したコミットを見つけます

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

  1. あなたはそのコミットでの変更のリストを見ることができます ソースツリー内のファイルのリスト
  2. それを選択してから...右側のボタンをクリックしてください...逆ファイルをクリックしてください
  3. 次に、左下のファイルステータスタブに表示され、[ステージ解除]をクリックします。

ファイルステータスタブ

  1. ビジュアルスタジオのコードを開き、削除したファイルをコミットして元に戻します
  2. それらすべての後、ソースツリーの最後のコミットの結果を見ることができます

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

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