504

リポジトリに無視する必要のあるファイルがいくつかあります。それらを.gitignoreに追加しましたが、もちろん、リポジトリから削除されません。

だから私の質問は、私の履歴を書き換えてこれらすべてのファイルを簡単に削除できるフィルターブランチを使用した魔法のコマンドまたはスクリプトはありますか?または、それらを削除するコミットを作成するコマンドですか?

4

9 に答える 9

635

それらをリポジトリから手動で削除できます。

git rm --cached file1 file2 dir/file3

または、ファイルがたくさんある場合:

git rm --cached `git ls-files -i -c --exclude-from=.gitignore`

しかし、これはWindowsのGitBashでは機能しないようです。エラーメッセージが表示されます。以下の方がうまく機能します。

git ls-files -i -c --exclude-from=.gitignore | xargs git rm --cached  

Windows上のPowerShellでは、これはさらにうまく機能します(パスとファイル名のスペースを処理します)。

git ls-files -i -c --exclude-from=.gitignore | %{git rm --cached $_}

これらのファイルを使用せずに履歴全体を書き換えることに関しては、自動的にそれを行う方法があるかどうかは非常に疑わしいです。
そして、歴史を書き直すのは悪いことだということは誰もが知っていますね。:)

于 2012-11-24T13:34:35.997 に答える
496

OSに関係なく機能する簡単な方法は、

git rm -r --cached .
git add .
git commit -m "Drop files from .gitignore"

基本的にすべてのファイルを削除して再度追加しますが、内のファイルgit addは無視します.gitignore

この--cachedオプションを使用すると、ファイルシステムにファイルが保持されるため、ディスクからファイルを削除することはありません。

注:コメントの中で、すべてのファイルの履歴が失われるとの指摘もありました。MacOSでgit2.27.0を使用してこれをテストしましたが、そうではありません。何が起こっているかを確認したい場合はgit diff HEAD~1、コミットをプッシュする前に確認してください。

于 2015-12-23T11:58:30.537 に答える
186

.gitignore内のファイルは追跡されていないため、git cleanコマンドを使用して、バージョン管理されていないファイルを再帰的に削除できます。

git clean -xdnドライランを実行し、何が削除されるかを確認するために使用します。
次に、を使用git clean -xdfして実行します。

基本的に、git clean -hまたはman git-clean(UNIXでは)あなたに助けを与えるでしょう。

このコマンドは、ステージング領域にない新しいファイルも削除することに注意してください。

それが役に立てば幸い。

于 2016-04-12T12:45:48.387 に答える
9

.gitignoreステートメントの出力をsedで操作することにより、非常に簡単な解決策を実行しました。

cat .gitignore | sed '/^#.*/ d' | sed '/^\s*$/ d' | sed 's/^/git rm -r /' | bash

説明:

  1. .gitignoreファイルを印刷します
  2. 印刷からすべてのコメントを削除します
  3. 空の行をすべて削除します
  4. 行の先頭に「gitrm-r」を追加します
  5. すべての行を実行します。
于 2017-09-29T17:54:16.647 に答える
3

" git clean" manmanは、無視されたディレクトリ内で無視されたパスを処理したり表示したりすることについて混乱していました。これはGit 2.32(Q2 2021)で修正されました。git ls-files -i

つまり、受け入れられた回答の2021バージョンは次のようになります。

git ls-files -i -c --exclude-from=.gitignore | xargs git rm --cached  
                ^^

Elijah Newren(によるcommit b548f0f、 commit dd55fc0、 commit aa6e1b2、 commit a97c7a8commit 2e4e43acommit b338e9fcommit 7fe1ffdcommit 7f9dd87(12 May 2021)を参照してください。Derrick Stolee()によるcommit 4e689d8(2021年5月12日) を参照してください。( Junio C Hamanoによってマージされました---コミット33be431、2021年5月20日newren
derrickstolee
gitster

ls-files:-oまたは-cが指定されていない限り、-iでエラーが発生します

サインオフ-作成者:Elijah Newren

ls-files --ignoredmanはまたはと一緒に使用でき--othersます--cached

少し戸惑い、コードを掘り下げた後、それは壊れていて何も印刷されていないと思いました。追跡された無視を見つけるために使用できることls-files -iにようやく気付いたとき、提出する準備ができた素敵なパッチがありました。-i--cached

それは私の側の間違いであり、ドキュメントを注意深く読むことでこれをより明確にすることができたかもしれませんが、これは他の人も同様に犯す可能性のあるエラーだと思います。
実際、私たちのテストスイートでの2つの使用のうち、2つのうちの1つがこのエラーを引き起こしたと思います。
t1306.13では、追跡されたファイルはありません。したがって、そのテストおよび以前のテストで構築および使用されたすべての除外は、追跡されていないファイルに関するものである必要があります。
しかし、彼らは空の結果を探していたので、彼らの誤ったコマンドもたまたま空の答えを与えたので、間違いは見過ごされました。

-iほとんどの場合、で使用されます。これは、またはのいずれかがない場合に暗示すること-oができることを示唆しますが、それは後方互換性のないブレークになります。代わりに、またはエラーなしでフラグを立て、関連する2つのテストケースを更新してその意図を指定し ましょう。-i-o-o-c
-i-o-c

つまり、がない-cと、次のようになります(Git 2.32、2021年第2四半期以降)。

fatal: ls-files -i must be used with either -o or -c

注:これはまだ進行中の作業です。Git2.32 -rc2で元に戻されましたが、 Junio C Hamano()によるcommit 2c9f1bfcommit 1df046b(2021年5月27日)で修正されました。Elijah Newren()によるcommit 906fc55(2021年5月27日) を参照してください。Derrick Stolee()によるcommit eef8148(2021年5月27日) を参照してください。( Junio C Hamanoによってマージされました---コミット329d63e 、20215月28日)gitster
newren
derrickstolee
gitster

dirreaddir_skip_dot_and_dotdot():ヘルパーを紹介する

サインオフ-作成者:Elijah Newren

于 2021-05-23T21:07:36.420 に答える
1

.gitignore本当にdファイルの履歴を整理したい場合は、最初.gitignoreにリポジトリの外に保存します。たとえば、として保存して/tmp/.gitignoreから、を実行します。

git filter-branch --force --index-filter \
    "git ls-files -i -X /tmp/.gitignore | xargs -r git rm --cached --ignore-unmatch -rf" \
    --prune-empty --tag-name-filter cat -- --all

ノート:

  • git filter-branch --index-filter私が思うディレクトリで実行され.gitます。つまり、相対パスを使用する場合は、最初にもう1つ追加する必要があります../。そして、どうやら../.gitignore、実際の.gitignoreファイルを使用することはできません。これは、何らかの理由で「致命的:../.gitignoreを除外ファイルとして使用できません」を生成します(おそらくgit filter-branch --index-filter、作業ディレクトリが空であると見なされますか?)
  • git ls-files -iX <(git show $(git hash-object -w .gitignore))他の場所へのコピーを避けるために、代わりにのようなものを使用したいと思っていまし.gitignoreたが、それだけですでに空の文字列が返されるため(cat <(git show $(git hash-object -w .gitignore))実際には.gitignore、期待どおりにの内容が出力されます)、で使用することはできませ<(git show $GITIGNORE_HASH)git filter-branch...
  • 実際に.gitignore特定のブランチのみをクリーンアップする場合--allは、最後の行をその名前に置き換えます。その--tag-name-filter cat場合、は正しく機能しない可能性があります。つまり、単一のブランチのタグを直接正しく転送できない可能性があります。
于 2020-11-23T10:03:03.113 に答える
0

Linuxでは、次のコマンドを使用できます。

たとえば、削除したい*.py~ので、コマンドは==>になります。

find . -name "*.py~" -exec rm -f {} \;

于 2019-11-26T15:21:15.863 に答える
0

このソリューションは、キャリッジリターン(私はWSLユーザーなので、これは重要です)と括弧のエスケープ(LaTeXユーザーにとって重要な場合があります)を追加します*.synctex(busy)


スコットのソリューションに触発されました:

cat .gitignore | sed "s/\r//" | sed -r "/^(#.*|\s*)$/d" | sed -r "s/([()])/\\\\\1/g" | sed "s/^/git rm -r /" | bash
  1. 削除:キャリッジリターン(s/\r//)。
  2. コメント(/^#.*$/)、空の行グループ(/^\s*$/、空白または空の行に一致)を含む行を削除します。パイプ|文字に注意してください。これは標準の正規表現であり、必要です-r(ただし、これも機能すると思います-E)。
  3. 置換:括弧/([()])/をエスケープされたバージョン\\\1\1、グループと一致します。この場合、一致したものはすべて、、または、を意味[()](ます)。フラグに注意してください。これは、すべての括弧gに一致(および置換)するためのものです。あなたがそれに興味があるかのように書き直すことができます。"s/(\(|\))/\\\\\1/g"
  4. プリペンドgit rm -r

交換はのように見えますs/$old/$new/$flags。削除はのように見えます/$old/d。プリペンディングは置き換えて/^/います。そして、を置き換えることで追加を行うことができます/$/。そしてもちろん、私が知る限り、bashで生の文字列を作成できないため、一部の文字はエスケープされます。最後に、この行は要約できますが、読みやすくするために拡張したままにすることにしました。


私は誰かが(スコットの解決策で)sed簡単な質問をしているのを見ました。私はこの方法を最も基本的で最も猿のように考えるのが好きです。これは良い方法です。これのバリエーションが必要になった場合は、その場で作成できるからです。そして、どちらかといえば、正規表現を練習することは良い言い訳です。

于 2021-11-24T06:43:46.347 に答える
-5

gitは、.gitignoreに追加した後、.gitignoreパターンに一致するファイルを無視します。

ただし、リポジトリにすでに存在するファイルは引き続き存在します。

git rm files_ignored; git commit -m 'rm no use files'無視されたファイルを削除するために使用します。

于 2012-11-24T13:31:16.170 に答える