I am versioning Microsoft Access VBA code, which is in general case insensitive. However changes the case of variable names happen every now in then (by the Access compiler or by the developer). This often leads to huge change set in my git workspace.
How can I revert or ignore changes, that only concern upper- or lowercase of file contents?
An example:
git init
echo "public sub example()\nend sub" > mdlExample.ACM
# ^-- lower e
git add --all
git commit --all --message "Initial Commit"
echo "public sub Example()\nend sub" > mdlExample.ACM
# ^-- upper E
I would love something like:
git restore --only-case-changes # not working
And then:
git status
> On branch master
> nothing to commit, working tree clean
If you wanted to ignore all files that end with a specific file extension, you would need to use the * wildcard selector followed by the file extension you want to ignore. This pattern will match any file ending with the .md extension located anywhere in the project. Earlier, you saw how to ignore all files ending with a specific suffix.
If you want to ignore all files with a specific name, you need to write the literal name of the file. In this case, you don't need to provide the full path to a specific file. This pattern will ignore all files with that particular name that are located anywhere in the project.
Git Documentationsays: core.ignoreCaseInternal variable which enables various workarounds to enable Git to work better on filesystems that are not case sensitive, like APFS, HFS+, FAT, NTFS, etc.
A .gitignore file is a plain text file that contains a list of all the specified files and folders from the project that Git should ignore and not track. Inside .gitignore, you can tell Git to ignore only a single file or a single folder by mentioning the name or pattern of that specific file or folder.
Consider changing example="example"
to Example="Example"
. How do you propose Git could decide which case change to ignore here? Now consider code snippets in comments, or stored as strings for code generators. I get wanting Git to make an annoying chore go away, but I think if you try to imagine telling Git exactly what you want you'll understand the context of your question a little better.
How can I revert or ignore changes, that only concern upper- or lowercase of file contents
When you want to temporarily ignore changes, when you want to do a diff or a blame without seeing those changes, you can use a "textconv" filter that normalizes the text you diff. I use those to do things like strip embedded timestamps out of generated html when diffing, quickest to hand atm is
[diff "doc-html"]
textconv = "sed 's,<span class=\"version\">Factorio [0-9.]*</span>,,;s,<[^/>][^>]*>,\\n&,g'"
wordRegex = "<[^>]*\\>|[^< \\t\\n]*"
in .git/config
, and
doc-html/*.html diff=doc-html
*.cfg -diff
in .git/info/attributes
.
so my what-changed diffs don't show me things I don't care about.
If you want to see the results of a diff ignoring case, try
[diff "nocase"]
textconv="tr A-Z a-z"
and drop * diff=nocase
(or maybe*.vba diff=nocase
) into .git/info/attributes
. When you're done, take it out.
but for merging, my leadoff example should convince you that Git automatically and silently making case changes in repo content, even just in the text that looks like identifiers, is a Bad Idea. When there's a conflict, not just a one-sided change but two different changes, it's still going to take some human judgement to decide what the result should be. Fortunately, with any decent merge tool, resolving simple conflicts is down around subsecond range each.
You don't have to git restore
anything: You could setup a clean content filter driver as illustrated here, which will automatically convert those cases on git diff
/git commit
.
That means:
Image from "Keyword Expansion" section of the "ProGit book"
This is done through:
.gitattributes
filter declaration, which means you can associate it only to certain files (through, for instance, their extension)
*.ACM filter=ignoreCase
git config filter.<driver>.clean
to declare the actual script (which should be in your PATH
)
git config filter.ignoreCase.clean ignoreCase.sh
# that give a .git/config file with:
[filter "ignoreCase"]
clean = ignoreCase.sh
The trick is:
Can you write a script which takes the content of an ACM file as input and produces the same ACM file as output, but with its strings converted?
You can have the filename in those scripts so you can do a diff and detect if said difference has to be adjusted, but you still need to write the right command to replace only "xxx
" strings when their case changes in ACM files.
Note: jthill suggests in the comments to set the merge.renormalize
config settings to tell Git that canonical representation of files in the repository has changed over time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With