I have 2 different branches, master and test. Those branches are exact replicas except for the database string which is different for master and test. Everytime I merge test to master, the database string in the master gets replaced by the test database string.
I have heard about using branch specific variables, so I don't need to worry about the database string getting changes on merge as .env variables will take care of it.
Please let me know how do I do that.
as .env variables will take care of it.
You could generate the right .env file.
And rename the current .env into .env.master and .env.test
In each branch, you would then generate .env, with the right content in it, from one of those files, depending on the current execution environment.
The generation script will determine the name of the checked out branch with:
branch=$(git rev-parse --symbolic --abbrev-ref HEAD)
Finally, you would register (in a .gitattributes declaration) a content filter driver.
(image from "Customizing Git — Git Attributes", from "Pro Git book")
The smudge script, associated to the .env.branch file, would generate (automatically, on git checkout or git switch) the actual .env file by looking at values in the right .env.branch value file.
The generated actual .env file remains ignored (by the .gitignore).
See a complete example at "git smudge/clean filter between branches".
In your case, your project would look like:
repo/
├── .env.master # Contains production DB configuration
├── .env.test # Contains test DB configuration
├── .env.default # (Optional) Contains default settings for other branches
├── .env # Generated on checkout, ignored via .gitignore
├── .gitattributes # Contains: .env filter=envfilter
├── scripts/
│ └── smudge_env.sh
└── README.md # Documentation for the setup
Your smudge script smudge_env.sh would then be:
#!/bin/sh
# scripts/smudge_env.sh
branch=$(git rev-parse --abbrev-ref HEAD)
case "$branch" in
test)
cat .env.test
;;
master)
cat .env.master
;;
*)
echo "Unknown branch: $branch. Using .env.default." >&2
cat .env.default
;;
esac
Then:
chmod +x scripts/smudge_env.sh
git config --local filter.envfilter.clean cat
git config --local filter.envfilter.smudge './scripts/smudge_env.sh'
echo ".env filter=envfilter" >> .gitattributes
git add .gitattributes
git commit -m "Add .env gitattributes declaration for envfilter"
So, addressing mikibok's comment:
Am I supposed to cp the contents of the branch file to the filter?
Not exactly.
Instead of performing an explicit file copy, the smudge script should simply output (e.g., using cat) the contents of the appropriate file (like .env.master or .env.test). Git uses the output of the smudge filter to create or update the .env file.
That is effectively the same as copying the file's content... but without having to run a separate cp command.
Should I have the same smudge script in both branches?
Yes. It is best practice to have one smudge script (stored under version control) that lives in a common location (for example, in a scripts/ directory).
That way, regardless of the branch you are on, the same script will run, detect the current branch (using a command like git rev-parse --abbrev-ref HEAD), and output the appropriate configuration content.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With