1. ホーム
  2. git

[解決済み] git restore` コマンドとは何ですか?また、`git restore` と `git reset` の違いは何ですか?

2022-03-03 02:21:51

質問

ステージングされたファイルをアンステージしたいのですが、どのGitチュートリアルでも次のようなことが書かれています。

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    README.md -> README
    modified:   CONTRIBUTING.md

このヒントでは git reset はステージングされたファイルのアンステージに使用します。

しかし、その代わりに、ターミナルで見ると

git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    renamed:    cat.js -> catcat.js
    renamed:    tolendo.gogo -> tolendo.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    readme (copy).md
    tolendo (copy).txt
    zing (copy).html

私の端末では git restore --staged が、チュートリアルでは Gitのウェブサイト を使用するように言われています。 git reset HEAD .

については全く分かりませんが、新しい restore コマンドを使用します。との違いをGoogleで検索してみたところ git resetgit restore が、私の質問に合うものはなかったようです。

どのように解決するのですか?

を提示しました。 git restore (これはまだ "experimental" としてマークされています) を " に追加しました。 作業ディレクトリからすべてのファイルをリセットし、ステージングエリアからはリセットしない方法は? "、最近のGit 2.23(2019年8月)で。

を分離するのに役立ちます。 git checkout を2つのコマンドに分割しています。

として リセット、リストア、リバート のドキュメントに記載されています。

似たような名前のコマンドが3つあります。 git reset , git restoregit revert .

  • git-revert は、他のコミットで行われた変更を取り消す新しいコミットを行うことです。
  • git-restore は、作業ツリー内のファイルをインデックスまたは別のコミットからリストアすることです。
    このコマンドでは、ブランチは更新されません。
    このコマンドは、別のコミットからインデックス内のファイルを復元するためにも使用できます。
  • git-reset はブランチを更新することで、ブランチからコミットを追加したり削除したりするためにチップを移動させることです。この操作により、コミット履歴が変更されます。
    git reset と重複して、インデックスの復元に使用することもできます。 git restore .

だから

インデックスにあるファイルを HEAD にあるバージョンと一致するようにリストアするには (これは git-reset )

git restore --staged hello.c

あるいは、インデックスと作業ツリーの両方をリストアすることもできます (これは git-checkout )

git restore --source=HEAD --staged --worktree hello.c

または、より実用的だが可読性に欠ける短縮形。

git restore -s@ -SW hello.c


Git 2.25.1 (2020年2月) で、" git restore --staged "がキャッシュツリー構造を正しく更新せず、その後に偽のツリーが書き込まれることがあったため、これを修正しました。

参照 ディスカッション .

参照 コミットe701bab (2020年01月08日)によるものです。 ジェフ・キング ( peff ) .
(によって統合されました。 ジュニオ・C・ハマノ--。 gitster -- コミット 09e393d , 2020年1月22日)

<ブロッククオート

restore : --staged でエントリを削除すると、キャッシュツリーを無効にする。

報告者: Torsten Krah
サインオフ:ジェフ・キング

いつ" git restore --staged "は、インデックスにあるパスを削除すると、そのエントリに CE_REMOVE, が、キャッシュ・ツリーを無効にするようなことはしていない。
非ステージ化の場合、最終的に checkout_worktree() を呼び出し、その結果 remove_marked_cache_entries() . これは実際にインデックスからエントリを削除し、キャッシュツリーと untracked-cache を無効化します。

しかし --staged を呼び出すことはありません。 checkout_worktree() を、そして CE_REMOVE のエントリが残ります。興味深いことに、これらはインデックスを書き出す際に削除されます。 しかし、これは出来上がったインデックスに一貫性がないことを意味します:キャッシュツリーが実際のエントリと一致せず、 " git commit "の直後には、間違ったツリーが作成されます。

これを解決するには remove_marked_cache_entries() は、インデックスを書き出す前に インデックスを書き出す前に、それを checkout_worktree() この関数は CE_REMOVE のエントリーを削除する前に(一致するワークツリーファイルを削除するために)、そのエントリーを削除します。

このパッチがないと、git-restoreを実行したときにBUG()が発生します。

BUG: cache-tree.c:810: new1 with flags 0x4420000 should not be in cache-tree

しかし、同じようなレシピを使った元の問題報告書では git restore は実際に偽のインデックスを作成します (そしてコミットは間違ったツリーで作成されます)。なぜこのテストが私のサイト外での再現と異なる動作をするのかはわかりませんが、ここにあるものはどちらの症状も捕らえることができます(そしてこの修正は両方のケースを修正します)。


Git 2.27(2020年第2四半期)で、" git restore --staged --worktree " は、デフォルトで "HEAD" からコンテンツを取り出すようになりました。 をエラーにするのではなく、エラーにするようにしました。

参照 コミット 088018e (2020年05月05日)による エリック・サンシャイン ( sunshineco ) .
(によって統合されました。 ジュニオ・C・ハマノ--。 gitster -- コミット 4c2941a , 2020年05月08日)

<ブロッククオート

restore : --staged と --worktree を組み合わせた場合、デフォルトは HEAD になります。

<上 サインオフバイ: エリック・サンシャイン
レビュー執筆者:Taylor Blau

デフォルトでは、ファイルの復元は --worktree の場合はHEADから。 --staged .

いつ --worktree--staged が組み合わされます。 --source を指定する必要があるため、ワークツリーとインデックスの両方でファイルをリストアすることが面倒になります。

(見落としにより --source の要件は、文書化されてはいるものの、実際には実施されていません)。

しかし、HEADもまた、合理的なデフォルトの --worktree と組み合わせた場合 --staged であるため、いつでもデフォルトにすることができます。 --staged が使用されます( --worktree を使用するかどうか。)

これで、うまくいきましたね。

git restore --staged --worktree
git restore -SW