コンテンツを削除せずに多数のファイルをアンステージする方法


454

私が誤ってたくさんの一時ファイルを追加しました git add -A

次のコマンドを使用してファイルをアンステージングし、ダーティインデックスを削除することに成功しました。

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

上記のコマンドは、にリストされていgit help rmます。しかし残念なことに、キャッシュオプションを指定していても、実行時にファイルも削除されました。コンテンツを失わずにインデックスをクリアするにはどうすればよいですか?

また、このパイプ操作の仕組みを誰かが説明できると助かります。


8
rm -fはgitコマンドではなく、--cachedオプションはありません。実行git rmする前にローカルファイルが削除されたため、正当な理由があるとは思えませんgit rm
CBベイリー

8
@saratは、より高度upvoted答えに正解変更することを検討してくださいイアン・マドックスを通り、git reset --hardある正しい答えではない、実際にコンテンツを削除します。これはユーザーを混乱させます-私と同じように。
マルコパシュコフ2015年

2
マルコが言うように、@ sarat。このページは多くのトラフィックを得ます。
ロス

@MarcoPashkov&Ross、みんなありがとう。できました。
sarat 2015年

回答:


986

git reset

やりすぎの「git add」の実行を元に戻すことだけが必要な場合:

git reset

変更はステージング解除され、必要に応じて再度追加できるようになります。


実行しないでくださいgit reset --hard

追加したファイルのステージを解除するだけでなく、作業ディレクトリで行った変更を元に戻します。作業ディレクトリに新しいファイルを作成した場合、それら削除されません


15
私はあなたにパイントイアンを借りています
DasBooten

1
私もよく演奏git checkout -- *しなければならないことがよくあります
Den-Jason

1
あなたは多くの労力を節約しました。おかげで男
RajnikantDixit

35

手付かずのレポがある場合(またはHEADが設定されていない場合)[1]

rm .git/index

もちろん、追加たいファイルを再度追加する必要があります。


[1]注意(コメントで説明されているように)これは通常、リポジトリが新品(「元の状態」)である場合、またはコミットが行われていない場合にのみ発生します。より技術的には、チェックアウトまたは作業ツリーがないときはいつでも。

より明確にするだけです:)


そうですね、作成されたインデックス自体を削除するようなものです。良いことは、gitを再初期化する必要がないことです。ありがとう!
サラト

安全な操作ですか?私はこれを実行し(実際にインデックスを移動しました)、他のすべてのファイルを削除するためにステージングしました。
2013年

@inger「元のレポがある場合」。あなたは明らかにそれを持っていませんでした。
2013年

実際、私は「手付かずのレポ」が何を意味しているのだろうと思っていました(Googleにも幸運を感じません)。
歌手2013年

1
@inger同意する。私はOPがたまたまこの正確な状況にあったと仮定しなければなりませんでした-彼はそれを指定していませんが、彼の説明は可能性を残しています。とにかく、私は情報を共有していて、投票に影響を与えることはできません:(それは将来的に他の人を助けてきた場合には、回答テキストに警告の言葉を追加しました。。
sehe

15

git reset HEADファイルを削除せずにインデックスをリセットするために使用します。(インデックス内の特定のファイルのみをリセットしたい場合は、を使用git reset HEAD -- /path/to/fileしてリセットできます。)

シェル内のパイプオペレーターはstdout、左側のプロセスのを受け取りstdin、右側のプロセスに渡します。これは基本的に次のものと同等です。

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

代わり$ proc1 | proc2に、最初のプロセスがデータを出力する前に、2番目のプロセスがデータの取得を開始できます。実際のファイルは関与していません。


しかし、それを複数のファイルで使用する方法については。これらのファイルをコミットしたことはありません。
サラト

3
git reset HEAD他に何も指定せずに入力するだけで、インデックス全体がリセットされます。その後、必要なファイルのみを再度追加できます。
アンバー

次のエラーが発生しました。これまでにこれらのアイテムをコミットしたことはありません。 $ git reset HEAD fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
サラト

1
ちょうど試してみてくださいgit resetなし、その後HEAD
アンバー

私はすでに次のエラーに終わったことを試しました。$ git reset fatal: Failed to resolve 'HEAD' as a valid ref.
sarat

9
git stash && git stash pop

2
「git stash && git stash pop」を実行して、スタッシュも削除されるようにします。'apply'は、スタッシュをスタッシュリストに残します。
チッティ2013年

8

HEADが設定されていない場合(つまり、まだコミットはありませんが、.git保持したい他のリポジトリ設定がすでに設定されているため、ただ吹き飛ばしたくない場合)、次のようにすることもできます

git rm -rf --cached .

すべてをステージング解除します。これは実質的にseheのソリューションと同じですが、Gitの内部をいじくるのを避けます。


これは実際にGitにキャッシュされた領域のすべてを削除するように指示します。
ビジョナリーソフトウェアソリューション

1
キャッシュはステージング領域とも呼ばれるため、何を取得しているのかわかりません。
jjlin 2013

seheから、rm .git / indexは非常に危険です-新しいリポジトリに関する彼のメモを必ず読んでください!これは、他の99.999%の時間に対してはるかに安全です。私は注意深く読んでおらず、私の作業コピーでrm .git / indexを実行した後、私の作業コピーを吹き飛ばして再クローンしなければなりませんでした。
phpguru 2017

このコマンドは使用しないでください!すべてのプロジェクトを追跡されていない状態に変更します(ステージングされていないものも含む)。これは元の質問に対する解決策ではありません。'git rm'コマンドを使用する正しい解決策は、ステージ解除するファイルのみを指定することです:git rm -rf --cached <ステージ解除するファイル>。
Monte Creasor

このコマンドは、まだコミットされていない新しいリポジトリがある場合にのみ使用する必要があります(これは「ヘッドが設定されていない」という意味です).git。保ちたい。これを明確にするために編集しました。
jjlin

5

警告:コミットされていない作業を失いたくない場合を除いて、次のコマンドを使用しないでください。

の使用方法git resetについて説明しましたが、パイプコマンドの説明も求めたので、次のように記述します。

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

このコマンドgit ls-filesは、gitが認識しているすべてのファイルを一覧表示します。オプション-zはそれらに特定の形式を課しますxargs -0。これは、が期待する形式であり、それらを呼び出しますrm -f。つまり、承認を確認せずにそれらを削除します。

言い換えれば、「gitが認識しているすべてのファイルをリストし、ローカルコピーを削除する」ということです。

次に、にアクセスしますgit diff。これは、gitが認識しているアイテムの異なるバージョン間の変更を示しています。それらは、異なるツリー間の変更、ローカルコピーとリモートコピーの違いなどです。
ここでは、ステージングされていない変更を示しています。変更したがまだコミットしていないファイル このオプション--name-onlyは、(完全な)ファイル名のみが--diff-filter=D必要であることを意味し、削除されたファイルのみに関心があることを意味します。(ねえ、私たちはたくさんのものを削除しませんでしたか?) 次にxargs -0、これは前に見たにパイプで送られ、git rm --cachedそれらを呼び出します。つまり、キャッシュから削除されますが、作業ツリーはそのままにしておく必要があります—作業ツリーからすべてのファイルを削除しました。これで、それらもインデックスから削除されました。

つまり、ステージングされているかどうかに関係なく、すべての変更がなくなり、作業ツリーは空になります。叫び声を上げ、元のファイルまたはリモートからファイルをチェックアウトし、作業をやり直してください。これらの地獄の線を書いたサディストを呪いなさい。誰もがこれをしたいと思う理由は、私にはまったくわかりません。


TL; DR:すべてをホースしただけです。最初からやり直して、git resetこれから使用します。


2

これらのコマンドラインの最初のものが、gitのステージング領域にあるすべてのファイルを作業コピーから無条件に削除したと思います。2つ目は、追跡されたが現在は削除されているすべてのファイルのステージングを解除しました。残念ながら、これはそれらのファイルへのコミットされていない変更が失われることを意味します。

作業コピーとインデックスを最後のコミット時の状態に戻したい場合は、次のコマンドを(慎重に)使用できます。

git reset --hard

git reset --hard 作業コピーとインデックスのコミットされていない変更を消去するので、「慎重に」と言います。ただし、この状況では、最後のコミット時の状態に戻したいだけのように聞こえ、コミットされていない変更はとにかく失われています。

更新:まだコミットを作成していない(HEADを解決できないため)とのAmberの回答に対するコメントから聞こえるので、これは役に立たないと思います。

これらのパイプがどのように機能するかについてはgit ls-files -zgit diff --name-only --diff-filter=D -z両方とも、バイトで区切られたファイル名のリストを出力します0。(改行とは異なり、0Unixライクなシステムではファイル名にバイトが含まれないことが保証されているため、これは便利です。)プログラムはxargs基本的に、標準入力からコマンド行を構築します。デフォルトでは、標準入力から行を取得して最後に追加します。コマンドラインの。-0オプションは区切らによって標準入力を期待すると言う0バイト。 xargsコマンドを数回呼び出して、標準入力からすべてのパラメーターを使い果たし、コマンドラインが長くなりすぎないようにします。

簡単な例としてtest.txt、次の内容のと呼ばれるファイルがあるとします。

hello
goodbye
hello again

...次に、コマンドxargs echo whatever < test.txtはコマンドを呼び出します。

echo whatever hello goodbye hello again

私はコミットをしたことがないので、HEADを解決できないと表示されます。そのような状況で私たちがすること。パイプを詳しく説明してくれてありがとう。
sarat

8
git ignoreを変更し、多くのファイルを含めるためにgit add --allを実行した場合は、git reset --hardを実行してステージングを解除しないでください。それらは削除されます!!
2014年

5
うわぁぁぁ!「注意深く」という言葉を強調する必要があるかもしれません。私はこれら3つの単語「git reset --hard」を見ただけで、ステージングされていないすべてのファイルは... fufff !! なくなった!!!!!
Vineeth Chitteti 2014

1

すべての変更をステージング解除するには、以下のコマンドを使用します。

git reset --soft HEAD

変更をステージング解除して作業ディレクトリから元に戻す場合は、

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