2

I know how to ignore specific lines completely in git using gitattributes (see How to tell git to ignore individual lines, i.e. gitignore for specific lines of code), but how would I go about ignore changes to a specific line?

I assume we can use a filter very similarly, but I don't know what my sed script should do to ignore the changes to the line.

For a practical example, I am writing up a C# library that needs a specific build output path depending on the project it's used in as a submodule. Thus, it has to be configured manually wherever it's being used, but that change must not be commited to the library itself.

Original Library.csproj:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    ...
    <OutputPath>bin\Debug\</OutputPath>
    ...
</PropertyGroup>

Submodule Library.csproj:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    ...
    <OutputPath>..\Target\</OutputPath>
    ...
</PropertyGroup>

How do I get git to ignore the change to this line?

DCardinal
  • 195
  • 1
  • 9
  • 1
    what people do is to commit a template file, for example `Library.csproj.template` and add the `Library.csproj` file to `.gitignore` and that way everyone create their own `Library.csproj` files which is ignore by git – Luis Silva Apr 08 '20 at 00:14

3 Answers3

3

With git, there is no way to ignore a single line of code. Once a file is tracked, the whole file is indexed.

Instead of changing the output of the build location, the surrounding code that calls your project should copy the outputs of the build to the proper location. This way you don't mess with the integrity of the submodule.

If you need to dynamically change the output location of the build, you could use an environment variable that is set prior to the build. This way, you could have that location change by changing the value of the environment variable.

Ben W
  • 930
  • 6
  • 16
2

For this very specific case, you could set up your clean filter to replace the line with a standard default line. That is, you'd read the incoming XML data stream, find the one item, replace it, and generate the new stream (either generated as all-new XML, or on the fly as you go).

This whole idea is a bad one though. It means that the user's private configuration is stored in their existing work-tree, in a file that Git will overwrite. In other words, there are situations under which Git will be told destroy the user's configuration irretrievably, and Git will obey, and the configuration will be destroyed. To put it back, you will need not only a clean filter but also a smudge filter. The smudge filter must obtain the correct configuration data from somewhere—this cannot be the file that is being destroyed and re-created right now—and put it into the data-stream.

That configuration must therefore also be stored in some other file that Git won't overwrite, either entirely outside the work-tree, or never committed. In this case, you might as well just read the value from the other file. So just use that file. See Ben W's answer for this alternative.

For another, consider having the main XML data read:

<OutputPath type="indirect">/etc/oursoftware.d/config.output</OutputPath>

for instance, to indicate that the output "path" here is the name of another file—in this case /etc/oursofware.d/config.output—that the user will configure to contain the output path. Or, if environment variables are available:

<OutputPath type="envvar">$OURSOFTWARE_OUTPUT_PATH</OutputPath>

indicating that the software is to be run as:

OURSOFTWARE_OUTPUT_PATH=/path/to/file.ext program

for instance. Note that you must change your C# program so that it understands these new XML controls.

torek
  • 448,244
  • 59
  • 642
  • 775
  • Solution with indirect seems the best in my scenario, but I can't get it to work. As soon as I add 'type="indirect" ' I get: "The attribute "type" in element is unrecognized. – DCardinal Apr 08 '20 at 05:02
  • I'm assuming *you* wrote the XML reader, and therefore you can change the code to handle an attribute here. You said *I am writing up a C# library* after all. – torek Apr 08 '20 at 05:08
  • If that's what you're suggesting, it sounds a little over the top to me to alter Visual Studio's xml reader for .csporoj files. – DCardinal Apr 08 '20 at 05:19
  • You didn't say you were using someone else's library. You said you were writing *your own* library. – torek Apr 08 '20 at 05:20
  • It's my own library but isn't in a .xml that I'm reading with code, it's in .csproj and is related to the project build. I don't have control over the reader handling that without some serious tinkering because it's part of Visual Studio itself, not my code or anyone else's (other than Microsoft) – DCardinal Apr 08 '20 at 05:23
  • Ah, well, in that case, you'll need some other approach. The general point is: where you have control (your code), make it work in a way that achieves your task. – torek Apr 08 '20 at 12:01
  • I understand. Unfortunately none of this has to do with my code. It either has to do with build configurations or git configuration. I am close to a solution though combining both of your answers. – DCardinal Apr 08 '20 at 12:25
1

After a few hours on this, here is where I have arrived, combining the two answers I have at this time and some supplementary research for my solution:

Answer to the question itself: Not really possible to ignore changes to a line

You can't ignore changes to a single line. The page I referenced in my question only discusses how to DELETE a single line from a commit, not IGNORE CHANGES. The best alternative would be to hook something that would REPLACE the line with something else when you push, and having to put back what was initially removed when you pull, which is possible but very tedious. (See "clean" and "smudge" in the Git Attributes Documentation)


As for the solution I opted to use for my build issues, I decided to write a small batch script, run as Post Build Event, that copies the files built to a target directory, whose path is defined in a file ignored from git to allow modularity.


Another nice solution, proposed by Luis Silva, is to use a .csproj.template file and add .csproj to the gitignore. The template can be copied and modified to fit the needs of the implementation.

DCardinal
  • 195
  • 1
  • 9