我的存储库中有一些文件应该被忽略,我将它们添加到.gitignore中,当然,它们不会从我的存储库中删除。
所以我的问题是,是否有一个使用filter-branch的魔术命令或脚本可以重写我的历史记录并轻松删除所有这些文件?或者只是一个命令,它将创建一个将删除它们的提交?
答案 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 -h
或man git-clean
(在unix中)会为您提供帮助。
请注意,此命令还会删除不在暂存区域中的新文件。
希望它有所帮助。
答案 3 :(得分:4)
我通过使用sed操作.gitignore语句的输出做了一个非常简单的解决方案:
cat .gitignore | sed '/^#.*/ d' | sed '/^\s*$/ d' | sed 's/^/git rm -r /' | bash
说明:
答案 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 b548f0f、commit dd55fc0、commit aa6e1b2、commit a97c7a8、commit 2e4e43a、commit b338e9f、commit 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
-- 合并)
签字人: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-rc2、commit 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
-- 合并)
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)
我不能说这是一个合适的解决方案,但是您可以尝试一下。
步骤
如果您要保留历史记录,而不是在其中增加麻烦,这只是黑客解决方案。
如果您不想使用此解决方案,请忽略并尝试避免使用它。因为我真的在努力提高自己的分数
答案 8 :(得分:-2)
将git添加到.gitignore后,git会忽略匹配的.gitignore模式。
但是存储库中已经存在的文件仍然存在。
使用git rm files_ignored; git commit -m 'rm no use files'
删除被忽略的文件。