web-dev-qa-db-ja.com

1つのファイルをgitの以前のバージョンに戻す

ファイルに対して異なるコミットを実行する方法はありますか。あるファイルを5回修正し、すでにコミットしてリポジトリーにプッシュした後に、変更2に戻りたいとします。

私の理解では、唯一の方法は多くのブランチを維持することですが、私はそのようにしましたか?私が正しいのであれば、数日のうちに何百ものブランチを持つことになるので、おそらくそれを本当に理解していないのでしょう。

誰かがそれをクリアしてもらえますか?

522
georgeliquor

私たちがやりたいことの定性的な説明から始めましょう(これの多くはBen Straubの回答で述べられています)。いくつかのコミットを行いましたが、そのうち5回で特定のファイルを変更しました。そのファイルを以前のバージョンの1つに戻します。まず第一に、gitは個々のファイルのバージョン番号を保持しません。内容を追跡するだけです - コミットは、本質的には何らかのメタデータ(コミットメッセージなど)と共に作業ツリーのスナップショットです。ですから、どのコミットに必要なバージョンのファイルがあるのか​​を知る必要があります。それがわかったら、ファイルをその状態に戻すための新しいコミットを行う必要があります。 (私たちはすでにこのコンテンツをプッシュしてきたので、歴史だけでは解決できません。また、履歴の編集は他のユーザー全員と混同します。)

それでは、正しいコミットを見つけることから始めましょう。あなたは非常に簡単に与えられたファイルに変更を加えたコミットを見ることができます:

git log path/to/file

コミットメッセージが十分ではなく、各コミットでファイルに何が行われたのかを確認する必要がある場合は、-p/--patchオプションを使用します。

git log -p path/to/file

あるいは、gitkのグラフィカルな表示が好きなら

gitk path/to/file

ビューメニューからgitkを始めたら、これを行うこともできます。ビューのオプションの1つは、含めるパスのリストです。

どちらの方法でも、必要なバージョンのファイルとコミットのSHA1(ハッシュ)を見つけることができます。さて、あなたがしなければならないのはこれだけです:

# get the version of the file from the given commit
git checkout <commit> path/to/file
# and commit this modification
git commit

(checkoutコマンドは最初にファイルをインデックスに読み込み、次にそれを作業ツリーにコピーするので、コミットに備えてgit addを使用してインデックスに追加する必要はありません。)

あなたのファイルが単純な履歴(名前の変更やコピーなど)を持っていない可能性がある場合は、VonCのすばらしいコメントを見てください。 gitは、速度を犠牲にして、そのようなことをもっと慎重に検索するように指示できます。歴史が単純だと確信しているのなら、気にする必要はありません。

758
Cascabel

Gitはとても柔軟です。あなたが求めていることをするのに何百もの枝を必要とするべきではありません。 2番目の変更までずっと状態を戻したい場合(そしてそれはすでにコミットされプッシュされた変更です)、 git revert を使用してください。何かのようなもの:

git revert a4r9593432 

ここで、a4r9593432は、取り消したいコミットのハッシュの開始文字です。

コミットに多くのファイルへの変更が含まれていて、ただ1つのファイルだけを元に戻したい場合は、 git reset (2番目または3番目の形式)を使用できます。

git reset a4r9593432 -- path/to/file.txt
# the reverted state is added to the staging area, ready for commit
git diff --cached path/to/file.txt        # view the changes
git commit
git checkout HEAD path/to/file.txt        # make the working tree match HEAD           

しかしこれはかなり複雑で、git resetは危険です。 Jefromiが示唆しているように、代わりにgit checkout <hash> <file path>を使用してください。

コミットxでファイルがどのように見えるかを見たいだけであれば、 git show を使用できます。

git show a4r9593432:path/to/file.txt

すべてのコマンドについて、コミットハッシュ以外の方法でコミットを参照する方法はたくさんあります(Gitユーザーマニュアルの 命名コミット を参照)。

70
Jim Hurne

Gitはファイルのバージョンに関しては考えていません。 gitのバージョンはツリー全体のスナップショットです。

これを考えると、あなたが本当に欲しいのはほとんどのファイルの最新の内容を持っていますが、1つのファイルの内容は5コミット前と同じであるツリーです。これは古いコミットの上に新しいコミットの形を取ります、そしてツリーの最新版はあなたが望むものを持ちます。

1つのファイルを5コミット前の内容に戻すワンライナーがあるかどうかはわかりませんが、lo-fiソリューションでうまくいくはずです。checkout master~5、ファイルを別の場所にコピーする、checkout master、ファイルをコピーバックする次にコミットします。

7
Ben Straub

必要な変更を元に戻す差分を取り、それをコミットすることができます。

例えば。 from..toの範囲の変更を元に戻したい場合は、次の手順に従ってください。

git diff to..from > foo.diff  # get a reverse diff
patch < foo.diff
git commit -a -m "Undid changes from..to".
5
Alex Budovski

ここから抜粋: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html

 git revert <commit> 
 git reset 
 git add <path> 
 git commit ... 
 git reset --hard # making sure you didn't have uncommited changes earlier 

それは私にとってとてもうまくいった。

4
Felipe