12624


一般的にLinuxの実行可能ファイルには拡張子をつけないので.gitignoreで一括して無視することができません。.gitignoreに個々の実行可能ファイルのパスを書くという方法は、あまりスマートではない気がします。

もっとスマートな方法はあるでしょうか。.gitignoreでfileコマンドの実行結果を使う、あるいは、拡張子のないバイナリファイルは無視する、等の記述ができても良いのかなとも思います。

スクリプトを書いて.gitignoreを自動生成する等も考えられますが、そうではなく、git側に便利機能として用意されていたら教えてほしいです。

また、もしgitの開発等についてくわしいかたでしたら、今後そのための機能が追加される予定はあるのか、あるいは何らかの理由でその可能性はすくない等も教えていただけたら幸いです。


CC BY-SA 3.0
2015-07-23T01:09:24.750
12591
2015-07-23T12:50:53.420
269
question
git
gitで拡張子のない実行ファイルを無視する方法


拡張子が無いファイルを一括無視することが適切かどうかはおいといて  
(Makefile にも Doxyfile にも拡張子ないですし、ディレクトリにも拡張子つかないし)

オイラ [mercurial](/questions/tagged/mercurial "'mercurial' のタグが付いた質問を表示")
しか使っていないので [git](/questions/tagged/git "'git' のタグが付いた質問を表示") はわからないんですが  
条件「ドット文字 U+002E を含まない」正規表現を .hgignore に書けばいいってことなら

[code]

    syntax:regexp
    ^((?!\.).)*$
    
[/code]

でいけそうな気がします。  
[mercurial](/questions/tagged/mercurial "'mercurial' のタグが付いた質問を表示") ではこれで
Makefile や Doxyfile 等が対象外になりました。

[code]

    $ hg init
    $ hg status -i
    I Doxyfile
    I Makefile
    I html/index.html
    I latex/files.tex
    $
    
[/code]

ファイル属性 rwx の x が立っていたら無視、という機能はなさそうです。  
Windows で使えないし、標準機能として追加されるとも思えません。

[git](/questions/tagged/git "'git' のタグが付いた質問を表示") でどう .gitignore を書けば良いか
.gitignore のデバッグをするかは  
[git](/questions/tagged/git "'git' のタグが付いた質問を表示") ユーザーの方にお任せで。


CC BY-SA 3.0
2015-07-23T02:20:43.033
12594
2015-07-23T02:20:43.033
8589
12591
answer


Git(.gitignore) にはファイルの中身がテキストかバイナリかを判別する方法はないはずです。

個別に指定するのが面倒ということならば、実行ファイルをすべて `bin/` 以下に置くように指定しておけばディレクトリ単位で一括無視ができます。


CC BY-SA 3.0
2015-07-23T06:12:19.160
12604
2015-07-23T06:26:01.887
2015-07-23T06:26:01.887
2391
2391
12591
answer


すべてを無視に指定したあとで、ドットつきのファイルを無視から除外する、というのでどうでしょう。

[code]

    *
    !*.*
    
[/code]


CC BY-SA 3.0
2015-07-23T08:37:36.640
12610
2015-07-23T08:37:36.640
4010
12591
answer


まぁ、 **どうしても** という場合には Git のソースコードを一部変更する事になるのでしょう。

まずは Git のソースコードを取得します。

[code]

    $ git clone https://github.com/git/git
    
[/code]

リポジトリ内のファイルの扱い方を決定しているのは、`git/dir.c` 内の `read_directory_recursive()` 関数です。

[code]

    static enum path_treatment read_directory_recursive(...
                       :
    
        /* add the path to the appropriate result list */
        switch (state) {
        case path_excluded:
          :
            break;
    
        case path_untracked:
          :
    
        default:
            break;
        }
    
[/code]

この `case path_untracked:` ブロックに対象ファイルが実行形式かどうかの判定処理を差し込みます。判定関数の名前を仮に `is_elf`
としておきます。

[code]

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <elf.h>
    
    int is_elf(char *path);
           :
    
    int is_elf(char *path) {
      struct stat statbuf;
    
      stat(path, &statbuf);
      if ( !S_ISREG(statbuf.st_mode) ) {
        return 0;
      }
    
      char *magic = ELFMAG;
      FILE *fp = fopen(path, "r");
      int i; char v;
      for (i=0;i<SELFMAG;i++) {
        fread(&v, sizeof(char), 1, fp);
        if ( v != magic[i] ) break;
      }
      fclose(fp);
    
      return (i == SELFMAG);
    }
    
[/code]

見てもらえば分かると思いますが、 **ELF 形式の通常ファイルかどうか** の判定しか行っていません(実際には magic number の先頭 4
バイトを比較しているだけです)。そのため、他の実行形式を採用している OS では意味のない処理になります。また、Linux 系 OS でも COFF
形式などの実行ファイルには適用できません。したがって、かなり限定的な使用になります。

先程の `read_directory_recursive()` 関数に追加します。

[code]

    switch (state) {
    case path_excluded:
        :
      break;
    
    case path_untracked:
      if (dir->flags & DIR_SHOW_IGNORED)
        break;
    
      // -->
      if (is_elf(path.buf)) {
        dir_add_ignored(dir, path.buf, path.len);
        break;
      }
      // <--
    
      dir_add_name(dir, path.buf, path.len);
      if (cdir.fdir)
        add_untracked(untracked, path.buf + baselen);
      break;
    
    default:
      break;
    }
    
[/code]

変更したソースコードをコンパイル・リンクして git コマンドを作成します(git.patched という名前にします)。以下、簡単な動作確認をしてみます。

[code]

    $ mkdir repo
    $ cd repo
    $ git init
    $ echo $'#include <stdio.h>\nint main() {printf("Hi, World!");return 0;}\n' > hello_world.c
    $ git add hello_world.c
    $ gcc -o hello_world hello_world.c
    $ gcc -o hello_world.static -static hello_world.c
    
[/code]

[code]

    $ git status -s
    A  hello_world.c
    ?? hello_world
    ?? hello_world.static
    
[/code]

実行形式ファイル(ELF形式)が `untracked` として扱われています。

[code]

    $ git.patched status -s
    A  hello_world.c
    !! hello_world
    !! hello_world.static
    
[/code]

`git.patched` では実行形式ファイル(ELF形式)が `ignored` として扱われています。


CC BY-SA 3.0
2015-07-23T12:22:23.010
12624
2015-07-23T12:50:53.420
2015-07-23T12:50:53.420
12591
answer