Search code examples
gitgitattributes

Is there a possibility in git to ignore only specific changes within a file, e.g. numbers?


i have a config file "Gui.cfg" that is used for a GUI, like this:

GROUP camera
 gui.drivers.CameraGui 1 (,,,,)
 gui.drivers.CameraGui 2 (,,,,)

when I open the GUI and the elements Camera 1 or Camera 2 the "Gui.cfg" changes and adds the window size, like

GROUP camera
 gui.drivers.CameraGui 1 (25,0,430,477,0)
 gui.drivers.CameraGui 2 (393,6,426,473,0)

Is there any way to tell git, that these changes in the brackets are ignored, but all other changes are not?

I already read something about gitattributes and filters, but didn't find out how to get it working for my problem.


Solution

  • Filters enable you to do exactly what you want, so you were on the right track.

    From the documentation:

    It turns out that you can write your own filters for doing substitutions in files on commit/checkout. These are called “clean” and “smudge” filters.

    What you want is a clean filter for the Gui.cfg file that will replace any lines matching this pattern:

    gui.drivers.CameraGui <anynumber> (<anycharacter>)
    

    with

    gui.drivers.CameraGui <matchednumber> (,,,,)
    

    before the file is committed.

    Since a clean filter runs just before a matching file is staged, this will have the effect of "undoing" the window size modification, while still letting through any other changes in the file.

    Let's start by telling Git that we want to run the Gui.cfg file through a filter called undoCameraWindowSize by adding this line to .gitattributes:

    Gui.cfg filter=undoCameraWindowSize
    

    Then, we implement the undoCameraWindowSize filter and tell Git that we want to run it before the file is staged by defining it as a clean filter:

    git config --global filter.undoCameraWindowSize.clean 'sed -E "s/gui\.drivers\.CameraGui\s([0-9]+)\s\(.*\)/gui.drivers.CameraGui \1 (,,,,)/"'
    

    Here, we're using sed to run a regular expression and replace the matching text with another string.

    The command itself is:

    sed -E "s/gui\.drivers\.CameraGui\s([0-9]+)\s\(.*\)/gui.drivers.CameraGui \1 (,,,,)/"
    

    Notice how we're using a capturing group ([0-9]+) to match the camera number, which we then reference in the replacement string with \1.