如何使Git“忘记”一个被跟踪的文件,但现在在.gitignore?
有一个文件被git
一次跟踪,但现在这个文件在.gitignore
列表中。
但是,该文件在编辑后一直显示在git status
。 你怎么强迫git
完全忘记它?
.gitignore
将防止未跟踪的文件被添加(没有add -f
)到由git跟踪的文件集,但git将继续跟踪任何已经被跟踪的文件。
要停止跟踪文件,您需要将其从索引中删除。 这可以通过这个命令来实现。
git rm --cached <file>
在下一次提交时,将会从头版本中删除文件。
下面的一系列命令将从Git索引(不是从工作目录或本地回购)中删除所有项目,然后更新Git索引,同时尊重git忽略。 PS。 索引=caching
第一:
git rm -r --cached . git add .
然后:
git commit -am "Remove ignored files"
git update-index为我做的工作:
git update-index --assume-unchanged <file>
注意:这个解决scheme实际上是独立于.gitignore
因为gitignore只适用于未跟踪的文件。
git ls-files --ignored --exclude-standard | xargs git rm --cached git commit -am "Remove ignored files"
这取得了被忽略的文件的列表,并将其从索引中删除,然后提交更改。
我总是使用这个命令来删除那些未跟踪的文件。 一行,Unix风格,干净的输出:
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached
它列出了所有被忽略的文件,用引用行replace每个输出行,而不是用空格来处理path,并将所有内容都传递给git rm -r --cached
以从索引中删除path/文件/目录。
如果因为其他人可能需要这个文件(如警告,即使你是 git rm --cached
,当其他人得到这个改变,他们的文件将被删除到他们的文件系统) .github.com / 1423106为人们解决问题的方式。
把它搬出来,承诺,然后把它移回去。这对我来说是过去的工作。 有可能是一个“gittier”的方式来实现这一点。
什么不适合我
(在Linux下),我想在这里使用提示ls-files --ignored --exclude-standard | xargs git rm -r --cached
的post ls-files --ignored --exclude-standard | xargs git rm -r --cached
方法。 但是,(某些)要删除的文件的名称中包含换行符/ LF / \n
。 这两个解决scheme都不是:
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
应对这种情况(获取有关文件未find错误)。
所以我提供
git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
这对ls文件使用-z
参数,对xargs使用-0
参数来安全/正确地处理文件名中的“讨厌”字符。
在手册页git-ls-files(1)中 ,它指出:
当不使用-z选项时,path名中的TAB,LF和反斜杠字符分别表示为\ t,\ n和\\。
所以我认为我的解决scheme是需要的,如果文件名中有任何这些字符。
编辑:我已经被要求添加—就像任何git rm
命令—这必须跟一个提交使删除永久性,例如git commit -am "Remove ignored files"
。
我通过使用git filter-branch完成了这个任务。 我使用的确切命令是从手册页获取的:
警告 :这将从您的整个历史logging中删除该文件
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
这个命令将重新创build整个提交历史logging,在每次提交之前执行git rm
,因此将删除指定的文件。 运行命令之前不要忘记将它备份,因为它会丢失。
-
更新你的
.gitignore
文件 – 例如,添加一个你不想跟踪的文件夹.gitignore
。 -
git rm -r --cached .
– 删除所有跟踪的文件,包括想要的和不需要的。 只要您在本地保存,您的代码将是安全的。 -
git add .
– 所有文件将被重新添加,除了.gitignore
。
给@AkiraYamamoto的帽子给我们指出了正确的方向。
我认为,也许git不能完全忘记文件,因为它的概念( “快照,不差异”部分 )。
例如,使用CVS时,这个问题就不存在了。 CVS将信息存储为基于文件的更改列表。 CVS的信息是一组文件以及随着时间对每个文件所做的更改。
但是在Git中,每次提交或保存项目状态时,都会基本拍摄所有文件的样子,并存储对该快照的引用。 所以,如果您添加了一次文件,它将始终存在于该快照中。
这两篇文章对我有帮助:
git假设 – 不变vs skip-worktree和如何忽略跟踪文件中的变化与Git
基于它,我做了以下,如果文件已被跟踪:
git update-index --skip-worktree <file>
从这一刻起,这个文件中的所有本地更改都将被忽略,不会进入远程。 如果文件在远程更改,当git pull
时会发生冲突。 藏匿不起作用。 要解决该问题, 请将文件内容复制到安全的地方,然后执行以下步骤:
git update-index --no-skip-worktree <file> git stash git pull
文件内容将被远程内容replace。 将您的更改从安全位置粘贴到文件并再次执行:
git update-index --skip-worktree <file>
如果每个使用项目的人都会执行git update-index --skip-worktree <file>
,那么就会出现pull
问题。 当每个开发人员都有自己的项目configuration时,该解决scheme对于configuration文件是可以的。
每次在远程更改文件时都不太方便,但可以防止远程内容被覆盖。
移动或复制文件到一个安全的位置,所以你不会失去它。 然后git rm文件并提交。 如果您还原为其中一个较早的提交,或者尚未删除的另一个分支,该文件仍将显示。 但是,在将来的所有提交中,您将不会再看到该文件。 如果文件在git忽略,那么你可以把它移回到文件夹,git不会看到它。
从马特恐惧的答案是最有效的恕我直言。 以下是仅用于Windows中的PowerShell脚本,只能从其git仓库中删除与其排除列表相匹配的文件。
# 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 .
BFG专门用于从Git仓库中删除不需要的数据,如大文件或密码,所以它有一个简单的标志,可以删除任何大的历史(不在你当前提交的)文件:–strip-blobs-降幅高于”
$ java -jar bfg.jar --strip-blobs-bigger-than 100M
如果你想按名字指定文件,你也可以这样做:
$ java -jar bfg.jar --delete-files *.mp4
BFG比git filter-branch快10-1000倍,而且使用起来更容易 – 查看完整的使用说明和示例以获取更多详细信息。
资料来源: https : //confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html
在mac上:
$ git --version git version 2.6.4 $ uname -a Darwin MUSRV186016-382 14.5.0 Darwin Kernel Version 14.5.0: Sun Sep 25 22:07:15 PDT 2016; root:xnu-2782.50.9~1/RELEASE_X86_64 x86_64
1.从分支foo中git跟踪的文件列表中删除DS_Store文件:
$ for file in $(git ls-tree -r foo --name-only | grep -i DS_Store); do git rm --cached $file; done
2.承诺:
$ git commit -m "Removed .DS_Store files"
3.validation文件不再被跟踪
$ git ls-tree -r foo --name-only # There should not be anything coming back
4.按下以从远程删除它们:
$ git push