Git - Ignoring a specific modification to a config file

后端 未结 4 987
深忆病人
深忆病人 2020-12-03 20:02

I have a config file in our project that holds a connection string to the database, as well as several application settings, e.g:

...


        
相关标签:
4条回答
  • 2020-12-03 20:31

    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.

    • You can have properties file with key-value pairs containing all local system specific values. This file should be updated manually. Then it is used on the application and merged into the application configuration. Details depend on the tools you are using. But I do believe this should not introduce any big difficulties but most likely would require application changes.
    • You can have 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).

    0 讨论(0)
  • 2020-12-03 20:35

    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.

    0 讨论(0)
  • 2020-12-03 20:47

    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
    
    0 讨论(0)
  • 2020-12-03 20:58

    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.

    0 讨论(0)
提交回复
热议问题