【问题标题】:gitignore binary files that have no extension没有扩展名的 gitignore 二进制文件
【发布时间】:2011-04-19 03:00:00
【问题描述】:

如何使用.gitignore 文件在git 中忽略二进制文件?

例子:

$ g++ hello.c -o hello

“hello”文件是一个二进制文件。 git 可以忽略这个文件吗?

【问题讨论】:

标签: git gitignore


【解决方案1】:
# 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

【讨论】:

  • 这个解决方案就像一个魅力!我不明白为什么通过 unignore all dirs "!*/",它也可以 unignore subdir 的带有扩展名的文件? (例如 aaa/bbb.c)但仍然忽略不带扩展名的子目录文件。 (例如 aaa/ccc)
  • 当我发现有多层目录时,似乎这个方法并没有按预期工作......
  • @dragonxlwang 我很好奇这在哪里不起作用?这里接受的解决方案 stackoverflow.com/a/19023985/1426932 略有不同,使用 !/**/ 而不是 !*/ ;哪一个是正确的? /cc @VonC​​pan>
  • 在 Unix 文化中,命名 shell 脚本以及不带扩展名的二进制可执行文件是相当普遍的,在这种情况下,此解决方案将导致脚本被忽略。一个更好的主意是,只要将二进制可执行文件添加到项目中,就手动将它们添加到 .gitignore ——它通常不会经常发生。如果实在是太麻烦了,那么vedantk建议的makefile方案会更好。
  • 这将忽略 makefile
【解决方案2】:

添加类似的东西

*.o

在 .gitignore 文件中并将它放在你的 repo 的根目录中(或者你可以放在任何你想要的子目录中——它将从那个级别开始应用)并签入。

编辑:

对于没有扩展名的二进制文件,最好将它们放在bin/ 或其他文件夹中。毕竟没有基于内容类型的忽略。

你可以试试

*
!*.*

但这并不是万无一失的。

【讨论】:

  • 添加了编辑。你有什么理由不希望你的二进制文件有扩展名
  • 可执行文件通常没有扩展名。我正在尝试对 gcc 通过 -o $@ 创建的文件执行相同的操作。
  • * 会忽略所有内容,甚至是目录,因此 !*.* 不会在目录中取消忽略,因此将 !*/ 添加到 .gitignore 以添加目录,然后 `!*.* 也会取消忽略文件在带有扩展名的目录中
【解决方案3】:

要将所有可执行文件附加到您的.gitignore(从您的问题来看,您可能是指“二进制文件”),您可以使用

find . -executable -type f >>.gitignore

如果您不关心 .gitignore 中的行顺序,您还可以使用以下命令更新您的 .gitignore,该命令还可以删除重复项并保持字母顺序不变。

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

请注意,您不能将输出直接通过管道传输到.gitignore,因为这会在cat 打开文件进行读取之前截断文件。此外,您可能需要添加\! -regex '.*/.*/.*' 作为选项来查找您是否不想在子目录中包含可执行文件。

【讨论】:

  • 此答案的可能更新可能是find . -executable -type f ! -name "*.*",只获取没有扩展名的可执行文件。
【解决方案4】:

使用二进制文件的最佳选择是给它们一个扩展,以便您可以使用标准模式轻松过滤掉它们,或者将它们放入可以在目录级别过滤掉的目录中。

扩展建议更适用于 Windows,因为扩展是标准的并且基本上是必需的,但在 Unix 中,您可能会或可能不会在可执行二进制文件上使用扩展。在这种情况下,您可以将它们放在 bin/ 文件夹中,并将 bin/ 添加到您的 .gitignore 中。

在您非常具体的小范围示例中,您只需将 hello 放入您的 .gitignore 中即可。

【讨论】:

    【解决方案5】:

    二进制文件通常没有扩展名。如果这是你的情况,试试这个:

    *
    !/**/
    !*.*
    

    参考号:https://stackoverflow.com/a/19023985/1060487

    【讨论】:

      【解决方案6】:

      你可以试试你的.gitignore:

      *
      !*.c
      

      这种方法有很多缺点,但对于小型项目来说是可以接受的。

      【讨论】:

      • 如果你能至少列出主要缺点就好了
      • 明显的缺点是允许 - 拒绝规则的顺序,正确的方法是只忽略不需要的文件,而不是全部禁止然后只包含想要的文件。
      【解决方案7】:

      如果您使用的是 makefile,您可以尝试修改您的 make 规则以将新二进制文件的名称附加到您的 .gitignore 文件中。

      这是一个小型 Haskell 项目的 Makefile 示例;

      all: $(patsubst %.hs, %, $(wildcard *.hs))
      
      %: %.hs
          ghc $^
          grep -xq "$@" .gitignore || echo $@ >> .gitignore
      

      这个 makefile 定义了从 Haskell 代码中创建可执行文件的规则。调用 ghc 后,我们检查 .gitignore 以查看二进制文件是否已在其中。如果不是,我们将二进制文件的名称附加到文件中。

      【讨论】:

      • 现在,这是一种不同的方法。
      【解决方案8】:

      最具体的 gitignore 行通常是最好的,这样您就不会意外地从 git 中隐藏文件,这会在其他人检查您的提交时导致难以诊断的问题。因此,我建议专门 gitignoring 仅在您的目录的根目录中名为 hello 的文件。为此,请添加:

      /hello
      

      到存储库根目录中的.gitignore 文件。 (也可以在存储库的其他地方有 .gitignore 文件,当您的 git 存储库包含多个项目时,这很有意义,您可能希望稍后移动这些项目,或者有一天将其拆分到自己的存储库中。)

      但是,如果您真的想忽略所有没有扩展名的文件,您可以使用:

      /[^\.]*
      

      甚至更不具体:

      [^\.]*
      

      解释:

      /  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"
      

      【讨论】:

      • 此解决方案还会忽略带有test.txt等扩展名的文件
      • ^ 表示 unix 中的行首。 gitignore 有什么不同吗?
      • 是的,实际上没有“行首”,因为这是文件/目录路径的列表。 '/' 是等价的,是 .gitignore 文件的路径。请注意,您可以在所需的 git repo 中的多少个目录中拥有一个 .gitignore 文件,这也是一个好主意,因为移动该目录将不再需要修改其他 .gitignores。
      【解决方案9】:

      这是另一种使用文件的解决方案。这样可执行脚本就不会出现在 gitignore 中。您可能需要更改文件输出的解释方式以匹配您的系统。然后可以设置一个预提交挂钩,以便在每次提交时调用此脚本。

      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)
      

      【讨论】:

      • 我制作了一个类似的脚本,并发布了一个重复的问题:stackoverflow.com/a/28258619/218294 你的代码更好:) 我的可能运行得更快,因为它只运行“文件”一次或几次(使用 xargs )。
      【解决方案10】:

      如果您在 .gitignore 文件上执行这些命令,并且文件似乎仍然出现,您可能需要尝试:

      git rm --cached FILENAME
      

      之后,添加您的 .gitignore,提交并推送。 我花了 40 分钟才明白这一点,希望这对像我这样的新手有所帮助

      【讨论】:

        【解决方案11】:

        一种在某些子目录中也可以忽略的方法,而不仅仅是在根目录中:

        # 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/**/*.*
        

        或者,如果您只想包含某些特定类型的文件:

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

        如果你愿意,它甚至可以像每个新的子目录一样工作!:

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

        前导斜杠仅在前两行中很重要,在其他行中是可选的。 !/*/!/subdir/ 中的尾部斜线也是可选的,但仅限于这一行。

        【讨论】:

          【解决方案12】:

          旧线程,但仍然相关。 我更改了 makefile,因此链接后生成的二进制文件的名称为 [filname].bin 而不仅仅是 [filname]。然后我在 gitignore 中添加了 *.bin 文件。
          这个例程满足了我的需求。

          【讨论】:

            【解决方案13】:

            我不知道任何其他解决方案,但将它们一一添加到.gitignore

            一种粗略的测试方法是 grep 文件命令的输出:

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

            编辑

            为什么不简单地将你的可执行文件命名为hello.bin

            【讨论】:

            • 因为使用文件扩展名.bin 命名可执行文件是不好的做法。
            【解决方案14】:

            只需将hello/hello 添加到您的.gitignore。要么工作。

            【讨论】:

            • 这也会忽略一个名为hello的文件夹。
            【解决方案15】:

            VenomVendors answer 为基础

            # Ignore all
            *
            
            # Unignore all files with extensions recursively
            !**/*.*
            
            # Unignore Makefiles recursively
            !**/Makefile
            
            # other .gitignore rules...
            

            【讨论】:

              【解决方案16】:

              我在 GOPATH 目录中创建了一个包含两个条目的 .gitignore 文件。

              /bin
              /pkg
              

              它目前忽略所有已编译的开发。

              【讨论】:

                【解决方案17】:

                .gitignore 使用glob programming 过滤文件,至少在 Linux 上是这样。

                我即将在 Meetup 上进行编码演讲,在准备过程中,我创建了一个目录,其中包含几个子目录,这些子目录按照我想要呈现的顺序命名:01_subject1、02_subject2、03_subject3。每个子目录都包含一个源文件,其扩展名与语言相关,根据惯例,该文件会编译成一个可执行文件,该文件的名称与源文件名匹配,但没有扩展名。

                我使用以下 .gitignore 行排除了数字前缀目录中的编译文件:

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

                根据我对文档的理解,它不应该工作。带有尾随星号应该会失败,因为它应该匹配任意数量的未指定字符,包括“。” + 扩展。省略尾随星号应该会失败(并且确实会失败),因为 [!\.] 仅匹配单个非句点字符。但是,我添加了尾随星号,就像我添加正则表达式一样,它可以工作。通过工作,我的意思是 git 注意到源文件的更改,而不是编译文件的存在或更改。

                【讨论】:

                  【解决方案18】:

                  .gitignore 机制仅基于文件名称起作用,而不是基于文件内容。作为二进制文件是内容的属性,因此您不能直接要求 git 忽略二进制文件,而只能按名称忽略它们(并且正如其他建议的那样,您可以将所有二进制文件名添加到您的 .gitignore 或使用适当的命名约定)。

                  .gitignore 作用于文件名这一事实在性能方面是一个重要的属性:Git 只需要列出文件,而不需要打开和读取它们就知道要忽略哪些文件。换句话说,如果您可以要求 Git 根据文件内容忽略文件,它会非常慢。

                  【讨论】:

                    猜你喜欢
                    • 2012-05-29
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-03-16
                    • 2016-12-24
                    • 2023-04-01
                    • 2012-12-24
                    • 1970-01-01
                    • 2013-03-20
                    相关资源
                    最近更新 更多