Gitでファイルのステージを解除する方法が2つあるのはなぜですか?


1169

時にはgitはgit rm --cachedファイルをステージング解除することを提案しますgit reset HEAD file。どちらを使用すればよいですか?

編集:

D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       a
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

D:\code\gt2>touch b

D:\code\gt2>git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       b
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add b

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

20
どうして?それは、gitのコマンドラインインターフェイスが有機的に進化し、一貫性を保つために大規模な再構築を行ったことがないためだと思います。(あなたが同意しない場合は、ノートどのようにgit rm両方のことができ、ステージの削除ともunstage ほか
ローマStarkov

3
@romkyns:Gitのインターフェースは有機的に進化したため、いくつかの奇妙な点があることに同意しますが、削除は確かに追加の逆関数であるためrm、元に戻すことは論理的ではありませんaddか?どのrmように振る舞うべきだと思いますか?
Zaz 2014

6
あなたの質問に対する唯一の実際の答えは、リセット直後にリセットするgit init必要がないということですHEAD
Miles Rout

このための最良のドキュメント:help.github.com/articles/changing-a-remote-s-url
ScottyBlades

4
@Zaz、私の意見を述べます。 rmUNIXコンテキストでの削除を意味します。インデックスへの追加と逆ではありません。ファイルを削除する関数は、ステージング状態を変更する関数でオーバーロードしないでください。それらを組み合わせるのに便利な実装の詳細がある場合、それは単にgitでの抽象化の思慮深い層の欠如を示しており、使いやすさが明確になります。
ジョシュアゴールドバーグ

回答:


1893

git rm --cached <filePath> ファイルのステージングを解除しませんが、実際にはリポジトリからのファイルの削除をステージングします(ファイルがすでにコミットされている場合)。ただし、ファイルは作業ツリーに残ります(追跡されていないファイルが残ります)。

git reset -- <filePath>unstageいずれかが指定されたファイル(複数可)の変更を上演しました。

つまり、git rm --cachedステージングされた新しいファイルを使用した場合、以前にコミットされたことがないため、ステージングを解除したように見えます。

git 2.24を更新します
。この新しいバージョンのgit git restore --stagedでは、の代わりに使用できますgit resetgit docsを参照してください。


71
私が言うgit rm --cachedファイルunstagesが、作業ディレクトリからは削除されません。
Pierre de LESPINAY

4
追加用にステージングされたファイルを削除して、もはやステージングされないようにすることは、確かに「追加用にステージングされたファイルのステージングを解除する」と言えるでしょう。最終結果は段階的な削除ではありません。それは確かです。したがって、誤解は完全に理解できると思います。
ローマン・スターコフ2014年

4
したがって、通常は、git rm --cached <filePath>リポジトリに存在してはならないこと気付いた、リポジトリからいくつかのファイルを削除するために使用します。そのため、このコマンドを実行し、関連するファイルをに追加しますgitignore。私は正しいですか?
Adrien Be

13
質問と回答の両方にこれほど多くの票が投じられたので、明らかに私たちはでunstageコマンドを持ちたいと思いgitます。
milosmns

4
"git status"がアドバイスする: "git restore --staged <file> ..."を使用してステージングを解除します
yucer

334

git rm --cachedインデックスからファイルを削除するために使用されます。ファイルがすでにリポジトリにある場合、はファイルをgit rm --cachedインデックスから削除し、作業ディレクトリに残します。コミットすると、ファイルもリポジトリから削除されます。基本的に、コミット後は、ファイルのバージョン管理を解除し、ローカルコピーを保持します。

git reset HEAD file(デフォルトでは--mixedフラグを使用しています)は、ファイルがすでにリポジトリ内にある場合とは異なり、ファイルのインデックスバージョンをリポジトリからのインデックスバージョン(HEAD)で置き換え、変更を効果的にステージング解除します。

バージョン管理されていないファイルの場合、ファイルがHEADに存在しなかったため、ファイル全体がステージング解除されます。この側面git reset HEAD filegit rm --cachedは同じですが、同じではありません(すでにリポジトリにあるファイルの場合で説明したように)

質問ですWhy are there 2 ways to unstage a file in git?が、gitで何かを実行する方法は1つだけではありません。それがその美しさです:)


7
受け入れられた答えとこれの答えはどちらも素晴らしいものであり、どちらを使用するのかを説明します。しかし、なぜ gitが2つの異なる方法を提案するのという暗黙の質問には直接答えていません。OPの例の最初のケースでは、git initが実行されました。その場合、gitは "git rm --cached"を提案します。その時点ではリポジトリにコミットがないため、HEADは無効だからです。"git reset HEAD-a"は次を生成します: "fatal:Failed to resolve 'HEAD' as a valid ref。"
sootsnoot 14

5
「git checkout」を使用すると、ファイルに加えたすべての変更が失われませんか?それは、私が誤解している場合を除き、ファイルのステージングを解除することと同じではありません。
John Deighan 2017

there is never really only one way to do anything in git. that is the beauty of it-うーん...なぜ?明らかな方法が1つしかない場合、それは常に素晴らしいことです。これは私たちの時間と脳の記憶を大幅に節約します))
Oto Shavadze

128

非常に単純に:

  • git rm --cached <file> gitがファイルの追跡を完全に停止するようにします(プレーンとは異なり、ファイルシステムに残しますgit rm*)
  • git reset HEAD <file> 最後のコミット以降にファイルに加えられた変更をステージング解除します(ただし、コマンド名が示唆する可能性があるのとは逆に、ファイルシステムでそれらを元に戻しません**)。ファイルはリビジョン管理されたままです。

ファイルが以前にリビジョン管理されていなかった場合(つまりgit add、最初に編集したファイルのステージングを解除している場合)、2つのコマンドは同じ効果をもたらすため、これらは「何かを行う2つの方法」のように見えます」

* 以前にリポジトリにコミットさgit rm --cachedたファイルに関して、@ DrewTが回答で言及している警告に留意してください。この質問のコンテキストでは、追加されたばかりでまだコミットされていないファイルについては、何も心配する必要はありません。

**その名前が原因でgit resetコマンドを使用するのは恥ずかしいほど長い間怖がっていました。それでも、今日でも、混乱しないように構文を調べることがよくあります。(更新:ようやく時間をかけてtldrページでの使用法git reset要約したので、それがどのように機能するかについてのより良いメンタルモデルと、詳細を忘れたときのクイックリファレンスが手に入りました。)


それはgit rm <file> --cached
ネオンメイト2015

8
2015年8月4日のこの回答の編集が全体的な改善であったとは私は思いません。技術的な正確性は修正されている可能性がありますが(評価する資格がないと思います)、「現在追跡されていないファイルの追跡を開始するために必要な設定を解除します。 "、そして" index "や" HEAD "のような専門用語を使用して、正確に初心者を怖がらせるようなものです。可能であれば、編集して、より新しい友好的な言語に戻してください。
厄介な

5
@waldyriousに同意します。元の答えはgitの教科書からそのままではなかったかもしれませんが、十分な技術レベルで質問に答えました。技術的な詳細は、元の意図を曖昧にする編集としてではなく、コメントで明確にされるべきでした。
Simon Robb、2015年

編集を元に戻しました。コミュニティが(以前のコメントと投票で)十分な検証が行われたため、編集が回答の明確性に悪影響を及ぼしたと思います。
騒々しい16/07/26

@DrewTは、 rm --cachedしてプッシュ、同じブランチをプルするすべてのユーザーが実際に作業ツリーからファイルを削除することています。
トム・ヘイル

53

このスレッドは少し古いですが、直感的な問題ではないため、少しデモンストレーションを追加したいと思います。

me$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   to-be-added
#   modified:   to-be-modified
#   deleted:    to-be-removed
#

me$ git reset -q HEAD to-be-added

    # ok

me$ git reset -q HEAD to-be-modified

    # ok

me$ git reset -q HEAD to-be-removed

    # ok

# or alternatively:

me$ git reset -q HEAD to-be-added to-be-removed to-be-modified

    # ok

me$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   to-be-modified
#   deleted:    to-be-removed
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   to-be-added
no changes added to commit (use "git add" and/or "git commit -a")

git reset HEAD (なし -q)は、変更されたファイルに関する警告を出し、その終了コードは1で、スクリプトのエラーと見なされます。

編集:git checkout HEAD to-be-modified to-be-removedアンステージングでも機能しますが、ワークスペースから変更を完全に削除します

git 2.23.0のアップデート:コマンドは随時変更されます。今、git status言う:

  (use "git restore --staged <file>..." to unstage)

... 3つのタイプの変更すべてで機能します


おかげで、最初の2つの回答(おそらく、私の専門用語がわからない)から完全に明確ではなかったため、git resetはファイルに変更をローカルに残しました(git checkoutとは対照的に)。
スープドッグ

古いバージョンは新しいバージョンのファイルを削除するため、最初にバージョンに関する警告を入れておく必要があります
Luis Mauricio

@LuisMauricioどのコマンドがファイルを削除しますか?
ダニエルアルダー

@DanielAlder申し訳ありませんが、私は再テストしました、それは削除しません、私の間違い。
ルイス・マウリシオ

36

コミットしたくないファイルを誤ってステージングしていて、変更を確実に保持したい場合は、次のものも使用できます。

git stash
git stash pop

これにより、HEADへのリセットが実行され、変更が再適用され、コミットのために個々のファイルを再ステージングできるようになります。これは、プルリクエストの機能ブランチを作成するのを忘れた場合にも役立ちます(git stash ; git checkout -b <feature> ; git stash pop)。


3
これは、きれいなソリューションと「gitのRM」を入力するよりもはるかに少ない気になる
サブイメージ

1
git stashreflogにエントリを作成し、後で利用できるようにするため、他の関連する利点があります。疑わしい場合は、先に進んでgit stash(たとえばgit stash save -u "WIP notes to self"、「-u」はstashコミットに新規/追跡されていないファイルを含めることです)...次にgit reflog show stashstashコミットとそのshaのリストを確認してください。シェルをお勧めしますエイリアスのようなalias grs="git reflog show stash"
cweekly

15

問題のファイルがすでにリポジトリ内にあり、バージョン管理下にある場合(以前にコミットされた場合など)、これら2つのコマンドにはいくつかの微妙な違いがあります。

  • git reset HEAD <file> 現在のコミットでファイルのステージを解除します。
  • git rm --cached <file>今後のコミットのためにファイルのステージングを解除します。で再度追加されるまで、ステージは解除されgit add <file>ます。

そしてもう一つ重要な違いがあります:

  • 実行git rm --cached <file>してブランチをリモートにプッシュした後、ローカルのワーキングセットではファイルが追跡されなくなる(つまり、フォルダーから物理的に削除されない)場合でも、リモートからブランチをプルすると、フォルダーからファイルが実際に削除されます。

この最後の違いは、チームの各開発者が異なる構成(つまり、異なるベースURL、IP、またはポート設定)を持つ構成ファイルを含むプロジェクトにとって重要であるためgit rm --cached <file>、ブランチをプルするユーザーを使用している場合、手動で再設定する必要があります。削除すると、リモートからブランチをプルしたユーザーにのみ影響が及ぶため、構成を作成するか、自分に送信して、IP設定などに再編集することができます。


10

stage介してディレクトリ全体git add <folder>があり、ステージングされたリスト(つまり、実行時に生成されるリストgit status)からファイルを除外して、除外されたファイル内に変更を保持したいとします(何かに取り組んでいて、コミットの準備ができていませんが、あなたの仕事を失いたくない...)。あなたは単に使うことができます:

git reset <file>

あなたが実行するとgit status、あなたはどんなファイル(複数可)が表示されますresetされているunstagedと、ファイルの残りの部分addedに残っているstagedリスト。


10

1。

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a

(ステージングを解除するには、「git rm --cached ...」を使用します)

  • gitはポインターのシステムです

  • ポインタを変更するコミットがまだありません

  • 「ポイントされているバケットからファイルを取り出す」唯一の方法は、変更を監視するようにgitに指示したファイル削除することです

2。

D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a

git commit -ma

  • あなたがコミットした、「保存された

3。

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

(ステージを解除するには「git reset HEAD ...」を使用)

  • この時点でコードをコミットしました
  • 今、あなたはあなたのコミットへのポインタをリセットすることができます ' 最後の保存に戻る '

1
これは実際、IMOの質問に適切に回答する唯一の回答です。それは実際に質問に答えます、それは「 'git rm --cached'と 'git reset HEAD'の違いは何ですか?ではなく、なぜgitは両方にオプションとして一貫性を与えないのですか?git init初めてあなたに。
Miles Rout

5

誰もgit reflog(http://git-scm.com/docs/git-reflog)に言及していないことに驚いています

# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}

reflogは、リポジトリへの変更を追跡するだけでなく、ユーザーアクション(プル、別のブランチへのチェックアウトなど)も追跡し、それらのアクションを元に戻すことができるgit履歴です。したがって、誤ってステージングされたファイルのステージングを解除する代わりに、ファイルをステージングしなかったポイントに戻すことができます。

これは git reset HEAD <file>いますが、特定のケースではより詳細な場合があります。

申し訳ありませんが、実際にはあなたの質問に答えるのではなく、私が頻繁に使用するファイルをアンステージングする別の方法を示しているだけです(私はRyan Stewartによる回答と非常に不機嫌です);)お役に立てば幸いです。


5

ただ使用する:

git reset HEAD <filename>

これにより、ファイルのステージが解除され、変更内容が保持されるため、必要に応じてブランチを変更し、git addそれらのファイルを別のブランチに変更できます。すべての変更が保持されます。


3

OS がバージョン管理を削除せずにディレクトリからファイルを削除するのと同じように、git rm --cached <file>プレーンからgit rm <file>両方を実行するディレクトリからファイルを削除せずに、インデックスからファイルを削除するように思えますrm <file>


1

バージョン2.23以上の場合のみ、

これらの提案の代わりgit restore --staged <file>unstage、ファイルを順番に使用できます 。


これはオプションの両方で動作する--stageだけでなく、--staged
dhana1310
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.