When the "assume unchanged" bit is on, Git stops checking the working tree files for possible modifications, so you need to manually unset the bit to tell Git when you change the working tree file. This is sometimes helpful when working with a big project on a filesystem that has very slow lstat(2) system call (e.g. cifs).
This option can be also used as a coarse file-level mechanism to ignore uncommitted changes in tracked files (akin to what .gitignore does for untracked files).
tl;dr: 正确的做法应该是:
git rm --cached logs/xx.log
,然后更新.gitignore
忽略掉目标文件,最后git commit -m "We really don't want Git to track this anymore!"
具体的原因如下:
被采纳的答案虽然能达到(暂时的)目的,但并非最正确的做法,这样做是误解了
git update-index
的含义,而且这样做带来的最直接(不良)后果是这样的:所有的团队成员都必须对目标文件执行:
git update-index --assume-unchanged <PATH>
。这是因为即使你让 Git 假装看不见目标文件的改变,但文件本身还是在 Git 的历史记录里的,所以团队的每个人在 fetch 的时候都会拉到目标文件的变更。(但实际上目标文件是根本不想被 Git 记录的,而不是假装看不见它发生了改变)一旦有人改变目标文件之后没有
git update-index --assume-unchanged <PATH>
就直接 push 了,那么接下来所有拉取了最新代码的成员必须重新执行 update-index,否则 Git 又会开始记录目标文件的变化。这一点实际上很常见的,比如说某成员换了机器或者硬盘,重新 clone 了一份代码库,由于目标文件还在 Git 的历史记录里,所以他/她很可能会忘记 update-index。为什么会这样?答案就在 Git 的 man pages 里:
首先,git update-index 的定义是:
这句话暗含的意思是:update-index 针对的是 Git 数据库里被记录的文件,而不是那些需要忽略的文件。
接着看关于 --assume-unchanged 的几句相关的描述:
大致意思是:
我们知道 Git 不仅仅是用来做代码版本管理的,很多其他领域的项目也会使用 Git。比如说我公司曾经一个客户的项目涉及到精密零件图纸文档的版本管理,他们也用 Git。有一种使用场景是对一些体积庞大的文件进行修改,但是每一次保存 Git 都要计算文件的变化并更新工作区,这在硬盘慢的时候延迟卡顿非常明显。
git update-index --assume-unchanged
的真正用法是这样的:git update-index --assume-unchanged
,这样 Git 暂时不会理睬你对文件做的修改;git update-index --no-assume-unchanged
,于是 Git 只需要做一次更新,这是完全可以接受的了;另外,根据文档的进一步描述:
这段描述告诉我们两个事实:
.gitignore
文件来实现(针对未追踪的文件)。随之而来的问题是:为什么我增加了 .gitignore 里的规则却没有效果?
这是因为我们误解了 .gitignore 文件的用途,该文件只能作用于 Untracked Files,也就是那些从来没有被 Git 记录过的文件(自添加以后,从未 add 及 commit 过的文件)。
之所以你的规则不生效,是因为那些
.log
文件曾经被 Git 记录过,因此.log
文件曾经被 Git 记录过,因此.gitignore
对它们完全无效。这也正是开头那段简短答案所做的事情:只有这样做,所有的团队成员才会保持一致而不会有后遗症,也只有这样做,其他的团队成员根本不需要做额外的工作来维持对一个文件的改变忽略。
最后有一点需要注意的,
git rm --cached
删除的是追踪状态,而不是物理文件;如果你真的是彻底不想要了,你也可以直接rm
+忽略+提交。已经维护起来的文件,即使加上了gitignore,也无济于事。
用下面这个命令:
git update-index --assume-unchanged logs/*.log
这样每次提交就不会出现logs下面的文件了
自己来一段详细的答案
.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
正确的做法是在每个clone下来的仓库中手动设置不要检查特定文件的更改情况。
另外 git 还提供了另一种 exclude 的方式来做同样的事情,不同的是 .gitignore 这个文件本身会提交到版本库中去。用来保存的是公共的需要排除的文件。而 .git/info/exclude 这里设置的则是你自己本地需要排除的文件。 他不会影响到其他人。也不会提交到版本库中去。
.gitignore 还有个有意思的小功能, 一个空的 .gitignore 文件 可以当作是一个 placeholder 。当你需要为项目创建一个空的 log 目录时, 这就变的很有用。 你可以创建一个 log 目录 在里面放置一个空的 .gitignore 文件。这样当你 clone 这个 repo 的时候 git 会自动的创建好一个空的 log 目录了。
把log文件删了,加ingore, 再commit
我发现最高票(n͛i͛g͛h͛t͛i͛r͛e͛)的答案压根没有理解题主的问题
反而是@FatGhosta的答案才是正确的
如果按照n͛i͛g͛h͛t͛i͛r͛e͛的方法进行操作 只是达到
“将不需要记录的文件从git中删除的同时在本地保留该文件 并在以后的提交中忽略”
而不是达到
“提交时忽略已在git中存在的文件”
其实场景应该是这样的 有一个配置文件 比如是数据库的链接信息
每个人的链接信息肯定不是一样的 但是又要提供一个标准的模板 用来告知如何填写链接信息
那么就存在git上需要记录一个标准配置文件 然后每个人根据自己的具体情况 配置一份链接信息自用 但是不会将该配置文件提交到库里的情况
因此FatGhosta的答案才是该题目下正确的回答