如何让 Git 忽略掉文件中的特定行内容?

时间:2021-09-09 12:20:38

近期在git遇到几个问题,让我重新认识到git的强大性,下面列出来记录一下

有一个数据库的配置文件,在用 git add 添加到 index file 时不能透露了相关配置。而如果用 .gitignore 去操作这需求,却会放弃add整个文件,如果这样做的话,commit后其他人就看不到这里面有个config配置文件了,这结果很明显不是我们想要的。怎么做呢?搜索了下要使用git下面的filter配置去过滤那些秘密。官方文档的描述如下:

filter.driver.clean

The command which is used to convert the content of a worktree file to a blob upon checkin. See gitattributes(5) for details.

filter.driver.smudge

The command which is used to convert the content of a blob object to a worktree file upon checkout. See gitattributes(5) for details.

SYNOPSIS

$GIT_DIR/info/attributes, .gitattributes

DESCRIPTION

A gitattributes file is a simple text file that gives attributes to pathnames.

Each line in gitattributes file is of form:

pattern    attr1 attr2 ...

文档详情内容请看 git config --help,这里不展开讨论

这是我当时的一个config.php文件:

<?php
return array(
'DB_TYPE' => 'MySql', // 数据库类型
'DB_HOST' => '10.66.111.111', // 服务器地址
'DB_NAME' => 'blog', // 数据库名
);

根据文档的提示,我们应该这么做:

echo config.php filter=rm_conf >> .gitattributes

git config filter.rm_conf.clean "sed 's/\'10\.66\.111\.111\'/\'\'/g;s/\'blog\'/\'\'/g'"

关于sed的命令的用法及参数说明,点这里

按照第二条命令运行,再用 git add 添加到 index file 时,发现错误提示

sed 's/\'10\.66\.111\.111\'/\'\'/g;s/\'blog\'/\'\'/g': -c: line 0: unexpected EOF while looking for matching `''
sed 's/\'10\.66\.111\.111\'/\'\'/g;s/\'blog\'/\'\'/g': -c: line 1: syntax error: unexpected end of file
error: external filter sed 's/\'10\.66\.111\.111\'/\'\'/g;s/\'blog\'/\'\'/g' failed 1
error: external filter sed 's/\'10\.66\.111\.111\'/\'\'/g;s/\'blog\'/\'\'/g' failed

唔...具体哪里错了呢,我们单独在命令行写 sed 's/\'10\.66\.111\.111\'/\'\'/g;s/\'blog\'/\'\'/g' config.php

命令行打印出了正确的结果

return array(
'DB_TYPE' => 'MySql', // 数据库类型
'DB_HOST' => '', // 服务器地址
'DB_NAME' => '', // 数据库名
);

一脸懵逼..再仔细查了下git的help文档,发现原来是分号惹的祸

The syntax is fairly flexible and permissive; whitespaces are mostly ignored. The # and ; characters begin comments to the end of line, blank lines are ignored.

然后我意识性地在分号前面加了个 \ 转义符,然而还是那个错误。机智的我立马搜 * ,不出所料这坑早已有人踩过了,立马找出了答案。以下是链接

于是,把commentChar设置为"#"

git config core.commentChar "#"
git config filter.rm_conf.clean "sed \"s/'10\.66\.111\.111'/''/g;s/'blog'/''/g\""

再run一次,达到了预期的效果!

but,感觉这样写起来不太美观啊,同一个文件需要隐藏配置项一多起来,就很难看懂这段command了。那我们就把这段脚本放在一个.sh里面,sed分开写,一行一个配置项,这样逻辑就清晰多了。假设这个脚本的名字叫hidden_conf.sh,将这文件放在.git目录里面,如下代码:

!#bin/bash

# filter服务器地址
sed -i 's/'10\.66\.111\.111'/''/g' config.php
# filter数据库名
sed -i "s/'blog'/''/g" config.php

然后再改下git中config的配置:

git config filter.rm_conf.clean '.git/hidden_conf.sh'