66

While trying to setup a dropbox folder with git, I saw a "Icon\r" file which is not created by me. I try to ignore it in the ~/.gitignore file. But adding Icon\r Icon\r\r Icon? won't work at all.

taiansu
  • 2,735
  • 2
  • 22
  • 29
  • 12
    Actually `Icon?` works for me. – 0 _ Aug 12 '13 at 22:42
  • 8
    @johntex That means you'll be ignoring "Icon" + any following character. So folders with names like "Icons" will get ignored as well, which is probably bad. – ray Sep 26 '13 at 15:34
  • 2
    I have the same issue where I have a directory named **icons** as well as a sprite named **icons.svg**. My solution was to add `!icons` to my .gitignore file so directories and files will be allowed to use that name without getting ignored. Folder icons still get ignored as desired. – wavematt Feb 03 '16 at 17:22
  • +1 for those who enlightened me that the **?** is **"\r"** or **"\r\r"**. Was having a hard time to find that out. My case was not for .gitignore but when listing a folder in PHP. I left both "Icon\r" and "Icon\r\r" in my exclude list, since the single \r was the one that worked for me. _I would use the printf solution for .gitignore._ Cheers! – Gus Neves Sep 12 '16 at 22:03

11 Answers11

69

You can use vim as well.

  1. vim .gitignore
  2. in a new line write Icon, then
  3. press ctrl+v and then press Enter
  4. repeat step 3
  5. save and exit (shortcut: ZZ)

Now you should have Icon^M^M and it's done :)

For a smarter use you could add it to your gitignore global config file in ~/.gitignore_global.

Dharma
  • 818
  • 1
  • 7
  • 7
  • 2
    I'm not sure if you need step 4? `$ find . -name "Icon^M^M"` gives nothing, but `$ find . -name "Icon^M"` gives `./Icon`. Is there something different about gitignore? – A.Wan Sep 29 '15 at 23:48
  • 1
    Actually, doesn't work on my system, neither with one `^M` – Dharma Nov 26 '15 at 23:59
  • Thanks! Do you know why we need *two* `^M` when it shows up in the `ls` results as just `Icon?` and a quick `git status` shows `"Icon\r"`? Weird. – Luke Davis Dec 13 '17 at 19:03
  • Hi @LukeDavis! Probably the char `?` is multibyte? – Dharma Dec 14 '17 at 12:11
  • 1
    You can (and should) specify the filename precisely with [ANSI-C Quoting](https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html); e.g. `find . -name $'Icon\r'` – David J. Dec 23 '20 at 16:45
  • 1
    This answer says what keys to press -- but not *what* these keypresses do -- or *why* they are necessary. – David J. Aug 27 '21 at 03:13
51

(This improves on the original answer, following a suggestion by robotspacer, according to hidn's explanation.)

The Icon? is the file of OS X folder icon. The "?" is a special character for double carriage return (\r\r).

To tell git to ignore it, open a terminal and navigate to your repository folder. Then type:

printf "Icon\r\r" >> .gitignore

If the file does not exist, it will be created and Icon\r\r will be its one line. If the file does exist, the line Icon\r\r will be appended to it.

Matthew Leingang
  • 2,579
  • 3
  • 20
  • 19
eldes
  • 1,206
  • 12
  • 16
  • 8
    The `?` stands for a _single_ carriage return. As explained by hidn's [answer](https://stackoverflow.com/a/33974028/192740) the double `\r\r` works only due to git's interpretation of the last `\r` as part of the `\r\n` EOL convention and is indeed a worse choice than `[\r]`. – cstork Nov 04 '17 at 23:27
  • 4
    Combining the two suggestions, you can use this to add the safer version of the rule to an existing file: `printf "Icon[\r]" >> .gitignore` – robotspacer May 05 '19 at 20:43
  • I suggest adding more context around how many text editors (depending on their settings) may alter line endings. They do this with good intentions; e.g. in the spirit of standardizing line endings, but in this case, it makes editing a .gitignore file more difficult. – David J. Dec 23 '20 at 16:47
  • Due to practical considerations (we tend to use text editors, and these editors often 'correct' line endings), this approach is brittle. I suggested an alternative answer at https://stackoverflow.com/a/65429032/109618 – David J. Dec 23 '20 at 18:16
  • The original answer that had been at the top of the post (with `>` instead of `>>`) clobbers the `.gitignore` file if it does exist. Given that there's no reason to use it (`>>` works in both situations), I simply deleted it. This protects users who hastily look for the first block of code in the accepted answer and copy it blindly. *raises hand sheepishly* – Matthew Leingang Dec 03 '21 at 14:21
37

"Icon[\r]" is probably a better alternative.
In vim, you just put Icon[^M], which is Icon[ followed by CtrlV, Enter then ].

The problem with "Icon\r\r" is EOL conversion.

The whole line is actually "Icon\r\r\n", counting line ending. Based on your setup, CRLF may be converted to LF on commit, so your repo will actually have "Icon\r\n". Say you sync the changes to another repo. You will get "Icon\r\n" in that working directory, which ignores Icon but not Icon^M. If you further edit .gitignore and commit it there, you will end up with "Icon\n" - completely losing \r.

I encountered this in a project where some develop on OS X while some on Windows. By using brackets to separate \r and the line ending, I don't have to repeat \r twice and I don't worry about EOL conversion.

mkjeldsen
  • 2,053
  • 3
  • 23
  • 28
hidn
  • 479
  • 4
  • 4
23

The best place for this is in your global gitignore configuration file. You can create this file, access it, and then edit per the following steps:

>> git config --global core.excludesfile ~/.gitignore_global

>> vim ~/.gitignore_global

press i to enter insert mode

type Icon on a new line

while on the same line, ctrl + v, enter, ctrl + v, enter

press esc, then shift + ; then type wq then hit enter

Matt Browne
  • 12,169
  • 4
  • 59
  • 75
rjatkinson
  • 498
  • 4
  • 11
  • This answer says what keys to press -- but not *what* they do -- or why they are necessary. – David J. Aug 27 '21 at 03:11
  • 1
    +1 Putting this in a global gitignore is the "one and only one truly obvious way to do it." `printf "Icon\r\r" >> ~/.gitignore_global` on the command line (as in eldes's answer) will add the line without using vim. – Matthew Leingang Dec 03 '21 at 14:26
22

Regarding Naming (and Quoting) Things: First, more people would benefit by knowing that ANSI-C Quoting can be used to unambiguously match the macOS icon file. Both Icon$'\r' or $'Icon\r' and work in Bash and Zsh and most other modern shells, I hope, such as Fish.

Keep Your .gitignore Editable: While I'm impressed by the byte-level manipulation offered by other answers here, these methods are brittle in practice. Simply put, programmers tend to use text editors, and many of these editors are configured to alter line endings when saving a file. (For example, see this VS Code discussion about line ending normalization.)

Do you want your careful byte editing undone by your editor? Of course not. So perhaps you find it practical and convenient to configure your editor so that it doesn't affect line endings. You might look into (a) editor-specific configuration settings; or (b) cross-editor configuration (i.e. EditorConfig).

But this gets complex and messy. If want a simpler, more flexible way, use this in your .gitignore file:

# .gitignore
Icon?
![iI]con[_a-zA-Z0-9]

Explanation for the patterns:

  • Use Icon? because the gitignore format does not support \r as an escape code.
  • Use [iI] because Git can be case sensitive.
  • Use [_a-zA-Z0-9] to catch many common ASCII characters; you may want to broaden this.

You can test that your gitignore patterns are working as expected with:

git check-ignore -v *

For example, for testing, with these files in a directory:

-rw-r--r--@  Icon?
-rw-r--r--   icon8
drwxr-xr-x   icons
-rw-r--r--   iconography

... the result of git check-ignore -v * is:

/Users/abc/.gitignore:3:Icon?   "Icon\r"
/Users/abc/.gitignore:4:![iI]con[_a-zA-Z0-9]    icon_
/Users/abc/.gitignore:4:![iI]con[_a-zA-Z0-9]    icons

This is what you want.

Long Term Recommendation This problem would be trivial to fix if Git supported the \r escape in .gitconfig files. One could simply write:

# .gitignore
Icon[\r]

So I suggest we engage with the Git community and try to make this happen.

(If you do want to wade in and suggest a patch to Git, be sure to read first.)

References

From the gitignore documentation:

Otherwise, Git treats the pattern as a shell glob: "*" matches anything except "/", "?" matches any one character except "/" and "[]" matches one character in a selected range. See fnmatch(3) and the FNM_PATHNAME flag for a more detailed description.

Please see This linuxize.com article for good examples of the square bracket syntax and negation syntax in .gitignore files.

For those that want to dig deep and see how pattern matching has changed over time in the Git source code, you can run this search for uses of fnmatch in the git repository on GitHub.

David J.
  • 31,569
  • 22
  • 122
  • 174
  • 4
    This answer should be at the top, and the accepted answer should be changed to this. It is truly the best if you edit gitignore files both from the command line or using a text editor (or only the latter). – cristian Oct 18 '21 at 12:12
  • 1
    This one is more robust. – Honghao Z Feb 17 '22 at 20:15
11

The Icon? is the file of OSX folder icon. It turn out that \r is actually CRLF. So I use ruby to add the line to .gitignore file. Open terminal and navigate to home folder, then:

> irb
>> f = File.open(".gitignore", "a+") #<File:.gitignore>
>> f.write("Icon\r\r")  # output a integer
>> f.close
>> exit
taiansu
  • 2,735
  • 2
  • 22
  • 29
3

I'm posting just an update answer because the one above didn't work for me but actually simply adding Icon? in my .gitignore worked. If you look at your name file on your Finder, it is actually how it is displayed.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Antoine Krajnc
  • 1,163
  • 10
  • 29
  • Note that `Icon?` will ignore things like "Icons" as well. For most of the answers to work your line ending should be `LF`, but on macs it's `CR`, AFAIK. And it also depends on your git's line ending conversion setting. It's displayed like that because many apps use "?" as a placeholder for any non-printable character. – EvgenKo423 Mar 12 '21 at 11:38
2

For me this worked in TextMate: Icon<CR><CR>. The <CR> is a carriage return character, which is at ctrl-alt-return on the keyboard. You can also find it in the standard Character Viewer app searching for cr. Please note that the <CR> is an invisible character, so it's only visible if the editor is set up to show them.

enter image description here

AAGD
  • 1,365
  • 1
  • 11
  • 18
1

Icon[\r] did not work for me. I had to use the following in .gitignore...

Icon*

I also added Icon* to my Settings > Core > Ignored Names in Atom...

.git, .hg, .svn, .DS_Store, ._*, Thumbs.db, desktop.inis, Icon*
ow3n
  • 5,974
  • 4
  • 53
  • 51
0

Add Icon? to your .gitignore file and save it. It should do the job.

Icon?
Rishabh
  • 1
  • 2
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 03 '22 at 17:12
0

To avoid wasting time on such trivial issues, I recommend using gibo.

gibo dump macOS >> .gitignore

The result:

### Generated by gibo (https://github.com/simonwhitaker/gibo)
### https://raw.github.com/github/gitignore/e5323759e387ba347a9d50f8b0ddd16502eb71d4/Global/macOS.gitignore

# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
Satoshi
  • 61
  • 1
  • 3