Let's say I have a configuration file config.cfg
which contains some extremely important stuff.
When you clone the repository, you have to get config.cfg
, or else nothing will work; therefore the config.cfg
file must be in the repository.
config.cfg
is also meant to be locally customizable by individual developers to suit their needs, but these customizations must remain local and never be committed. Therefore, developers must be prevented from accidentally committing config.cfg
as part of their normal workflow.
In the exceptional situation where someone does actually need to commit config.cfg
, they should have to invoke some magical incantation to indicate that they really mean to do so. (For example, if this situation was, hypothetically, solvable by something as simple as git-ignoring config.cfg
, then the magical incantation could, also hypothetically, consist of temporarily un-listing config.cfg
from .gitignore
in order to commit it, and re-listing it afterwards. But it isn't. This was just an example.)
When The Guru Developer modifies config.cfg
and commits it, (invoking the beforementioned magical incantation,) then all developers should get these changes next time they pull, and they should get merge conflicts, if necessary, against any local changes that they may have.
Developers should not be burdened with extra bureaucracy; in other words, they should be able to just clone the repository and run the software, they should not have to first follow lists of things that need to be done.
I am trying to achieve this scenario.
First I tried committing config.cfg
and then adding it to .gitignore
; it does not work, because it is a well known fact that git silently fails to ignore entries that happen to already be committed.
Then I tried git update-index --skip-worktree config.cfg
; it does achieve the part where .gitignore
failed, but it does not work either, because it does not prevent developers from accidentally committing config.cfg
as part of their normal workflow. For this to work, every developer would have to execute this command locally, which is an untenable proposition.
Someone suggested that I should have a config.cfg
with the extremely important stuff, which should remain largely untouched, and an optional git-ignored config.user.cfg
for developers to go wild with their customizations. Actually, I am already doing this: the config.cfg
that I was telling you about was a lie; in actuality, I was talking about my config.user.cfg
, I just called it config.cfg
to keep things simple. Still, nothing changes: config.user.cfg
must exist or else bad things will happen, but if it is git-ignored then developers will not receive it when cloning, so it will not initially exist. Also, config.user.cfg
needs to have some default boilerplate content for developers to modify; I do not want to tell developers that they have to create it from scratch. So, we are back to square one, how to have config.user.cfg
both versioned and locally ignored.
How can I achieve this scenario?
The closest other question and answer that I have managed to find is How to make GIT ignore tracked file locally? where someone has to have an executable in their repository, and wants to prevent developers from building it and committing it. According to the answers in that question, it cannot be done.