1. ホーム
  2. git

[解決済み] .DS_Storeファイルが.gitignoreにあるにもかかわらず、ステータスに表示され続ける

2022-03-14 07:21:38

質問

私は検索しました...私はここで見つけることができた類似または同じ質問に関するすべての答えを読みました。チュートリアルも見ました。誰かの端末で起きていることなら、超簡単で論理的だと思えるのですが。私の端末では、それはうまくいきません。どうやら、私は何か超明確なことを見逃しているようです。 .gitignoreをコミットしましたが、.DS_Storeはまだステータスに表示されています。それから、git rm --cached .DS_Storeを使って.DS_Storeを削除しました(念のため、私のレポにはなかったのですが......)。 いいえ。現在、ステージングエリアに "コミットされる変更 => 削除済み: .DS_Store" として表示されているのがわかります。 これを完全に取り除く方法はあるのでしょうか?それで、私のステータスに表示されなくなるのですか?

ここにあります。

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    .DS_Store

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md
        modified:   assets/.DS_Store
        modified:   assets/stylesheets/main.css
        modified:   index.html

解決方法は?

ここでの(かなり軽い)問題は、あなたがいくつかの数の 既存 コミットで .DS_Store が存在します。 現在のステータスでは、少なくとも2つのそのようなファイル、1つはツリーのトップレベル、もう1つは assets :

deleted:    .DS_Store
modified:   assets/.DS_Store

これらの既存のコミットは変更することができません . のコピーを保持し続けることになります。 .DS_Store ファイルを永久に (あるいはこれらのコミットが存在し続ける限り) 保存します。

あなたは しなければならない これらを削除する .DS_Store ファイル ( すべて をGitのインデックスから削除します。 ない を将来のコミットで保存するようにします。 これを実行することで git rm --cached を取り出し、コミットすることで、これらの過去のコミットをチェックアウトするときに、過去の .DS_Store ファイルを作成し、その歴史的なコミットからより新しいコミットに切り替えたときに 欠けている これらの .DS_Store ファイルであれば、Git は 削除 を使用します。

macOSのFinderは、ファイルが見つからない場合、新しい .DS_Store Finder ウィンドウにディレクトリが表示されるたびに、この特定のアクションは この特殊なケース . しかし、以下のようないくつかの点に注意する必要があります。 その他 ファイルを使用する必要がある場合は git rm --cached を追加しました。

オプショナルリーディング:なぜこんなに複雑なのか

Gitの インデックス という比較的貧弱な名前を持っていますが(index? what is it index-ing?)、他に二つの名前を持っています。 Gitはまた、このことを ステージングエリア で、これは使い方を指しており、また キャッシュ は、内部でどのように使用されているかを示しています。 cache"という名前は、大抵の場合 git rm --cached これは、作業ツリーから削除せずにインデックスから削除するように Git に指示します。

さて、これで3つの名前が揃いましたね。 これは何を意味するのでしょうか。 まずひとつは、Gitのインデックスが 本当に重要 . 実際、絶対に欠かせないものです。 しかし、なぜでしょう? なぜGitは何度も何度もそのインデックスを私たちの顔に押し付けるのでしょうか? 結局のところ、本当の答えは その しかし、Linus Torvalds氏にこの選択をさせた要因を見てみる価値はあるでしょう。 これは、以下のことから始まることがわかりました。 コミット .

Gitは、結局のところ、コミットについてです。 についてではありません。 ファイル しかし、ファイルはある意味、各コミットに含まれています。 それは ブランチ名 ブランチ名は、あなた(とGit)を助けるために必要です。 見つける コミットです。 コミットですが は、リポジトリにおける履歴です。 ファイルを保持し、ブランチと呼ぶこともあるものを形成します ( ブランチとはどういう意味ですか? ).

各コミットには、大きな醜いハッシュ ID 番号が振られています。 各コミットには2つのものが保存されます。

  • あなた(あるいは誰であろうと)が を作成しました。 コミット; および
  • メタデータ または、誰が、いつ、何のためにコミットしたかといったコミット自体の情報 (ログメッセージ) を表示します。

コミットのメタデータ内部では、各コミットに対して、ある 以前 コミットが履歴として機能するのはこのためです。 ここでは詳細を説明しませんが、これがブランチの実際の仕組みです。

ここで知っておくべき重要なことは コミットのいかなる部分も変更することはできません . これは、ハッシュID コミットはすべてのデータのチェックサムです。 があります。 Git は、コミットを作成するときにこれらのチェックサムを計算し、コミットを抽出するときに検証を行います。 もし一致しない場合は、コミットが保管中に何らかの理由で破損していることになります。 1 となり、使用することができません。

そのため、保存されているすべてのファイル での コミットは読み取り専用です。 また、圧縮(スペースの節約)、重複排除(スペースと時間の節約)が行われます。 もし、2つのコミットが連続して1000ファイル中999ファイルを共有する場合、それらは 文字通り ファイルを共有します。 変更 ファイルは後のコミットのために保管される必要があります。 しかし、これでは コミット のファイルは、新しい仕事をするためには全く役に立たないのです。

  • 変更できないし
  • ほとんどのプログラムでは 読む を使用します。

だからGit があります。 を使用して、コミットを使用可能な領域へ抽出します。 Gitはこの領域をあなたの 作業ツリー または ワークツリー というのも、ここは仕事をする場所だからです。 ここにあるファイルは普通の日常的なファイルであり、仕事をすることができるのです。

では、Gitに必要なものは何かというと、これはすべてのバージョン管理システムに共通することで、この種の設定はすべて共通です。

  • コミットされた、不変の 歴史的 ファイル、および
  • 仕事をするための作業領域(ワークスペース、ワーキングツリー、その他お好みのもの)。

Gitの場合、ワーク・エリアは文字通り あなたの 好きなように使ってください。 つまり、この中で、あなたが しない Gitにずっと保存しておいてほしいのです。 ここで、あなたは .gitignore が出てきます。 この仮定は 間違い しかし、それは 未完成 .


1 記憶媒体 する 現実の世界では故障がつきものです。 ほとんどの故障は検出されますが 可能性はあります-通常10分の1と言われています 16 というのも、ある種の故障は見逃され、悪いデータが返ってくる可能性があるからです。 Googleは分析を行い、実際のエラーレートは主張されているよりも高い傾向があることを発見しました。


インデックス

Gitに本当に必要なのは コミットするファイルのリスト . つまり、あなたがワークツリーで仕事をしているとします。 数百、数千、あるいはもっと多くのファイルを作成したとします。 2つ に格納する必要があります。 次の を新しいファイルとしてコミットし、残りは無視されるべきです。

この問題に対処する一つの方法は、単に "ignore these files" ファイルを用意して、"ignore these files" ファイルにリストされていないすべてのファイルから、コミットすべきファイルのリストを自動的に生成することです。 しかし、これを試してみると、エラーが発生しやすいことがわかります。 Gitやいくつかの似たようなバージョン管理システムでは、代わりに、明示的に"add some file(s)" というコマンドを使って 追加 をファイルリストに追加します。

では、インデックスです。 は、単なるマニフェストのようなものだったのです。 他のすべてのファイルは、ステータスを要求するときに未追跡として呼び出されるようにします。 . 仮に、このような場合、次のように言ったとします。 すべてのファイルを追加 . あなたはGitに明示的に 無視 その .DS_Store ファイルです。 これらはリストに入ります。 あなたはコミットを行い、そのコミットには .DS_Store ファイルを作成します。 後で、あなたは 意図する をコミットするために .DS_Store ファイルを作成します。

もう遅いんだ。 それらのコミットは今存在しています。 マニフェストに何をしようが、せいぜい .DS_Store のファイル フューチャー のコミットです。 既存のコミットは読み取り専用なので、修正することはできません。 せいぜいできるのは、すべての古いコミットに戻ってひとつひとつを削除し、その中から .DS_Store ファイルを作成し 新しく改良された のコミットで、それ以外はオリジナルと同じですが、現在は .DS_Store ファイルです。

(実際にはこれらすべてを行うことができます。 しかし、それはつまり 他全員 -あなたのリポジトリのクローンを持っている他のすべての人が、古いコミットを使うのをやめて、新しく改良されたコミットを使うようにします)。

さて、Gitのインデックスが特に変わっているのは、例えばMercurialのマニフェストと比較して、このファイルのリストを持っていることで、Linusは次のように決めました。 公開する そして、それを使っていくつかの特別なトリックを行うのです。

  • インデックスには、次のコミットに含まれるすべてのファイル名が格納されます。 git checkout -のみならず、Git内部の ブロブハッシュID のような各ファイルの

  • マージの際に、インデックス 拡大する を持つファイルを一度に3つまで保持することができます。 名前 .

  • git commit コマンド は、わざわざワークツリーを見ようとはしません。 2 その代わり を実行した時点で、インデックス git commit . これは非常に高速です。なぜなら、これらの内部ブロブ・ハッシュIDは、Gitがファイルを保存する方法だからです。実際、それらはすでにそこにあり、あらかじめ圧縮され、重複が取り除かれているのです。

  • その git add コマンドに相当する。 これらのファイルを圧縮・重複排除してインデックスに登録し、 同じ名前の以前のファイルを置き換えるか、以前のファイルがない場合は新しいエントリを作成します。 . 3

  • git rm コマンドの意味は インデックスとワークツリーの両方からファイルを削除します。 . 追加する --cached というのは ワークツリーのコピーに手をつけない .

このようなことから、一つの成果として git commit にあるものはコミットされません。 ワークツリー . このプロパティを使用すると、実際にテストコードをコミットすることなく、テスト目的でワークツリー内のファイルをいじることができます。 これは良いことでもあり悪いことでもあります。良いことが多いか悪いことが多いかについては人によって意見が異なります。

このことは、比較的単純な言葉に集約されます。 インデックスには、常に、あなたの 次回のコミット予定 あるいは、まだ解決されていないマージコンフリクトを保持しているため、現時点ではコミットが不可能な場合もあります。 マージコンフリクトのケースを省けば、インデックスには次のコミット候補が格納されていると考えればよいでしょう。

既存のコミットをチェックアウトするとき、Git はそのインデックスに値を入れます。 から そして、このインデックスを使用して、作業ツリーをファイルで埋めます。 これは、Git が今すぐ 新しい のコミットで、現在のコミットと完全に一致します。 4


2 使い勝手を考えて、ずいぶん前に少し変更になりました。 git commit が実行されるようになりました。 git status を内部で生成し、コメントアウトされた git status セクションをコミットメッセージの中で編集できます。

3 実際に git add は、次のような意味にもなります。 インデックスを一致させる という程度に、もし 削除 ワークツリーファイルの git add は、そのファイルのインデックスコピーを削除することができます。 例えば rm path/to/file; git add path/to/file を実行する長ったらしい方法です。 git rm path/to/file .

4 もしインデックスと現在のコミット する に一致する。 git commit は通常、新規コミットを拒否するので git commit --allow-empty を使用してコミットします。 新しいコミットは -インデックスにあるものはすべて持っていますが は、現在のコミットからは空になります。


これまでのまとめ

Git は作業ツリーから新しいコミットを行わないので、作業ツリー内の .gitignore ファイルには関係ありません。 git commit コマンドを使用します。 その代わり、GitはGitのインデックスにあるものから新しいコミットを行います。 Gitのインデックスの内容は、通常は 現在の コミットします。 5

何らかのファイルを追加したら、次に、そのファイルの は新しいコミットに入り続けます。 を明示的に指定するまで 削除 となります。 このことは、ファイル名が .gitignore ファイルを作成します。 そのファイルを本当に消してしまうには しなければならない を削除してください。 そうすると、現在のコミットと次に行うコミットの差分には、文字通り 削除 というファイルを作成します。

だから 何 が行います。 ファイル名、ディレクトリ名、パターン、その他何でもかんでも .gitignore ファイルの中で .gitignore するのですか? 何かいいことがあるのでしょうか?


5 例外もありますので、例えば、以下をご参照ください。 現在のブランチにコミットされていない変更がある場合、別のブランチをチェックアウトします。 .


.gitignore が行います。

には、2つの便利な機能があります。 .gitignore (などの除外ファイル .git/info/exclude )が行うもので、一種の危険なものです。

  • まず、エンマス git add のような操作を行います。 git add --all または git add . または git add * . 6 あるいは、それどころか、次のようなファイルパターンを列挙することもできます。 *.pyc.gitignore を実行し git add file.pyc はとにかく ここで起こることは単純です。 そのファイルがまだGitのインデックスになく、名前が除外ファイルにある場合。 git add はそれを追加しません。

    これは、あるファイルが現在 未追跡 -未追跡の定義については後述します)、未追跡のままです。 しかし、そのファイルがすでにGitのインデックスに登録されている場合は .gitignore エントリー 効果がない .

  • 次に git status を使用すると、Git はしばしば、さまざまなファイルが追跡されていないことについて泣き言を言います。 除外ファイルの名前あるいはパターンをリストアップする 泣き言を言わなくなる .

危ないのはこれからです。 では 追尾型 では Gitにおける追跡済みのファイルとは、現在Gitのインデックスに登録されているファイルのことです。 これだけです。 実にシンプルです。 ワークツリー内のファイルがGitのインデックスにある場合 今すぐ 追跡されます。 Gitのインデックスにない場合は 今すぐ は、未追跡です。

Gitのインデックスの内容は変化することを忘れないでください もし git checkout をコミットすると、Git はそのインデックスを埋めます。 これらのファイルは、現在追跡されています。 もしあなたが git add を新しいファイルに追加すると、そのファイルはGitのインデックスに登録されます。 そのファイルは、現在追跡されています。 もし git rm -を使用するかしないか --cached -ファイルの上で、そのファイルが来る アウト をGitのインデックスに追加します。 そのファイルは、現在 未追跡 . もちろん、もしあなたが git rm を使用せずに --cached そのファイルは、ワークツリーからも消えてしまいます。 7

git status は、現在のブランチの名前を表示するなどの他に、次のようなことを行います。 git diff コマンドを使用します。

  • 最初の git diff を比較します。 現在のコミット をGitのインデックスに追加します。 同じファイルに対しては、Gitは何も言いません。 すべてのファイルに対して 異なる または新規作成、削除された場合、Git はそのファイルが コミット用ステージ 変更、追加、または削除されるとともに。
  • 2番目の git diff は、Gitのインデックスにあるものとワークツリーにあるものを比較します。 同じファイルについては、Gitは何も言いません。 同じファイルに対して、Gitは何も言いません。 異なる である場合、Git はそのファイルが コミットのためにステージングされていない . ここで少し変わっているのは、ファイルが 新しい を呼び出すと、Git はこれらのファイルを 未追跡 . 最後の部分は、もちろん、未追跡ファイルの定義によるものです。

のファイルをリストアップします。 .gitignore 作る git status 黙る アンタックトネスについて。 実際の追跡可能性には全く影響しません! ただ、泣き言を黙らせるだけです。

最後に、ファイル名やパターンをリストアップするのは .gitignore (または他の除外ファイル)が行うことは、物事がほんの少し危険になるところです。 これは、Gitに 破壊する そのようなファイルを

  • コミット中だとすると a123456... というのは はありません。 があります。 .DS_Store ファイルがあり、その中に .DS_Store ファイルをワークツリーに追加します。 つまり .DS_Store は現在 未追跡 .
  • を発行するようになりました。 git checkout コマンドでチェックアウトし、コミット 4321cab... というのは する があります。 .DS_Store ファイルが含まれています。

コミットを抽出するには 4321cab... の場合、Git は .DS_Store ファイルを Git のインデックスに登録し、そのファイルをワークツリーにコピーします。 すでに .DS_Store ファイルを作成します。 このファイルは上書きされます。

通常、Gitは停止して文句を言います。 おい、コミットを展開すると 4321cab... を破壊してしまいます。 .DS_Store ファイル! これで、貴重なデータなら移動させるチャンスがある。 しかし、もしそのファイルを 無視できる Gitはそれを遠慮なく叩き潰します。

のデータは .DS_Store が貴重とされることはほとんどないので、ここではおそらくOKでしょう。 しかし、一般的には注意してください。


6 の正確な動作は * のような Unix 系のシェルを使っているかどうかで、Git コマンドの内容が変わってきます。 bash のようなDOSスタイルのコマンドインタプリタか、あるいは CMD.EXE しかし、Git自体がグロブ展開を行うので、ほとんど同じような結果になります。 しかし、ここでは取り上げない微妙な違いがあります。

7 ちょっと哲学的な練習問題です。 ghost はありません。 は、ワークツリーにも Git のインデックスにも存在しない、存在しない ghost ファイルもアントラックされますか? (Gitのインデックスにないので、いずれにせよ次のコミットには含まれないでしょう。)たとえば ghost その をGitのインデックスに登録したのに、ワークツリーには登録されていないのですか? このファイルは追跡されているのでしょうか? 次のコミットに含まれるのでしょうか?