Gitによって追跡されていたファイルがありますが、現在そのファイルは.gitignore
リストにあります。
git status
ただし、そのファイルは編集後も表示され続けます。Gitにそれを完全に忘れさせるにはどうすればよいですか?
.gitignore
追跡されていないファイルがGitによって追跡されているファイルのセットに(なしで)追加されるのを防ぎますadd -f
が、Gitはすでに追跡されているファイルを引き続き追跡します。
ファイルの追跡を停止するには、ファイルをインデックスから削除する必要があります。これは、このコマンドで実行できます。
git rm --cached <file>
フォルダ全体を削除する場合は、その中のすべてのファイルを再帰的に削除する必要があります。
git rm -r --cached <folder>
ヘッドリビジョンからのファイルの削除は、次のコミットで行われます。
警告:これによってローカルから物理ファイルが削除されることはありませんが、次の開発者のマシンからファイルが削除されますgit pull
。
以下の一連のコマンドは、(作業ディレクトリやローカルリポジトリからではなく)Gitインデックスからすべてのアイテムを削除し、Gitが無視することを尊重しながら、Gitインデックスを更新します。PS。インデックス=キャッシュ
初め:
git rm -r --cached .
git add .
それで:
git commit -am "Remove ignored files"
またはワンライナーとして:
git rm -r --cached . && git add . && git commit -am "Remove ignored files"
git update-index
私のために仕事をします:
git update-index --assume-unchanged <file>
注:.gitignore
gitignoreは追跡されていないファイル専用であるため、このソリューションは実際には独立しています。
この回答が投稿されてから、新しいオプションが作成されました。これを優先する必要があります。--skip-worktree
これは、ユーザーがもうコミットしたくない変更された追跡ファイルに使用し、パフォーマンスを維持し--assume-unchanged
て、gitが大きな追跡ファイルのステータスをチェックしないようにする必要があります。詳細については、 https://stackoverflow.com/a/13631525/717372を参照してください...
git update-index --skip-worktree <file>
キャンセルします
git update-index --no-skip-worktree <file>
git ls-files -c --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"
これにより、無視されたファイルのリストが取得され、インデックスから削除され、変更がコミットされます。
私は常にこのコマンドを使用して、追跡されていないファイルを削除します。1行、Unixスタイル、クリーンな出力:
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached
無視されたすべてのファイルが一覧表示され、すべての出力行が引用符で囲まれた行に置き換えられ、内部にスペースがあるパスが処理され、すべてが渡されgit rm -r --cached
てパス/ファイル/ディレクトリがインデックスから削除されます。
移動してコミットしてから、元に戻します。
これは過去に私にとってはうまくいきましたが、おそらくこれを達成するための「より巧妙な」方法があります。
コピー/貼り付けの答えは次のとおりです。
git rm --cached -r .; git add .; git status; git commit -m "Ignore unwanted files"
このコマンドはファイルの内容を変更しません.gitignore
。すでにGitリポジトリにコミットされているファイルは無視されますが、ここでそれらをに追加しました.gitignore
。
コマンドgit status;
は変更を確認するだけであり、削除される可能性があります。
最後に、「不要なファイルを無視します」というメッセージを表示して、変更をすぐにコミットします。
変更をコミットしたくない場合は、コマンドの最後の部分を削除します(git commit -m "Ignore unwanted files"
)
ソース:.gitignoreに基づいてGitリポジトリにすでに追加されているファイルを追跡解除する
すでにいくつかのファイルをGitリポジトリに追加/コミットしてから、それらを.gitignoreファイルに追加したとします。これらのファイルは、リポジトリインデックスに引き続き存在します。この記事では、それらを取り除く方法を説明します。
続行する前に、 .gitignoreファイルを含むすべての変更がコミットされていることを確認してください。
リポジトリをクリアするには、次を使用します。
git rm -r --cached .
rm
コマンドは容赦のないものになる可能性があります。事前にそれが何をするかを試したい場合は、-n
または--dry-run
フラグを追加してテストしてください。
git add .
git commit -m ".gitignore fix"
あなたのリポジトリはきれいです:)
変更をリモコンにプッシュして、そこでも有効な変更を確認します。
他の人がファイルを必要としている可能性があるために追跡できないgit rm
ファイルの場合(たとえあなた git rm --cached
がこの変更を受け取ったとしても、他の誰かがこの変更を取得すると、そのファイルはファイルシステムで削除されます)。これらは、構成ファイルのオーバーライド、認証資格情報などが原因で行われることがよくあります。問題を回避する方法については、 https://gist.github.com/1423106を参照してください。
要約する:
これは、 gitfilter-branchを使用して実現しました。私が使用した正確なコマンドは、マニュアルページから取得されました。
警告:これにより、履歴全体からファイルが削除されます
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
このコマンドは、コミット履歴全体を再作成し、git rm
各コミットの前に実行するため、指定されたファイルを削除します。コマンドを実行する前にバックアップすることを忘れないでください。コマンドは失われます。
ls-files --ignored --exclude-standard | xargs git rm -r --cached
(Linuxでは)アプローチを提案するここの投稿を使用したいと思いました。\n
ただし、削除されるファイル(の一部)には、名前に改行/LF/が埋め込まれていました。どちらの解決策も:
git ls-files --ignored --exclude-standard | xargs -d"\n" git rm --cached
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached
この状況に対処します(ファイルが見つからないというエラーが発生します)。
git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git commit -am "Remove ignored files"
これは、ls-filesの-z
引数と、 xargsの引数を使用して、ファイル名の「厄介な」文字に安全に/正しく対応します。-0
マニュアルページgit-ls-files(1)には、次のように記載されています。
-zオプションを使用しない場合、パス名のTAB、LF、およびバックスラッシュ文字は、それぞれ\ t、\ n、および\\として表されます。
したがって、ファイル名にこれらの文字が含まれている場合は、私の解決策が必要だと思います。
ファイル/フォルダーに対して次の手順を実行します。
ファイルを削除します。
例えば:
test.txtファイルを削除したい。誤ってGitHubにプッシュしたので、削除したいと思います。コマンドは次のようになります。
まず、ファイル.gitignoreに「test.txt」を追加します
git rm --cached test.txt
git add .
git commit -m "test.txt removed"
git push
フォルダを削除:
例えば:
.ideaフォルダ/ディレクトリを削除したい。誤ってGitHubにプッシュしたので、削除したいと思います。コマンドは次のようになります。
まず、ファイル.gitignoreに.ideaを追加します
git rm -r --cached .idea
git add .
git commit -m ".idea removed"
git push
ファイルを更新します。.gitignore
たとえば、追跡したくないフォルダを追加します.gitignore
。
git rm -r --cached .
–必要なファイルと不要なファイルを含め、追跡されたすべてのファイルを削除します。ローカルに保存している限り、コードは安全です。
git add .
–内のファイルを除き、すべてのファイルが再び追加され.gitignore
ます。
私たちを正しい方向に向けてくれた@AkiraYamamotoへの帽子のヒント。
次の手順を順番に実行すると、問題はありません。
誤って追加したファイルをディレクトリ/ストレージから削除します。「rm-r」(Linuxの場合)コマンドを使用するか、ディレクトリを参照して削除することができます。または、PC上の別の場所に移動します。(移動/削除のために実行している場合は、IDEを閉じる必要があるかもしれません。)
ここでファイル/ディレクトリを.gitignoreファイルに追加して保存します。
次に、これらのコマンドを使用してGitキャッシュからそれらを削除します(複数のディレクトリがある場合は、このコマンドを繰り返し発行して1つずつ削除します)
git rm -r --cached path-to-those-files
次に、次のコマンドを使用してコミットとプッシュを実行します。これにより、これらのファイルがGitリモートから削除され、Gitはこれらのファイルの追跡を停止します。
git add .
git commit -m "removed unnecessary files from Git"
git push origin
おそらく、Gitはその概念( 「違いではなくスナップショット」のセクション)のためにファイルを完全に忘れることはできないと思います。
この問題は、たとえばCVSを使用している場合には発生しません。CVSは、ファイルベースの変更のリストとして情報を保存します。CVSの情報は、ファイルのセットと、時間の経過とともに各ファイルに加えられた変更です。
ただし、Gitでは、プロジェクトの状態をコミットまたは保存するたびに、基本的にその時点でのすべてのファイルの外観の写真が撮られ、そのスナップショットへの参照が保存されます。したがって、ファイルを1回追加すると、そのファイルは常にそのスナップショットに存在します。
これらの2つの記事は私にとって役に立ちました:
gitassume-変更なしvsスキップワークツリーとGitで追跡されたファイルの変更を無視する方法
ファイルがすでに追跡されている場合は、それに基づいて次のことを行います。
git update-index --skip-worktree <file>
この時点から、このファイルのすべてのローカル変更は無視され、リモートには移動しません。リモートでファイルを変更すると、。のときに競合が発生しgit pull
ます。スタッシュは機能しません。これを解決するには、ファイルの内容を安全な場所にコピーし、次の手順に従います。
git update-index --no-skip-worktree <file>
git stash
git pull
ファイルの内容はリモートの内容に置き換えられます。変更を安全な場所からファイルに貼り付けて、もう一度実行します。
git update-index --skip-worktree <file>
プロジェクトに携わるすべての人が実行するのであればgit update-index --skip-worktree <file>
、問題はpull
ないはずです。すべての開発者が独自のプロジェクト構成を持っている場合、このソリューションは構成ファイルに適しています。
リモートでファイルが変更されたときに毎回これを行うのはあまり便利ではありませんが、リモートコンテンツによる上書きからファイルを保護することができます。
コマンドを使用してgit rm --cached
も、元の質問には答えられません。
git
[ファイル]を完全に忘れるにはどうすればよいですか?
実際、このソリューションでは、 !を実行すると、リポジトリの他のすべてのインスタンスでファイルが削除されます。git pull
Gitにファイルを忘れさせる正しい方法は、GitHubによってここに文書化されています。
ドキュメントを読むことをお勧めしますが、基本的には次のとおりです。
git fetch --all
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch full/path/to/file' --prune-empty --tag-name-filter cat -- --all
git push origin --force --all
git push origin --force --tags
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
full/path/to/file
ファイルのフルパスに置き換えるだけです。ファイルをファイルに追加したことを確認してください.gitignore
。
また、Gitの履歴を変更するため、リポジトリへの非早送りプッシュを(一時的に)許可する必要があります。
Matt Frearからの回答は、最も効果的なIMHOでした。以下は、除外リストに一致するファイルのみをGitリポジトリから削除するWindows上のPowerShellスクリプトです。
# Get files matching exclusionsfrom .gitignore
# Excluding comments and empty lines
$ignoreFiles = gc .gitignore | ?{$_ -notmatch "#"} | ?{$_ -match "\S"} | % {
$ignore = "*" + $_ + "*"
(gci -r -i $ignore).FullName
}
$ignoreFiles = $ignoreFiles| ?{$_ -match "\S"}
# Remove each of these file from Git
$ignoreFiles | % { git rm $_}
git add .
ファイルを安全な場所に移動またはコピーして、紛失しないようにします。次に、ファイルを「gitrm」してコミットします。
これらの以前のコミットの1つ、またはファイルが削除されていない別のブランチに戻ると、ファイルは引き続き表示されます。ただし、今後のすべてのコミットでは、ファイルが再び表示されることはありません。ファイルがGit無視にある場合は、ファイルをフォルダーに戻すことができ、Gitはそれを認識しません。
JonBraveの答えは気に入りましたが、作業ディレクトリが乱雑でcommit -a
少し怖いので、次のようにしました。
git config --global alias.exclude-ignored '!git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached && git ls-files -z --ignored --exclude-standard | xargs -0 git stage && git stage .gitignore && git commit -m "new gitignore and remove ignored files from index"'
それを分解する:
git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git ls-files -z --ignored --exclude-standard | xargs -0 git stage
git stage .gitignore
git commit -m "new gitignore and remove ignored files from index"
私の場合、 .gitignoreファイルに「 .envrc
」を入れる必要がありました。
そして、私は使用しました:
git update-index --skip-worktree .envrc
git rm --cached .envrc
そして、ファイルは削除されました。
次に、ファイルが削除されたことを伝えて、再度コミットしました。
しかし、コマンドを使用したとき、ファイルのコンテンツ( Amazon S3git log -p
の秘密のクレデンシャルでした)は削除されたコンテンツを表示していたので、Gitリポジトリの履歴にこのコンテンツを表示したくありません。
次に、次のコマンドを使用しました。
git filter-branch --index-filter 'git rm --cached --ignore-unmatch .envrc' HEAD
そして、私はその内容を二度と見ません。
BFGは、Gitリポジトリから大きなファイルやパスワードなどの不要なデータを削除するように特別に設計されているため、大きな履歴(現在のコミットではない)ファイルを削除する単純なフラグがあります。'--strip-blobs-より大きい'
java -jar bfg.jar --strip-blobs-bigger-than 100M
名前でファイルを指定したい場合は、次のようにすることもできます。
java -jar bfg.jar --delete-files *.mp4
BFGは10〜1000倍高速でgit filter-branch
、一般的にはるかに使いやすいです。詳細については、完全な使用手順と例を確認してください。
出典:リポジトリサイズを縮小
CLIを使用せずにWindowsで作業している場合、非常に簡単な解決策はTortoiseGitを使用することです。メニューに「削除(ローカル保持)」アクションがあり、正常に機能します。
受け入れられた答えは、「Gitにファイルを「忘れさせる」 ...」(歴史的に)ではありません。Gitに現在/将来のファイルを無視させるだけです。
この方法では、Gitは無視されたファイル(過去/現在/将来)を完全に忘れますが、作業ディレクトリからは何も削除されません(リモートから再プルされた場合でも)。
この方法では、ファイル/.git/info/exclude
(推奨)を使用するか、ファイルを無視/忘れるすべてのコミットに既存の .gitignore
ものを使用する必要があります。1
Gitを強制するすべての方法は、事後の動作を無視して履歴を効果的に書き換えるため、このプロセスの後にプルされる可能性のあるパブリック/共有/コラボレーションリポジトリに重大な影響を及ぼします。2
一般的なアドバイス:クリーンなリポジトリから始めてください-すべてがコミットされ、作業ディレクトリまたはインデックスで保留中のものはなく、バックアップを作成してください!
また、この回答のコメント/改訂履歴(およびこの質問の改訂履歴)は、役立つ/啓発的である可能性があります。
#Commit up-to-date .gitignore (if not already existing)
#This command must be run on each branch
git add .gitignore
git commit -m "Create .gitignore"
#Apply standard Git ignore behavior only to the current index, not the working directory (--cached)
#If this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#This command must be run on each branch
git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached
#Commit to prevent working directory data loss!
#This commit will be automatically deleted by the --prune-empty flag in the following command
#This command must be run on each branch
git commit -m "ignored index"
#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits. If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command
git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all
#List all still-existing files that are now ignored properly
#If this command returns nothing, it's time to restore from backup and start over
#This command must be run on each branch
git ls-files --other --ignored --exclude-standard
最後に、以下のコマンドに関する重要な警告/情報を含む、このGitHubガイドの残りの部分(ステップ6から開始)に従ってください。
git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now
現在変更されているリモートリポジトリからプルする他の開発者は、バックアップを作成してから、次のことを行う必要があります。
#fetch modified remote
git fetch --all
#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed
git reset FETCH_HEAD
1/.git/info/exclude
上記の手順を使用してすべての履歴コミットに適用できるため、ファイルを必要とする履歴コミットに.gitignore
ファイルを取り込む方法の詳細は、この回答の範囲を超えています。私.gitignore
が最初にしたことのように、適切なファイルをルートコミットに含める必要がありました。/.git/info/exclude
コミット履歴のどこにファイルが存在するかに関係なく同じことを実行できるため、他の人は気にしないかもしれません。また、影響を認識している場合でも、.gitignore
履歴の書き換えは非常に厄介な問題です。
FWIW、潜在的なメソッドには、この質問への回答のように、外部を各コミットにコピーする、git rebase
またはが含まれる場合があります。git filter-branch
.gitignore
2スタンドアロンコマンドの結果をコミットしてGitの事後無視動作を強制すると、強制的にプッシュされたリモートからの将来のプルでgit rm --cached
、新たに無視されたファイルが削除される可能性があります。次のコマンドの--prune-empty
フラグはgit filter-branch
、以前の「無視されたすべてのファイルを削除する」インデックスのみのコミットを自動的に削除することにより、この問題を回避します。Gitの履歴を書き換えると、コミットハッシュも変更され、パブリック/共有/コラボレーションリポジトリからの将来のプルに大混乱をもたらします。このようなリポジトリに対してこれを行う前に、影響を完全に理解してください。このGitHubガイドでは、次のことを指定しています。
共同作業者に、古い(汚染された)リポジトリ履歴から作成したブランチをマージするのではなく、リベースするように指示します。1回のマージコミットで、パージの問題が発生したばかりの汚染された履歴の一部またはすべてが再導入される可能性があります。
リモートリポジトリに影響を与えない代替ソリューションは、git update-index --assume-unchanged </path/file>
またはです。git update-index --skip-worktree <file>
その例はここにあります。
これは、最新のGit (執筆時点ではv2.17.1)では問題ではなくなりました。
.gitignoreファイルは、追跡されたが削除されたファイルを最終的に無視します。次のスクリプトを実行して、これを自分でテストできます。最後のgit status
ステートメントは、「コミットするものは何もない」と報告する必要があります。
# Create an empty repository
mkdir gitignore-test
cd gitignore-test
git init
# Create a file and commit it
echo "hello" > file
git add file
git commit -m initial
# Add the file to gitignore and commit
echo "file" > .gitignore
git add .gitignore
git commit -m gitignore
# Remove the file and commit
git rm file
git commit -m "removed file"
# Reintroduce the file and check status.
# .gitignore is now respected - status reports "nothing to commit".
echo "hello" > file
git status
これが私の問題を解決した方法です:
git filter-branch --tree-filter 'rm -rf path/to/your/file' HEAD
git push
これでは、基本的に、以前のコミットでもその特定のファイルの履歴を書き換えようとしています。
詳細については、ここでfilter-branchのmanページを参照してください。
git rm --cached -r <YOUR_files_or_folders>
--キャッシュ| インデックスからファイルを削除するだけです
すでにコミットされている場合DS_Store
:
find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch
それらを無視します:
echo ".DS_Store" >> ~/.gitignore_global
echo "._.DS_Store" >> ~/.gitignore_global
echo "**/.DS_Store" >> ~/.gitignore_global
echo "**/._.DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global
最後に、コミットしてください!
特にIDEベースのファイルの場合、私はこれを使用します。
たとえば、slnx.sqliteファイルの場合、次のように完全に削除しました。
git rm {PATH_OF_THE_FILE}/slnx.sqlite -f
git commit -m "remove slnx.sqlite"
これらのファイルの一部には、プロジェクトのローカルユーザー設定と設定(開いたファイルなど)が保存されていることに注意してください。したがって、IDEでナビゲートしたり変更を加えたりするたびに、そのファイルが変更されるため、ファイルがチェックアウトされ、コミットされていない変更として表示されます。
誰かがWindowsで苦労していて、フォルダー全体を無視したい場合は、ファイルエクスプローラーの目的の「フォルダー」に移動し、右クリックして「GitBashHere」を実行します(Git for Windowsがインストールされている必要があります)。
次のコマンドを実行します。
git ls-files -z | xargs -0 git update-index --assume-unchanged
ここでの私の場合、削除する必要のあるいくつかのディレクトリにいくつかの.lockファイルがありました。私は以下を実行し、それらを削除するために各ディレクトリに移動する必要なしに機能しました:
git rm -r --cached **/*.lock
これを行うと、私がいた場所の「ルート」の下の各フォルダーに移動し、パターンに一致するすべてのファイルを除外しました。