gitがパスでハード/ソフトリセットを実行できないのはなぜですか?


137

$ git reset -- <file_path> パスでリセットできます。

ただし、$ git reset (--hard|--soft) <file_path>以下のようなエラーが報告されます。

Cannot do hard|soft reset with paths.

回答:


142

意味がないので(他のコマンドがすでにその機能を提供しています)、誤って間違ったことをする可能性を減らします。

パスの「ハードリセット」は、git checkout HEAD -- <path>(ファイルの既存のバージョンをチェックアウトする)で行われます。

パスのソフトリセットは意味がありません。

パスの混合リセットがgit reset -- <path>機能します。


72
個人的に、私は考えるgit checkout -- <path>べきである取り替えgit reset --hard <path>。それは非常に理にかなっています...
vergenzt

24
git checkout -- <path>ハードリセットは行いません。作業ツリーのコンテンツをステージングされたコンテンツに置き換えます。git checkout HEAD -- <path>パスのハードリセットを行い、インデックスと作業ツリーの両方をHEADコミットのバージョンで置き換えます。
Dan Fabulich、2012年

1
@EdPlunkett Er、回答の2番目の文は、他のコマンドが機能を提供していることを示しています。
アンバー

16
-1:上記のリビジョンにチェックアウトしても、そのリビジョンに削除されたファイルが含まれている場合、作業コピーからファイルは削除されません。reset --hardパスを指定すると、この欠落した部分が提供されます。Gitはすでに非常に強力なので、「あなた自身の保護のためにこれを行うことはできません」という言い訳には水がありません。間違って「偶然」に行う方法はたくさんあります。あなたが持っている場合、それはいずれにしても重要ではありませんgit reflog
void.pointer 2015年

1
@ void.pointerチェックアウトで述べたように、チェックアウトはファイルを削除しません。その動作が必要な場合は、この答えを見てください。それでも、いつか私たちが得られることを願っていますgit reset --hard -- <path>。それには正当なユースケースがあります。
Mariusz Pawelski、

18

を使用して実行しようとしていることを達成できますgit checkout HEAD <path>

とは言っても、提供されたエラーメッセージは私には意味がなく(git resetサブディレクトリで正常に機能します)、git reset --hardユーザーが求めていることを正確に実行してはならない理由はわかりません。


チェックアウトを使用して変更をステージングします。これは、リセットとは異なります--soft
worc

11

質問はどのように既に回答されています理由を説明します一部を。

では、git resetは何をするのでしょうか?指定されたパラメーターに応じて、次の2つのことを実行できます。

  • パスを指定すると、インデックス内の一致したファイルがコミット(デフォルトではHEAD)からのファイルで置き換えられます。このアクションは作業ツリーにまったく影響を与えず、通常はgit addの反対として使用されます。

  • パスを指定しない場合は、現在のブランチヘッドを指定したコミットに移動し、それとともに、オプションでインデックスと作業ツリーをそのコミットの状態にリセットします。この追加の動作は、モードパラメータによって制御されます
    。--soft:インデックスと作業ツリーに触れないでください。
    --mixed(デフォルト):インデックスをリセットしますが、作業ツリーはリセットしません。
    - ハード:インデックスと作業ツリーをリセットします。
    他のオプションもあります。完全なリストといくつかの使用例については、ドキュメントを参照してください。

    コミットを指定しない場合、デフォルトはHEADでありgit reset --soft、ヘッドを(現在の状態に)HEADに移動するコマンドであるため、何もしません。git reset --hard一方、その原因に理にかなっている副作用、それはHEADにヘッドを移動言う HEADにインデックスと作業ツリーをリセットします。

    この操作が本質的に特定のファイルに対するものではない理由は、今では明らかだと思います。これは、ブランチヘッドを最初に移動して、作業ツリーをリセットし、インデックスが二次機能であることを目的としています。


リセットはそもそもブランチヘッドを移動することを目的としていることは明らかですが、作業ツリーとコミット全体のインデックスをリセットする追加機能と、特定のファイルのインデックスをリセットする機能があるため、なぜそうではないのですか?特定のファイルの作業ツリーをリセットする機能はありますか?それがOPが求めていることだと思います。
Danilo SouzaMorães18年

おそらく、その機能(特定のファイルの作業ツリーをリセットする)がすでにgit checkoutコマンドとして利用できるためでしょうか?そして、同じことをするためにリセットを行うと、ユーザーをさらに混乱させるでしょう。私の答えは、この--hardオプションはインデックスのリセットではなくブランチのリセットのためのモードであるため、特定のファイルには適用できないということでした。そして、他の回答で読むことができるように、作業ツリーのリセットはチェックアウトと呼ばれます。これらはすべて、GitのユーザーインターフェースであるIMHOの設計が悪いだけです。
ユーザー

最初のオプションとの比較git checkoutgit reset --インデックスのみをgit checkout --設定し、作業ツリーのみを設定しますか?
seeker_of_bacon

4

必ず起点または上流(ソース)と実際のブランチの間にスラッシュを入れてください。

git reset --hard origin/branch

または

git reset --hard upstream/branch`

もう一度質問を読んでください。
Xerus

3

その背後には非常に重要な理由があります。 checkoutあります。resetます。それ。

Gitの用語では、チェックアウトは「現在の作業ツリーに取り込む」ことを意味します。そしてgit checkout、作業ツリーを任意のデータで埋めることができます、リポジトリ内のコミットからのや、コミットまたはステージング領域からの個々のファイルなど、領域ます(これもデフォルトです)ます。

一方、git resetにはこの役割はありません。名前が示すように、現在の参照をリセットしますが、常にますが、「到達範囲」(--soft、-mixedまたは--hard)とは関係リポジトリをソースとして保持します

要約:

  • チェックアウト:どこからでも(インデックス/リポジトリコミット)->作業ツリー
  • リセット:Repo commit-> HEAD(およびオプションでインデックスと作業ツリー)を上書きします

したがって、少し混乱する可能性があるのは、 git reset COMMIT -- filesいくつかのファイルだけで「HEADを上書きする」のは意味がないのでです。

公式な説明がない場合、Git開発者がresetステージング領域に加えられた変更を破棄するコマンドの最良の名前であることがわかり、データソースがリポジトリのみである場合、 "を拡張してみましょう機能性新しいコマンドを作成する代わりに「」

だから、どういうわけかgit reset -- <files>、もう少し例外的です:それはヘッドを上書きしません。私見このようなバリエーションはすべて例外です。--hardバージョンを想像できても、他のもの(たとえば--soft)は意味をなさないでしょう。


私はこの答えが好きです。本当に、git reset -- <files>これは便利な機能なので追加されたように見えますが、どのコマンドを使用すればよいのか誰にもわかりませんでした。幸いにも今ははるかにまとも持つgit restoreの機能持つgit checkout -- <path> git checkout <commit> -- <path>git reset [<commit>] -- <path>かなり正気のデフォルトとし、さらに(答えを受け入れたことに反しては述べています。今、あなたは最終的には簡単に触れインデックスなし、単に作業ツリーを復元することができます)前に、あなたが行うことができなかった特徴を。
Mariusz Pawelski

0

説明

git resetマニュアルのリスト呼び出しの3つの方法:

  • 2はファイル単位です。これらは作業ツリー影響を与えませんが、で指定されたインデックス内のファイルのみを操作します<paths>

    • git reset [-q] [<tree-ish>] [--] <paths>..
    • git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
  • 図1は、コミット単位である:上で動作するすべてのファイルの参照では<commit>、と作業ツリーに影響を与えます。

    • git reset [<mode>] [<commit>]

のみ指定されたファイルを操作する呼び出しのないモードがありませんし、作業ツリーに影響を与えますが。

回避策

両方したい場合:

  • ファイルのインデックス/キャッシュバージョンをリセットする
  • ファイルをチェックアウトします(つまり、作業ツリーをインデックスに一致させ、バージョンをコミットします)。

このエイリアスはgit構成ファイルで使用できます。

[alias]
  reco   = !"cd \"${GIT_PREFIX:-.}\" && git reset \"$@\" && git checkout \"$@\" && git status --short #"  # Avoid: "fatal: Cannot do hard reset with paths."

その後、次のいずれかを実行できます。

$ git reco <paths>

$ git reco <branch/commit> <paths>

$ git reco -- <paths>

(Menenonic for recoreset && check out)


-2

git reset --soft HEAD〜1 filenameはコミットを取り消しますが、変更はローカルに残ります。ファイル名は次のようになります-コミットされたすべてのファイル


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