Callum M
Callum M

Reputation: 2080

Is there a way to have git add --patch skip all single line changes?

My team checks in an exported JSON file from a tool that we use (Postman) so that we can share the configuration easily. In a recent change to that tool, all the IDs (which are just GUIDs) get changed every time we export. This means that our diff has hundreds of one line meaningless changes (GUIDs changing), and then the actual meaningful change/addition that we've made.

If we check this in as-is then rebasing is really tricky, because the IDs seem to be completely random and so we get loads of meaningless merge conflicts. It's also annoying to review since the change we want reviewing is buried under hundreds of other meaningless changes. But using git add --patch is basically impossible because you have to skip hundreds of patches and then select the one you want, which might be near the bottom of the file.

I'm wondering if there's any clever scripting trick I can use to make it automatically discard all the one-liners, and only ask me about patches that are longer than one line. The actual patches we want are almost always longer than one line, so this would almost always work and make it much easier to work with.

Upvotes: 0

Views: 380

Answers (3)

LeGEC
LeGEC

Reputation: 51988

Another way is :

  • write a script, that, from a file name, is able to generate the correct patch
  • use git apply --cached to apply this patch on the staging area, without modifying the worktree version

If you wrap the two actions in a script, accessible from your PATH, called git-something (e.g: git-addpostman), you can then add your files by calling git addpostman $file from within your repo.

Upvotes: 1

LeGEC
LeGEC

Reputation: 51988

I assume the list of files is clearly established : *.json files, present in some clearly identifiable directories, perhaps with a specific name structure ... (meaning: you can easily target these files from .gitattributes)

If such is the case : your use case is a good fit for a filter (with a clean / smudge pair of scripts) that would replace the ever moving lines with fixed values when adding these files to git.


Here is a link to the docs: git attributes

relevant graphical description :

Figure 144. The “smudge” filter is run on checkout. Figure 144. The “smudge” filter is run on checkout. Figure 145. The “clean” filter is run when files are staged. Figure 145. The “clean” filter is run when files are staged.

The target "filter" scripts to run should be defined in git's configuration,
the files to pass through this filter should be defined in a .gitattributes file.

You would need to set the following configuration once on each machine :

  • deploy a script, let's call it normalize-postman-ids, that would be used when git adding demo files,

  • possibly a second script, let's call it insert-valid-postman-ids, that would be used when git checkouting a commit,

  • add a section in the .git/config file, that would describe a so called filer :

     [filter "postman-ids"]
         clean = path/to/normalize-postman-ids
    
         # if the values stored in git can be used straight away:
         smudge = cat
         # if you need some action on checkout:
         smudge = path/to/insert-valid-postman-ids
    

You would need to update and commit the .gitattributes file of your repo :

  • in the .gitattributes file, target the files which should be filtered :

    # .gitattributes :
    postman*.json filter=postman-ids
    

Upvotes: 1

Callum M
Callum M

Reputation: 2080

I've found a reasonable workaround, using the / search feature of the git add --patch UI. Search for something in the hunk that's intended to have changed, stage that, then use d to discard everything else. This is probably a better approach than my original idea, because it would work even with a one-liner actual change.

Upvotes: 2

Related Questions