随之而来的问题是:为什么我增加了 .gitignore 里的规则却没有效果?
这是因为我们误解了 .gitignore 文件的用途,该文件只能作用于 Untracked Files,也就是那些从来没有被 Git 记录过的文件(自添加以后,从未 add 及 commit 过的文件)。
1. git rm --cached logs/xx.log // if file is traced
2. 然后更新 .gitignore 忽略掉目标文件,
3. 最后 git commit -m "We really don't want Git to track this anymore!"
之所以你的规则不生效,是因为那些 .log 文件曾经被 Git 记录过,因此 .gitignore 对它们完全无效。这也正是开头那段简短答案所做的事情:
1. 从 Git 的数据库中删除对于该文件的追踪;
2. 把对应的规则写入 .gitignore,让忽略真正生效;
3. 提交+推送。
最后有一点需要注意的,git rm --cached
删除的是追踪状态,而不是物理文件;如果你真的是彻底不想要了,你也可以直接rm+忽略+提交
。
About Another Command
git update-index --assume-unchanged logs/*.log
的真正用法是这样的:
你正在修改一个巨大的文件,你先对其 git update-index --assume-unchanged
,这样 Git 暂时不会理睬你对文件做的修改;
当你的工作告一段落决定可以提交的时候,重置改标识:git update-index --no-assume-unchanged
,于是 Git 只需要做一次更新,这是完全可以接受的了;
提交+推送
。
另外,根据文档的进一步描述:
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).
这段描述告诉我们两个事实:
虽然可以用其来达成楼主想要的结果,但这是不讲究的做法(coarse);
同样的事情更应该用 .gitignore 文件来实现(针对未追踪的文件)。
git update-index --assume-unchanged logs/*.log
虽然能达到(暂时的)目的,但并非最正确的做法,这样做是误解了 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。