如何删除.gitignore中列出但仍在存储库中的文件?

时间:2012-11-24 13:22:40

标签: git ignore gitignore

我的存储库中有一些文件应该被忽略,我将它们添加到.gitignore中,当然,它们不会从我的存储库中删除。

所以我的问题是,是否有一个使用filter-branch的魔术命令或脚本可以重写我的历史记录并轻松删除所有这些文件?或者只是一个命令,它将创建一个将删除它们的提交?

9 个答案:

答案 0 :(得分:340)

您可以手动将其从存储库中删除:

git rm --cached file1 file2 dir/file3

或者,如果你有很多文件:

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

但这似乎并不适用于Windows上的Git Bash。它会产生错误消息。以下效果更好:

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

关于在没有这些文件的情况下重写整个历史记录,我非常怀疑是否有自动方式来实现它。
而且我们都知道重写历史很糟糕,不是吗? :)

答案 1 :(得分:266)

适用于任何操作系统的更简单方法是

git rm -r --cached .
git add .
git commit -m "Removing all files in .gitignore"

你基本上读了所有文件,除了.gitignore

中的文件

答案 2 :(得分:113)

由于未跟踪 .gitignore 中的文件,您可以使用 git clean 命令以递归方式删除不受版本控制的文件。

使用git clean -xdn执行干运行并查看将要删除的内容 然后使用git clean -xdf执行它。

基本上,git clean -hman git-clean(在unix中)会为您提供帮助。

请注意,此命令还会删除不在暂存区域中的新文件

希望它有所帮助。

答案 3 :(得分:4)

我通过使用sed操作.gitignore语句的输出做了一个非常简单的解决方案:

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

说明:

  1. 打印.gitignore文件
  2. 删除打印中的所有评论
  3. 删除所有空行
  4. 添加' git rm -r'到行的开头
  5. 执行每一行。

答案 4 :(得分:1)

"git clean"(man)git ls-files -i(man) 对工作或在被忽略的目录中显示被忽略的路径,这已在 Git 2.32(2021 年第二季度)中得到纠正。

这意味着 the accepted answer 的 2021 版将是:

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

commit b548f0fcommit dd55fc0commit aa6e1b2commit a97c7a8commit 2e4e43acommit b338e9fcommit 7fe1ffd、{{3} }(2021 年 5 月 12 日)作者:commit 7f9dd87
请参阅Elijah Newren (newren)commit 4e689d8(2021 年 5 月 12 日)。
(2021 年 5 月 20 日于 Derrick Stolee (derrickstolee)Junio C Hamano -- gitster -- 合并)

<块引用>

commit 33be431:除非指定了 -o 或 -c,否则 -i 会出错

签字人:Elijah Newren

<块引用>

ls-files(ls-files --ignored) 可以与 --others--cached 一起使用。

在困惑了一段时间并深入研究代码之后,我认为 ls-files -i 只是坏了,没有打印任何东西,当我终于意识到 -i可与 --cached 一起使用以查找跟踪的忽略。

虽然这是我的错误,仔细阅读文档可以更清楚地说明这一点,但我怀疑这也是其他人可能会犯的错误。
事实上,在我们的测试套件中的两个用途中,我相信这两个中的一个确实犯了这个错误。
在 t1306.13 中,没有跟踪文件,因此在该测试和之前的测试中建立和使用的所有排除项都必须与未跟踪文件有关。
然而,由于他们正在寻找一个空的结果,错误没有被注意到,因为他们的错误命令也恰好给出了一个空的答案。

-i 大部分时间与 -o 一起使用,这表明我们可以在没有 -i 的情况下让 -o 暗示 -o-c,但这将是向后不兼容的中断。
相反,让我们将没有 -i-o-c 标记为错误,并更新两个相关的测试用例以指定它们的意图。

这意味着如果没有 -c,您会得到(从 Git 2.32 开始,2021 年第二季度):

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

注意:这仍在进行中,因为它是 man,但已通过 reverted in Git 2.32-rc2commit 2c9f1bf(2021 年 5 月 27 日)由 commit 1df046b 修复。
请参阅Junio C Hamano (gitster)commit 906fc55(2021 年 5 月 27 日)。
请参阅Elijah Newren (newren)commit eef8148(2021 年 5 月 27 日)。
(于 2021 年 5 月 28 日在 Derrick Stolee (derrickstolee)Junio C Hamano -- gitster -- 合并)

<块引用>

commit 329d63e:引入 readdir_skip_dot_and_dotdot() 助手

签字人:Elijah Newren

答案 5 :(得分:0)

在Linux中,您可以使用以下命令:

例如,我想删除“ * .py〜”,因此我的命令应为==>

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

答案 6 :(得分:0)

如果您确实想修剪.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目录中运行,即,如果您要使用相对路径,则必须先添加一个../。显然,由于某些原因,您不能使用../.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可能无法正常工作,即您可能无法直接正确转移单个分支的标签

答案 7 :(得分:0)

不能说这是一个合适的解决方案,但是您可以尝试一下。

步骤

  • 我希望您已经克隆了您的仓库。
  • 现在将文件复制到项目之外的某个地方。
  • 添加该文件名并在gitigonre文件中添加一个位置。
  • 从本地项目中删除该文件。
  • 将您的代码推送到远程来源。
  • 现在将复制的文件添加到您的项目中,它将被忽略。

如果您要保留历史记录,而不是在其中增加麻烦,这只是黑客解决方案

如果您不想使用此解决方案,请忽略并尝试避免使用它。因为我真的在努力提高自己的分数

答案 8 :(得分:-2)

将git添加到.gitignore后,git会忽略匹配的.gitignore模式。

但是存储库中已经存在的文件仍然存在。

使用git rm files_ignored; git commit -m 'rm no use files'删除被忽略的文件。