使文件受版本控制并在本地被忽略

问题描述 投票:0回答:1

假设我有一个配置文件

config.cfg
,其中包含一些极其重要的内容。

当你克隆存储库时,你必须得到

config.cfg
,否则什么都不起作用;因此
config.cfg
文件必须位于存储库中。

config.cfg
也意味着个人开发人员可以在本地进行自定义以满足他们的需求,但这些自定义必须保留在本地并且永远不会被提交。因此,必须防止开发人员在正常工作流程中意外提交
config.cfg

在某人确实需要做出承诺的特殊情况下

config.cfg
,他们应该必须调用一些神奇的咒语来表明他们确实打算这样做。 (例如,假设这种情况可以通过像 git-ignoring
config.cfg
这样简单的事情来解决,那么神奇的咒语也可以假设为暂时从
config.cfg
中取消列出
.gitignore
,以便提交它,然后重新列出它。但事实并非如此。这只是一个例子。)

当 Guru Developer 修改

config.cfg
并提交它时(调用前面提到的神奇咒语),那么所有开发人员都应该在下次拉取时获得这些更改,并且如果有必要,他们应该针对他们可能的任何本地更改获得合并冲突有。

开发商不应背负额外的官僚作风;换句话说,他们应该能够克隆存储库并运行软件,他们不必首先遵循需要完成的事情列表。

我正在努力实现这个场景。

首先我尝试提交

config.cfg
然后将其添加到
.gitignore
;它不起作用,因为众所周知的事实是 git 默默地无法忽略碰巧已经提交的条目。

然后我尝试了

git update-index --skip-worktree config.cfg
;它确实实现了
.gitignore
失败的部分,但它也不起作用,因为它不能防止开发人员在正常工作流程中意外提交
config.cfg
。为此,每个开发人员都必须在本地执行此命令,这是一个站不住脚的主张。

有人建议我应该有一个

config.cfg
包含极其重要的内容,这些内容应该基本上保持不变,以及一个可选的 git-ignored
config.user.cfg
供开发人员进行自定义。事实上,我已经在这样做了:我告诉你的
config.cfg
是一个谎言;实际上,我正在谈论我的
config.user.cfg
,我只是将其称为
config.cfg
以保持简单。尽管如此,没有任何变化:
config.user.cfg
必须存在,否则会发生不好的事情,但如果它被 git-ignored,那么开发人员在克隆时将不会收到它,因此它最初不会存在。另外,
config.user.cfg
需要有一些默认的样板内容供开发者修改;我不想告诉开发人员他们必须从头开始创建它。所以,我们回到第一个点,如何让
config.user.cfg
既受版本控制又在本地被忽略。

我怎样才能实现这个场景?

我设法找到的最接近的其他问题和答案是如何使 GIT 在本地忽略跟踪文件?有人必须在其存储库中拥有可执行文件,并且希望阻止开发人员构建并提交它。根据该问题的答案,这是不可能的。

git gitignore
1个回答
0
投票

以下是如何解决该问题的示例。

您有多种选择。

  1. 涂抹/清洁(下面的演示脚本)
  2. assume-unchanged
    - https://git-scm.com/docs/git-update-index#Documentation/git-update-index.txt---no-assume-unchanged
  3. git 钩子

我建议使用smudge clean,因为在my看来,这是最干净的选项。

  • 清洁/污迹过滤器使用起来非常简单。

  • 使用两个命令(clean 和 smudge)创建过滤器驱动程序,然后对 .gitattributes 文件中的每条记录应用过滤器。

  • 过滤器位于工作目录和特定

    .gitattributes
    模式的暂存区域之间(您也必须定义 - 在您的情况下,它可以是
    config.cfg
    )。

  • 使用

    git add
    将内容从工作目录添加到暂存区域时,与
    .gitattributes
    模式匹配的文件将通过干净过滤器。

  • 使用

    git pull
    将内容从存储库拉回到工作目录时,这些相同的文件将通过污迹过滤器。

  • 在随附的演示中,您可以看到 git “不关心”您本地的内容,并将内容设置为您想要的内容。

工作演示

  • 复制脚本并运行它,它可以工作。
#!/bin/bash

# SET your remote repo
REMOTE_REPO=<git....>

clear
# Set output the colors script
Color_Off='\033[0m'       # Text Reset

# Regular Colors
Black='\033[0;30m'        # Black
Red='\033[0;31m'          # Red
Green='\033[0;32m'        # Green
Yellow='\033[0;33m'       # Yellow
Blue='\033[0;34m'         # Blue
Purple='\033[0;35m'       # Purple
Cyan='\033[0;36m'         # Cyan
White='\033[0;37m'        # White

# Bold
BBlack='\033[1;30m'       # Black
BRed='\033[1;31m'         # Red
BGreen='\033[1;32m'       # Green
BYellow='\033[1;33m'      # Yellow
BBlue='\033[1;34m'        # Blue
BPurple='\033[1;35m'      # Purple
BCyan='\033[1;36m'        # Cyan
BWhite='\033[1;37m'       # White

### Define the desired filters.
### For the simplicity of the demo we use it inline
### In real life it can be any path to the actual script

### The ip which we wish to use
### In real life it can be passowrd, ip or any other value
DB_IP_LOCAL=127.0.0.1
DB_IP_PROD=10.10.10.10

echo -e ""
echo -e "Pre-defined values:"
echo -e "------------------------------------------------"
echo -e "${Yellow}DB_IP_PROD:\t${Green}${DB_IP_LOCAL}${Color_Off}"
echo -e "${Yellow}DB_IP_PROD:\t${Green}${DB_IP_PROD}${Color_Off}"
echo -e ""

echo -e "${Cyan}* Creating\t demo repository${Color_Off}"
### Create the demo repository
rm -rf      /tmp/demo_smudge
mkdir -p    /tmp/demo_smudge
cd          /tmp/demo_smudge

# Generate the .env file
echo -e "${Cyan}* Initializing\t .env file${Color_Off}"
cat << EOF >> .env
## Database
##  * Local:      <Any Value>
##  * Production: 10.10.10.10
database.ip=0.0.0.0

## Feature1
feature1.env=DEV
feature1.key=f1-key
feature1.name=feature1
EOF

echo -e ""
echo -e "Current .env file content"
echo -e "------------------------------------------------"
echo -e "${Green}"
cat .env
echo -e "${Color_Off}"
echo -e "------------------------------------------------"
echo -e ""

### Init the empty repository
echo -e "${Cyan}* Initializing demo repository${Color_Off}"

## Init git repo
git init --quiet
# Add the demo remote repository
git remote add origin ${REMOTE_REPO}

# Add all files
echo -e "${Cyan}* Adding content to demo repository${Color_Off}"
git add .

# Commit changes
echo -e "${Cyan}* Committing content to demo repository${Color_Off}"
git commit -m"Initial Commit without smudge-clean" --quiet

echo -e "${Cyan}* Pushing content to demo repository${Color_Off}"
echo -e "${Yellow}${REMOTE_REPO}{Color_Off}"

git push --set-upstream origin main -f --quiet

echo -e "${Red}>>> Press any key to continue${Color_Off}"

# Wait for user input to continue (max timeout 600 seconds)
read -t 600 -n 1

### MacOS users should use gsed instead of sed

# Clean is applied when we add file to stage
echo -e "${Cyan}* Define clean filter${Color_Off}"
git config --local filter.cleanLocalhost.clean  "gsed -e 's/database.ip=.*/database.ip=${DB_IP_PROD}/g'"

# Smudge is applied when we checkout file
echo -e "${Cyan}* Define smudge filter${Color_Off}"
git config --local filter.cleanLocalhost.smudge "gsed -e 's/database.ip=*/database.ip=${DB_IP_LOCAL}/g'"

###  Define the filters 
echo -e "${Cyan}* Adding filters (smudge-clean) to demo repository${Color_Off}"
echo '.env text eol=lf filter=cleanLocalhost' > .gitattributes

### Commit the file again after we set up the filter
echo -e "${Cyan}* Adding second commit${Color_Off}"
echo 'Second Commit' >> README.md

echo -e "${Cyan}* Adding the same file (.env)${Color_Off}"
git add .

echo -e "${Cyan}* View the diff (.env)${Color_Off}"
echo -e "------------------------------------------------"
git --no-pager diff --cached .env
echo -e "------------------------------------------------"

echo -e "${Cyan}* Commit changes${Color_Off}"

git commit -m"Second commit with smudge-clean" --quiet
echo -e "${Cyan}* Pushing second commit to git${Color_Off}"
git push --set-upstream origin main --quiet
© www.soinside.com 2019 - 2024. All rights reserved.