I have a config file in our project that holds a connection string to the database, as well as several application settings, e.g:
...
Let me put some suggestions on how this might be done.
When adding changes to the index you can use git add -p app.config
and manually skip some of the changes in your file. If you don't add changes to the index before doing commit these changes would not be committed. This is a kind of 'local-only' solution. But it might be really boring to always see the file modified in git status
report.
All other suggestions might require changes in the architecture and there for can not be considered as 'local-only' solution. Anyway I think they might worth reviewing.
The main idea for all changes is to have local file added to .gitignore
which contains local system specific settings. We have used several slightly different solutions here.
app-original.config
file in git repository and app.config
file in git
ignore list. The app.config
file should be created manually from app-original.config
file.What is really boring with all these solutions is that some manual work is required when the structure of config file is altered. For example on every config file update you should check if new properties have been introduced and update your local properties file. As well when you update your local file because of some application changes you need to remember to commit related changes in configuration files (remember your local files are in .gitignore
).
I do not think git
has such facility. And the proposed way of managing the app.config
file, treating part of the file version controlled and other part not, does not smell right to me.
In your situation I would seek a way to arrange the app.config
to be generated from two files. The ConnectionString
setting would be placed in user created (build) configuration file, and the other parts would be put in some sort of template file (conceptually speaking). The user created configuration file could be added to the .gitignore
file. The template file would be controlled by git
. We would need to have a method to build the app.config
file by applying the settings in your build configuration file to the template file.
We are lacking background information about the development setting to tell how all this could be implemented. If you are using make
or ant
or similar thing, then this would be a simple dependency and rule to create the app.config
to make sure the file is created if it does not exist or if the build config file or template file change. Also the natural choice for how to generate the app.config
file from the template file depends on your build environment and the nature of the app.config
file. For longer than couple of lines of text, even a shell script can be used for simple expansion of a given template file easily (couple of lines of lines to expand ${VARIABLE} constructs, but gets more complicated if the file needs to include dollar signs or back ticks or backslashes etc). More complicated expansion we could use eruby
, or eperl
or similar thing (even perhaps PHP
). The app.config
file could also be generated manually whenever you need to change the setting. But all this is somewhat useless speculation without further context.
filters are made for stuff like this. In your repo,
cat >.git/info/saved-connection <<EOD
<setting name="ConnectionString"><value>Server=prodServer;Database=myDataBase;</value></setting>
EOD
cat >.git/info/my-connection <<EOD
<setting name="ConnectionString"><value>Server=myprivateserver;Database=myDataBase;</value></setting>
EOD
git config filter.use-my-connection.smudge 'sed -f ".git/info/use-my-connection.smudge"'
git config filter.use-my-connection.clean 'sed -f ".git/info/use-my-connection.clean"'
cat >.git/info/use-my-connection.smudge <<EOD
/^<setting name="ConnectionString">/ {
w .git/info/saved-connection
r .git/info/my-connection
d
}
EOD
cat >.git/info/use-my-connection.clean <<EOD
/^<setting name="ConnectionString">/ {
w .git/info/my-connection
r .git/info/saved-connection
d
}
EOD
echo >> .git/info/attributes path/to/app.config filter=use-my-connection
I think I found a good solution to this issue.
As I said, in my project there is a config file that (wrongly) stores the connection string inside that config file.
I'd like to be able to work with a modified version of the config but without having the file constantly in the "modified" files list and without completely ignoring all its changes.
Here is what I do
After I clone from our servers my log graph looks like so:
A---B---C master
All my development will be done in another branch, "development". So I branch it. Then I change the config file and change the connection string and commit.
A---B---C master, origin/master
\
X development
Next I checkout master and merge the changes back with "--nocommit" flag. Then in the merge commit, I revert the config changes and commit. In effect, I've created an empty commit that just serves as a notice to Git that these changes were merged and there is no need to merge them again.
A---B---C---D master, origin/master
\ /
X development
Now as I continue developing new features on the X, I can safely merge the changes back to master - Git will only try to merge back the new changes since the last merge.
A---B---C---D---E---F master, origin/master
\ / /
X---Y---Z development
So in the example above, only the changes in "Y" and "Z" will be me merged back.
I've tried it and it seems to be working fine. It does mean, however, that whenever I switch to the master branch, I'm going to have the config with incorrect connection string, but since most of my development is done on "development" branch, it doesn't seem like a big issue to me.
If there is any issue with my solution, please let me know in the comments.
UPDATE
An issue with this is that if the config file is changed, in any way, on the "master", and then you merge "master" changes to the "development" branch, then the config file would get overwritten without warning.