gitignore binary files that have no extension

GitGitignore

Git Problem Overview


How can binary files be ignored in git using the .gitignore file?

Example:

$ g++ hello.c -o hello

The "hello" file is a binary file. Can git ignore this file ?

Git Solutions


Solution 1 - Git

# Ignore all
*

# Unignore all with extensions
!*.*

# Unignore all dirs
!*/

### Above combination will ignore all files without extension ###

# Ignore files with extension `.class` & `.sm`
*.class
*.sm

# Ignore `bin` dir
bin/
# or
*/bin/*

# Unignore all `.jar` in `bin` dir
!*/bin/*.jar

# Ignore all `library.jar` in `bin` dir
*/bin/library.jar

# Ignore a file with extension
relative/path/to/dir/filename.extension

# Ignore a file without extension
relative/path/to/dir/anotherfile

Solution 2 - Git

Add something like

*.o

in the .gitignore file and place it at the root of your repo ( or you can place in any sub directory you want - it will apply from that level on ) and check it in.

Edit:

For binaries with no extension, you are better off placing them in bin/ or some other folder. Afterall there is no ignore based on content-type.

You can try

*
!*.*

but that is not foolproof.

Solution 3 - Git

To append all executables to your .gitignore (which you probably mean by "binary file" judging from your question), you can use

find . -executable -type f >>.gitignore

If you don't care about ordering of lines in your .gitignore, you could also update your .gitignore with the following command which also removes duplicates and keeps alphabetic ordering intact.

T=$(mktemp); (cat .gitignore; find . -executable -type f | sed -e 's%^\./%%') | sort | uniq >$T; mv $T .gitignore

Note, that you cannot pipe output directly to .gitignore, because that would truncate the file before cat opens it for reading. Also, you might want to add \! -regex '.*/.*/.*' as an option to find if you do not want to include executable files in subdirectories.

Solution 4 - Git

Your best bet with binaries is to either give them an extension that you can easily filter out with a standard pattern, or put them into directories that you can filter out at the directory level.

The extension suggestion is more applicable in Windows, because extensions are standard and basically required, but in Unix, you may or may not use extensions on your executable binaries. In this case, you can put them in a bin/ folder, and add bin/ to your .gitignore.

In your very specific, small-scope example, you can just put hello in your .gitignore.

Solution 5 - Git

Binary files are often without extensions. If this is your case try this:

*
!/**/
!*.*

REF: https://stackoverflow.com/a/19023985/1060487

Solution 6 - Git

You may try in your .gitignore:

*
!*.c

This approach has many disadvantages, but it's acceptable for small projects.

Solution 7 - Git

If you're using a makefile, you could try modifying your make rules to append the names of new binaries to your .gitignore file.

Here's an example Makefile for a small Haskell project;

all: $(patsubst %.hs, %, $(wildcard *.hs))

%: %.hs
    ghc $^
    grep -xq "$@" .gitignore || echo $@ >> .gitignore

This makefile defines a rule for creating executables out of Haskell code. After ghc is invoked, we check the .gitignore to see if the binary is already in it. If it isn't, we append the name of the binary to the file.

Solution 8 - Git

The most specific gitignore line is normally the best, so that you don't accidentally hide files from git, which causes hard-to-diagnose problems when someone else checks out your commit. Hence, I recommend specifically gitignoring only the file called hello in the root of your directory. To do that, add:

/hello

to the .gitignore file in the root of your repository. (It is also possible to have .gitignore files elsewhere in the repository, and this makes sense when your git repository contains multiple projects, which you might want to move around later, or split off into their own repository one day.)

However, if you really want to ignore all files that have no extension, you could use:

/[^\.]*

or even less specific:

[^\.]*

Explanation:

/  starting with / means "only in the root of the repository"
[] encloses a character class, e.g. [a-zA-Z] means "any letter".
^  means "not"
\. means a literal dot - without the backslash . means "any character"
*  means "any number of these characters"

Solution 9 - Git

Here's another solution using file. This way executable scripts will not end up in gitignore. You may need to change how the output from file is interpreted to match your system. One could then set up a pre-commit hook to call this script each time you commit.

import subprocess, os

git_root = subprocess.check_output(['git', 'root']).decode("UTF-8").strip()
exes = []
cut = len(git_root)

for root, dirnames, filenames in os.walk(git_root+"/src/"):
  for fname in filenames:
    f = os.path.join(root,fname)
    if not os.access(f,os.X_OK):
      continue

    ft = subprocess.check_output(['file', f]).decode("UTF-8")

    if 'ELF' in ft and 'executable' in ft:
      exes.append(f[cut:])

gifiles = [ str.strip(a) for a in open(git_root + "/.gitignore").readlines() ]
gitignore=frozenset(exes+gifiles)

with open(git_root+"/.gitignore", "w") as g:
  for a in sorted(gitignore):
    print(a, file=g)

Solution 10 - Git

If you follow these commands on your .gitignore file and files still seems to appear you may want to try:

git rm --cached FILENAME

After that, add your .gitignore, commit and push. Took me 40 minutes to understand that, hope this helps to newbies like me

Solution 11 - Git

A way to also ignore in some subdir, not only in a root:

# Ignore everything in a root
/*
# But not files with extension located in a root
!/*.*
# And not my subdir (by name)
!/subdir/
# Ignore everything inside my subdir on any level below
/subdir/**/*
# A bit of magic, removing last slash or changing combination with previous line
# fails everything. Though very possibly it just says not to ignore sub-sub-dirs.
!/subdir/**/
# ...Also excluding (grand-)children files having extension on any level
# below subdir
!/subdir/**/*.*

Or, if you want to include only some specific types of files:

/*
!/*.c
!/*.h
!/subdir/
/subdir/**/*
!/subdir/**/
!/subdir/**/*.c
!/subdir/**/*.h

Seems it may even also work like for every new subdirectory if you want!:

/*
!/*.c
!/*.h
!/*/
/*/**/*
!/*/**/
!/*/**/*.c
!/*/**/*.h

Leading slashes are important only in first two lines and optional in other. Tailing slash in !/*/ and !/subdir/ is also optional, but only in this line.

Solution 12 - Git

Old thread, but still relevant. I changed the makefile so the resulting binary file after linking has the name [filname].bin instead of only [filname]. Then I added *.bin files in the gitignore.
This routine fulfill my needs.

Solution 13 - Git

I don't know any other solution but adding them one by one to .gitignore.

A crude way to test is to grep the file command's output:

find . \( ! -regex '.*/\..*' \) -type f | xargs -n 1 file | egrep "ASCII|text"

EDIT

Why don't you simply name you executable hello.bin?

Solution 14 - Git

Just add hello or /hello to your .gitignore. Either works.

Solution 15 - Git

Building on [VenomVendors answer][1]

# Ignore all
*

# Unignore all files with extensions recursively
!**/*.*

# Unignore Makefiles recursively
!**/Makefile

# other .gitignore rules...

[1]: https://stackoverflow.com/a/25592735/1119345 "VenomVendors answer"

Solution 16 - Git

I created a .gitignore file with two entries in GOPATH directory.

/bin
/pkg

It ignore all the compiled developments, currently.

Solution 17 - Git

.gitignore uses glob programming to filter files, at least on Linux.

I am about to give a coding talk at a Meetup and, in preparation, I made a directory with several subdirectories that are named according to the order I want to present them: 01_subject1, 02_subject2, 03_subject3. Each subdirectory contains a source file with a language-dependent extension that compiles to an executable file whose name matches the source file name without the extension according to common practice.

I exclude the compiled files in the numeral-prefixed directories with the following .gitignore line:

[0-9][0-9]_*/[!\.]*

According to my understanding of the documentation, it shouldn't work. Having the trailing asterisk should fail because it should match any number of unspecified characters, including the '.' + extension. Omitting the trailing asterisk should fail (and does) because [!\.] matches only a single non-period character. However, I added the trailing asterisk, as I would for a regular expression, and it works. By work, I mean that git notices changes to the source file, but not the existence or changes to the compiled files.

Solution 18 - Git

The .gitignore mechanism works only based on file names, not on file contents. Being a binary file is a property of the content, hence you can't ask git ignore binary files directly, but only to ignore them by name (and as other suggested, you can either add all binary file names to your .gitignore or use an appropriate naming convention).

The fact that .gitignore works on file names is an important property performance-wise: Git only needs to list files, but not to open and read them to know which files to ignore. In other words, Git would be terribly slow if you could ask it to ignore files based on their contents.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJuanPabloView Question on Stackoverflow
Solution 1 - GitVenomVendorView Answer on Stackoverflow
Solution 2 - GitmanojldsView Answer on Stackoverflow
Solution 3 - GiticksView Answer on Stackoverflow
Solution 4 - GitAndy WhiteView Answer on Stackoverflow
Solution 5 - GitmattdlockyerView Answer on Stackoverflow
Solution 6 - GitAndrei BeliankouView Answer on Stackoverflow
Solution 7 - GitvedantkView Answer on Stackoverflow
Solution 8 - GitTamaMcGlinnView Answer on Stackoverflow
Solution 9 - GitTyler EarnestView Answer on Stackoverflow
Solution 10 - GitShaun PeretzView Answer on Stackoverflow
Solution 11 - Gitshaman.sirView Answer on Stackoverflow
Solution 12 - GitNalle HaddockView Answer on Stackoverflow
Solution 13 - GitmuhukView Answer on Stackoverflow
Solution 14 - GitTravis ReederView Answer on Stackoverflow
Solution 15 - GitEero AaltonenView Answer on Stackoverflow
Solution 16 - GitgszecsenyiView Answer on Stackoverflow
Solution 17 - GitchuckjView Answer on Stackoverflow
Solution 18 - GitMatthieu MoyView Answer on Stackoverflow