Git忽略本地的文件修改,保留其在远程仓库的状态

项目中的一些配置文件,需要在本地根据实际情况配置和修改,但同时这些配置仅在本地使用,并不想提交到远程仓库,这个时候仅使用.gitignore就办不到了...

如引言中的使用场景,在项目中有一些配置文件在远程仓库存在,但是本地的修改并不具有普适性,因此是不需要提交到远程仓库的,天真的我一开始将项目拉下后,直接在.gitingnore中添加了相关文件,但是在修改后发现,根本不会生效

失效的.gitignore

查了下.gitignore不生效的问题,发现如下解释:

The files/folder in your version control will not just delete themselves just because you added them to the .gitignore. They are already in the repository and you have to remove them.

即文件已经被track后,再添加到.gitignore是无效的,因为git不会自动的帮你删除文件,这一步需要手动去做,即:

git rm -rf --cached .
git add .

这个操作是删除仓库中的所有文件,然后再将他们添加回来,注意添加进仓库的时候,track的规则就会根据最新的.gitignore进行。

好家伙,这肯定不行啊,因为这个操作是直接把配置文件给干掉了,即远程仓库也不再会有这个文件,这显然不是我想要的效果。因此,开始寻找新的方案

探寻方案

我们的核心诉求并不是'ingnore'文件,删除以及不上传这些文件,而是Only keep it in the remote repo

但是在我的知识体系中,还没有一个很好的解决方式,遂google探索之,终于找到了非常符合场景需求的一个git操作:

  • 忽略跟踪
git update-index --assume-unchanged <file>
  • 查看被忽略的跟踪文件
git ls-files -v | grep '^h '
  • 恢复忽略文件,重新被版本控制
git update-index --no-assume-unchanged <file>
  • git update-index只能忽略单个文件,想要忽略整个文件夹下的文件,可以使用以下命令:
cd dir
git update-index --assume-unchanged $(git ls-files | tr '\n' ' ')

方案优化

以上指令的确可以满足一开始的诉求,但是正开开心心搞完,切花分支时,一个checkout竟然失败了,提示

 error: Your local changes to the following files would be overwritten by merge ...

但是查看git tree并没有任何跟踪文件是没有保存和提交的状态,也就是说之前被设置忽略的文件,犹如掩耳盗铃般,只是不被提交,但是在mergecheckout的时候还是会被提示覆盖风险而导致git操作失败。

所以最终选择使用了--skip-worktree指令, 与之前的方案非常类似:

# 原指令
git update-index --no-assume-unchanged -- <file>

# 优化指令
git update-index --skip-worktree -- <file>

至于和原指令的差别,可以查看这篇文章Difference Between 'assume-unchanged' and 'skip-worktree'

最终方案

  • 忽略文件
git update-index --skip-worktree --  <file>
  • 查看忽略的文件
git ls-files -v | grep -i ^S
  • 取消标志,恢复版本控制
git update-index --no-skip-worktree -- <file>
  • 批量忽略文件
cd dir
git update-index --skip-worktree $(git ls-files | tr '\n' ' ')

参考

  1. git update-index --assume-unchanged on directory

  2. 忽略不想提交的文件

  3. using gitignore to ignore (but not delete) files

  4. Git: untrack a file in local repo only and keep it in the remote repo

  5. git pull error for git update-index --assume-unchanged files

  6. git忽略本地文件

  7. Git命令git update-index --assume-unchanged,忽略不想提交的文件(忽略跟踪)