web-dev-qa-db-ja.com

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

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

ただし、$ git reset (--hard|--soft) <file_path>は次のようなエラーを報告します。

Cannot do hard|soft reset with paths.
114
yao

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

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

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

パスの混合リセットは、git reset -- <path>が行うことです。

118
Amber

git checkout HEAD <path>を使用して、やろうとしていることを達成できます。

とはいえ、提供されたエラーメッセージは私には意味がありません(git resetはサブディレクトリでうまく動作します)、git reset --hardがあなたが求めていることを正確にしない理由はわかりません。

19
Aaron Kent

質問howはすでに 回答済み です。whyの部分について説明します。

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

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

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

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

    なぜこの操作がその性質上特定のファイルに対するものではないのか、今では明らかだと思います-そもそもブランチヘッドを移動し、作業ツリーをリセットすることを意図しており、インデックスは二次的な機能です。

8
user

Originまたはアップストリーム(ソース)と実際のブランチの間に必ずスラッシュを入れてください:

git reset --hard Origin/branch

または

git reset --hard upstream/branch`
2
Pascal Nitcheu

説明

git reset manual は、呼び出しの3つの方法をリストします。

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

    • git reset [-q] [<tree-ish>] [--] <paths>..
    • git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
  • 1はコミット単位です:参照される<commit>内のすべてのファイルおよびmay作業ツリーに影響を与えます:

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

指定されたファイルでのみ動作する呼び出しモードはなく、は作業ツリーに影響します。

Workaround

両方にしたい場合:

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

Git configファイルでこのエイリアスを使用できます:

[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>

recoの記憶法:reset && checkout)

0
Tom Hale

その背後には非常に重要な理由があります:checkoutおよびresetの原則

Gitの用語では、checkoutは「現在の作業ツリーにアクセスする」ことを意味します。 git checkoutを使用すると、作業ツリーにanyエリアのデータを入力できます。コミットからのリポジトリまたは個々のファイル、またはステージング領域(これがデフォルトです)。

同様に、gitresetにはこの役割はありません。名前が示すように、現在のrefをリセットしますが、alwaysは、「repository」をソースとして、「リーチ"(--soft、-mixed、または--hard)。

要約:

  • checkout:どこからでも(インデックス/リポジトリコミット)->作業ツリー
  • reset:リポジトリコミット-> HEAD(およびオプションでインデックスと作業ツリーを上書き)

したがって、「[HEADを上書きする」一部のファイルのみで上書きすることは意味をなさないため、少し混乱する可能性があるのはgit reset COMMIT -- filesの存在です。

公式の説明がない場合、git開発者は、resetがまだステージング領域に加えられた変更を破棄するコマンドの最良の名前であり、唯一のデータソースがリポジトリであると判断したと推測できます。次に、新しいコマンドを作成する代わりに、「機能を拡張しましょう」。

何らかの理由でgit reset -- <files>は既に少し例外的です。HEADを上書きしません。私見では、そのようなバリエーションはすべて例外です。 --hardバージョンを想像できたとしても、他のバージョン(たとえば--soft)は意味がありません。

0
F Pereira