Addendum - git version 2.34.1.windows.1 & others(?)
Regrettably, git config core.protectNTFS false
turned out not to be enough; the contents of the colon-carrying filenames are lost (filesize = 0).
Solution
TL;DR
git diff ec28c8ddd5f8c83d11604bcae69afb46d79b1029 > p.patch
patch -R -f -i p.patch
git add *
git commit
Elaboration
Turns out git config core.protectNTFS false
does work, insofar as to not produce fatal errors on git checkout
anymore.
However, git now will produce filenames clipped to the colon and with zero content.
E.g. Writing-Bops:-The-Bebop-Schema-Language.md
(~9KB) --> Writing-Bops
(0 KB)
To fix this, we need to get a copy of the original offending file(s)' content another way, so we can restore it.
Conditions / Assumptions
- This assumes you cannot or will not use a sparse clone for some reason.
- Ditto on
git apply-filter
and other techniques to 'permanently rewrite' git history, f.e. when you are tracking a third-party git repo.
- You're running Windows, using NTFS storage, git-for-windows with
bash
as your shell and have a patch.exe
available (patch --version
should report something like "GNU patch 2.7.6")
(In our case, we were messing about with a github wiki clone and ran into this issue of filenames containing colons. Of course, we wanted to fix this in place, without going the extra 'sparse clone' or WSL mile.)
Turns out we can get the missing content after we did
git config core.protectNTFS false
git checkout <hash>
by running patch
. (BTW: TortoiseGit would hang forever if you tried to diff/compare these commits!)
Use this next command to get a patch file with all the missing changes. If you have multiple files with colons or other trouble, all the missing content will be listed in the patchfile: one patchfile to catch it all!
git diff ec28c8ddd5f8c83d11604bcae69afb46d79b1029 > p.patch
# ^^^^ reference the git hash with the offending original file(s)
Now that you have a patchfile, you can apply it to the current working directory: it must be applied in reverse (-R
):
patch -R -f -i p.patch
If you forget -R
, patch will ask (answer [y]es
); if you do specify -R
patch will yak even more, so -f
(force) is in order to shut up patch and just do the job.
This should list one or more files being patched as a result, e.g.
$ patch -R -f -i p.patch
patching file Writing-Bops:-The-Bebop-Schema-Language.md
Note the colon in that filename: turns out GNU patch on windows (at least v2.7.6) uses a Unicode homoglyph to simulate a colon in a filename. See also further below.
You now have the original content of the colon-ed files in your working directory and you're now ready to add these files to the git index and commit them as usual:
Warning: you'll probably need to cleanup (delete) the empty clipped filenames produced by your earlier git checkout
before proceeding!
Note: if you don't like the homoglyphed filename patch -i
assigned to the missing content, you can change it to anything you like before committing the result.
git add *
git commit
Verifying results
When you did everything right, that last commit should list the colon-ed file as renamed as you did not change the content and git commit
should thus have detected the "file rename action" as-is.
Extra: replacing colon with a homoglyph
I found several Unicode homoglyphs that look more or less like a colon, but are considered legal in NTFS filenames.
After a bit of experimentation, I decided on using ꞉
as I wanted to keep the github wiki page I was fiddling with intact as much as possible.
Generally, I would discard the colon entirely, or replace it with one or more hyphens, but in the case of wiki MarkDown pages, that decision can go the other way.