We use the auto-format tool uncrustify on our git repositories, they run in a git clean filter.
The problem is that users sometimes turn off their filters (don't ask). This leads to some bad formatting in some commits. Checking out these commits, while having the clean filter active, shows the bad formatting as diffs.
The filter is applied on git diff and others, and now users can't checkout another commit (warning about losing changes), so they turn off their filter, and create more problems since it's easy to forget to turn it on again.
One solution is to apply the auto-format on the server repository, I'm looking into it.
I like seeing the auto-formatting on git diff, so I see what I'm going to commit.
The question is: can we prevent running the clean filter on given operations, such as checkout, stash pop, and such?
Any better suggestion?
First, a note:
git checkoutshould not run the clean filter at all, because it only does an index → work-tree copy.1 This runs the smudge filter instead. Only index ← work-tree copy operations use the clean filter.Since
git stash save/git stash pushdoes an index ← work-tree operation, it will use the clean filter.Stash's
applyandpopinvokegit merge-recursive, which is more complicated. While some merging happens in the index, this sometimes needs to do smudging and/or cleaning,2 so you will see some cases of clean filter invocation here too.As ElpieKay suggested in the comment, a quick and dirty, but easy, way to disable a filter is to temporarily override its driver's configuration on the command line, with the front-end's
-coption:git -c filter.name.type=noopfor each applicablename(driver name in.gitattributes) andtype(cleanorsmudge).1This is true whether
git checkoutis doing a branch-switch (git switchoperation in Git 2.23 or later) or a file-restore (git restoreoperation in Git 2.23 or later). In either case, checkout updates index copies of some file(s) if/as appropriate, then updates the work-tree copy from each updated or selected index copy.That is, when using
git checkout -- paths, the givenpathsget updated in the work-tree, from the copies already present in the index: this requires smudging. When usinggit checkout tree-ish -- paths, the givenpathsget copied from the giventree-ishinto the index and then copied to the work-tree: this also requires smudging.Or, when using
git checkoutorcommitgit checkout branch, the index entries that are different between the previousHEADand the newly selected one are updated in the index, then copied to the work-tree, which requires smudging.2
git merge -X renormalizealways runs both, doing a smudge first and then a clean, before merging, for every file in every commit, using the.gitattributesfrom the work-tree. Settingmerge.renormalizein your configuration has the same effect, unless you override this withgit merge -X no-renormalize. Whilegit merge-recursiveis lower level thangit merge, I expect it does pretty similar things for the two commits that aren't represented by existing work-tree contents.