Improve macOS Icon pattern to avoid line-ending corruption
Reasons for making this change
The current Icon\r pattern in macOS.gitignore has a reliability issue: the invisible carriage return (CR) character is silently corrupted by editors' default behavior, causing the rule to fail even when developers believe they haven't modified the file.
Core Problem: Silent Line-Ending Conversion
The literal \r character in the .gitignore file is automatically processed by modern editors during save operations, even when file content is ultimately unchanged.
Actual corruption observed (real git diff output):
diff --git a/Global/macOS.gitignore b/Global/macOS.gitignore
--- a/Global/macOS.gitignore
+++ b/Global/macOS.gitignore
@@ -3,7 +3,8 @@
__MACOSX/
.AppleDouble
.LSOverride
-Icon[^M]
+Icon[
+]
What happened:
- Original rule:
Iconfollowed by carriage return (displayed as^Min some environments) - After corruption: CR is replaced by LF (
\n), splitting the pattern into two lines - Result: Pattern becomes
Icon[+ new line], completely broken - macOS
Icon\rfiles are no longer matched and start appearing ingit status
Precise Reproduction Steps (Verified)
Test Environment:
- Editor: VS Code (without EditorConfig enabled)
- File:
Global/macOS.gitignore
Reproduction Steps:
- Open
.gitignorefile containing theIcon\rrule - Modify other content in the file (e.g., add a comment line)
- Save the file (Ctrl+S / Cmd+S)
- Undo the modification (Ctrl+Z / Cmd+Z), reverting to original state
- Save the file again
- Check changes with
git diff
Expected Result:
- File content has been reverted, there should be no diff
Actual Result:
- The diff above appears:
Icon\ris split into two lines - Git shows the file as modified, even though the developer made no intentional changes
Analysis:
- VS Code silently converted
\r→\nduring the first save - Even though the developer undid all content changes, the line-ending conversion persisted
- This is VS Code's default line-ending normalization behavior
- Developers cannot perceive this change from the editor interface (requires checking git diff)
Why This Is a Serious Problem
High stealth:
- Developers believe they "didn't modify the file" (content was indeed reverted)
- Git shows the file as changed (line endings were converted)
- Difficult to diagnose that the
\rcharacter caused the issue
Wide impact:
- Once someone opens and edits this file with VS Code
- The rule becomes permanently broken
- Other macOS users' Icon files start appearing in version control
No error indication:
- No warnings that the gitignore rule is corrupted
- File appears "normal" (no visual anomalies in the editor)
Solution: Use Character Class Pattern
Replace Icon\r with Icon[^!-~] (Icon followed by any non-printable character):
Technical Rationale:
[^!-~]matches all characters outside the ASCII printable range (33-126)- Includes all control characters: CR(13), LF(10), TAB(9), etc. (ASCII 0-32)
- Includes DEL character (ASCII 127)
Why This Works:
- ✅ Completely immune to line-ending processing: Character class syntax
[^!-~]contains only printable characters and won't be modified by editors' line-ending normalization - ✅ Won't be split into multiple lines: Entire pattern is single-line printable text
- ✅ Stable and reliable: Pattern remains unchanged regardless of how many times you save/undo
- ✅ Visible: Clear in code reviews and diffs, no invisible characters
- ✅ Functionally equivalent: Covers all real macOS Icon files (
Icon\r)
Backward Compatibility:
- ✅ 100% matches all legitimate macOS
Icon\rfiles - ⚠️ Theoretically matches
Icon + any control charactercombinations- Practical impact: negligible. macOS Finder only creates
Icon\rfiles - If files with other control characters exist, they are abnormally named and should be ignored anyway
- Practical impact: negligible. macOS Finder only creates
- ✅ Won't false-match normal files:
Icon.png,IconSet,Icon!,Icon123etc. are explicitly excluded!(ASCII 33) to~(ASCII 126) defines the printable character range boundary
Why Character Class Is the Best Solution
Comparison of possible approaches:
| Approach | Viable | Issue |
|---|---|---|
Keep Icon\r |
❌ | Cannot resist editor line-ending normalization, will be silently corrupted |
Use Icon[\r] |
❌ | The \r inside brackets is still a literal byte, will be converted the same way |
Use Icon? |
❌ | Would false-match Icon1, Icona and other normal files |
Use Icon* |
❌ | Would match all Icon-prefixed files |
Use Icon[^!-~] |
✅ | Pure printable character syntax, immune to line-ending processing; precise function; stable after undo |
Links to documentation supporting these rule changes
N/A - This change fixes an editor compatibility issue discovered through testing. The pattern syntax is standard gitignore format documented in the Git documentation.
If this is a new template
N/A - This PR modifies an existing template (Global/macOS.gitignore), not adding a new one.
Merge and Approval Steps
- [x] Confirm that you've read the contribution guidelines and ensured your PR aligns
- [ ] Ensure CI is passing
- [ ] Get a review and Approval from one of the maintainers
======================================
Icon[^!-~] Full Validation Test
======================================
📝 Creating test files...
✓ Creating control character files (should be ignored):
- Icon\r (CR-13) ← target file
- Icon\t (TAB-9)
- Icon\n (LF-10)
- Icon\f (FF-12)
- Icon\x1B (ESC-27)
- Icon space (SP-32)
- Icon\x7F (DEL-127)
✓ Creating printable character files (should not be ignored):
- Icon! (boundary-33)
- Icon" (34)
- Icon# (35)
- Icon$ (36)
- Icon~ (boundary-126)
- Icon.png
- Icon.svg
- Icon.ico
- Icon.icns
- Icona
- Icon1
- Icon123
- IconSet
- Icon_old
- Icon-new
- Icon.backup
- MyIcon
- icon.png (lowercase)
✓ Creating multi-character test files:
- Icon\r\r (double carriage return)
- Icon\r\n (Windows line ending)
📋 File list (with byte display):
Icon\t
Icon\n
Icon\f
Icon\r
Icon\r\n
Icon\r\r
Icon\033
Icon
Icon!
Icon\"
Icon#
Icon$
Icon-new
Icon.backup
Icon.icns
Icon.ico
Icon.png
Icon.svg
Icon1
Icon123
IconSet
Icon_old
Icona
Icon~
Icon\177
MyIcon
🔍 Inspecting byte code of Icon\r:
00000000: 4963 6f6e 0d Icon.
======================================
Begin testing gitignore rule
======================================
[Test 1] Files that should be ignored (control characters):
--------------------------------------
✅ Icon\r (CR-13) correctly ignored
✅ Icon\t (TAB-9) correctly ignored
✅ Icon\n (LF-10) correctly ignored
✅ Icon\f (FF-12) correctly ignored
✅ Icon\x1B (ESC-27) correctly ignored
✅ Icon space (SP-32) correctly ignored
✅ Icon\x7F (DEL-127) correctly ignored
[Test 2] Files that should not be ignored (printable characters):
--------------------------------------
✅ Icon! (boundary-33) not ignored
✅ Icon" (34) not ignored
✅ Icon# (35) not ignored
✅ Icon~ (boundary-126) not ignored
✅ Icon.png not ignored
✅ Icon.svg not ignored
✅ Icona not ignored
✅ Icon1 not ignored
✅ Icon123 not ignored
✅ IconSet not ignored
✅ Icon_old not ignored
✅ Icon-new not ignored
✅ MyIcon not ignored
✅ icon.png (lowercase) not ignored
[Test 3] Multi-character boundary cases:
--------------------------------------
✅ Icon\r\r (should not match) not ignored
✅ Icon\r\n (should not match) not ignored
[Test 4] git check-ignore -v detailed check:
--------------------------------------
.gitignore:1:Icon[^!-~] "Icon\r"
======================================
Test summary
======================================
✅ All tests passed! Icon[^!-~] rule works as expected
Validation summary:
✓ Icon\r (macOS Icon file) correctly ignored
✓ All control character files ignored
✓ All normal files unaffected
✓ Boundary characters (!, ~) handled correctly
Ued7ed7ee7e7e7eeuee7euesueueueueueu4
Dorian Gurazdowski - Chat @ Spike [3did87]
On November 10, 2025 at 19:32 GMT, silentip404 @.***> wrote:
silentip404 left a comment (github/gitignore#4753) ====================================== Icon[^!-~] Full Validation Test ====================================== 📝 Creating test files... ✓ Creating control character files (should be ignored): - Icon\r (CR-13) ← target file - Icon\t (TAB-9) - Icon\n (LF-10) - Icon\f (FF-12) - Icon\x1B (ESC-27) - Icon space (SP-32) - Icon\x7F (DEL-127) ✓ Creating printable character files (should not be ignored): - Icon! (boundary-33) - Icon" (34) - Icon# (35) - Icon$ (36) - Icon~ (boundary-126) - Icon.png - Icon.svg - Icon.ico - Icon.icns - Icona - Icon1 - Icon123 - IconSet - Icon_old - Icon-new - Icon.backup - MyIcon - icon.png (lowercase) ✓ Creating multi-character test files: - Icon\r\r (double carriage return) - Icon\r\n (Windows line ending) 📋 File list (with byte display): Icon\t Icon\n Icon\f Icon\r Icon\r\n Icon\r\r Icon\033 Icon Icon! Icon" Icon# Icon$ Icon-new Icon.backup Icon.icns Icon.ico Icon.png Icon.svg Icon1 Icon123 IconSet Icon_old Icona Icon~ Icon\177 MyIcon 🔍 Inspecting byte code of Icon\r: 00000000: 4963 6f6e 0d Icon. ====================================== Begin testing gitignore rule ====================================== [Test 1] Files that should be ignored (control characters): -------------------------------------- ✅ Icon\r (CR-13) correctly ignored ✅ Icon\t (TAB-9) correctly ignored ✅ Icon\n (LF-10) correctly ignored ✅ Icon\f (FF-12) correctly ignored ✅ Icon\x1B (ESC-27) correctly ignored ✅ Icon space (SP-32) correctly ignored ✅ Icon\x7F (DEL-127) correctly ignored [Test 2] Files that should not be ignored (printable characters): -------------------------------------- ✅ Icon! (boundary-33) not ignored ✅ Icon" (34) not ignored ✅ Icon# (35) not ignored ✅ Icon~ (boundary-126) not ignored ✅ Icon.png not ignored ✅ Icon.svg not ignored ✅ Icona not ignored ✅ Icon1 not ignored ✅ Icon123 not ignored ✅ IconSet not ignored ✅ Icon_old not ignored ✅ Icon-new not ignored ✅ MyIcon not ignored ✅ icon.png (lowercase) not ignored [Test 3] Multi-character boundary cases: -------------------------------------- ✅ Icon\r\r (should not match) not ignored ✅ Icon\r\n (should not match) not ignored [Test 4] git check-ignore -v detailed check: -------------------------------------- .gitignore:1:Icon[^!-~] "Icon\r" ====================================== Test summary ====================================== ✅ All tests passed! Icon[^!-~] rule works as expected Validation summary: ✓ Icon\r (macOS Icon file) correctly ignored ✓ All control character files ignored ✓ All normal files unaffected ✓ Boundary characters (!, ~) handled correctly
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.Message ID: @.***>