3

I am trying to ignore all but a single file in a named directory that could be at any depth. So in a structure like this, I want to track any occurrence of build/.gitkeep but ignore all other files in and below build/. The items to track are marked with ++. The items to ignore are marked with --.

    |.gitignore                               ++
    |Makefile                                 ++
    |--build/                                 ++
    |--build/.gitkeep                         ++
    |--build/ignore_any_file                  --
    |--build/ignore_any/dir                   --
    |--foo/                                   ++
    |--foo/file_to_keep                       ++
    |--foo/dir_to_keep/                       ++
    |--foo/dir_to_keep/stuff                  ++
    |--foo/build/                             ++
    |--foo/build/.gitkeep                     ++
    |--foo/build/ignore_any_file              --
    |--foo/build/ignore_any/dir               --
    |--foo/build/ignore_any/dir/subir         --
    |--bar                                    ++
    |--bar/file_to_keep                       ++
    |--bar/dir_to_keep/                       ++
    |--bar/dir_to_keep/stuff                  ++
    |--bar/build/                             ++
    |--bar/build/.gitkeep                     ++
    |--bar/ignore_any_file                    --
    |--bar/ignore_any/dir                     --
    |--bar/ignore_any/dir/subir               --
    |--foobar/foo                             ++
    |--foobar/foo/file_to_keep                ++
    |--foobar/foo/dir_to_keep/                ++
    |--foobar/foo/dir_to_keep/stuff           ++
    |--foobar/foo/build/                      ++
    |--foobar/foo/build/.gitkeep              ++
    |--foobar/foo/build/ignore_any_file       --
    |--foobar/foo/build/ignore_any/dir        --
    |--foobar/foo/build/ignore_any/dir/subir  --

I have tried many, many combinations. The sticking point for me seems to be having build/ at any depth. I am trying to avoid have to create entries for every path where build/ exists. I also don't want to create .gitignore files in every instance of build/.

    $ git --version
    git version 2.20.1
nelsonov
  • 60
  • 6

1 Answers1

5

You should make sure to exlude folders from your ignore rule, if you want then to be able to exclude a file:

build/**
!build/**/
!build/**/.gitkeep

This is because:

It is not possible to re-include a file if a parent directory of that file is excluded

In your case (build at any depth)

**
!**/
!build/.gitkeep
!**/build/.gitkeep

The OP nelsonov made it work (in the comments) with:

build/** 
!build/**/ 
!build/ 
!build/.gitkeep 
!**/build/ 
!**/build/.gitkeep 
**/build/**
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • In your version, I still get build/file and build/dir/ (but not build/dir/file). It looks like I am still getting one layer that I shouldn't. I am familiar with the concept that something can not be re-included after the parent is excluded, but I seem to not be excluding enough. – nelsonov Jun 09 '20 at 06:45
  • @nelsonov OK, what about my second proposal in my edited answer? – VonC Jun 09 '20 at 06:47
  • The results seem the same for me. Here's some examples of files showing up as untracked (that should be ignored): `GatewayESP8266-nrf24/build/file GatewayESP8266-nrf24/build/somedir/ GatewayESP8266-rfm95/build/ mysensors-eeprom/build/EEProm.ino.eep mysensors-eeprom/build/build.options.json mysensors-eeprom/build/core/` – nelsonov Jun 09 '20 at 06:55
  • @nelsonov where is your .gtiignore? I just tested it, and it works perfectly. No lower `build` folders are detected, even if they include a `.gitkeep`. What version of Git are you using? On which OS? – VonC Jun 09 '20 at 07:02
  • git version 2.20.1 on Linux (Rasbian 10 and Debian 10) .gitignore is in the root of git repository To clarify (maybe necessarily) I want to track every instance of `build/.gitkeep` at any depth but ignore anything else in `build/` at any depth. – nelsonov Jun 09 '20 at 07:11
  • @nelsonov OK, my second config tracks `.gitkeeps` only the main `build/` folder, not `.gitkeep ` in any `build/` subfolder – VonC Jun 09 '20 at 07:12
  • Other portions of my .gitignore work as expected: `secrets.h` `build/**` `!build/` `!build/.gitkeep` `*~` `*elf` `*bin` `*hex` I don't know how to get the linebreaks to remain. Please assume they are there. – nelsonov Jun 09 '20 at 07:13
  • I don't know what to do then. I'm still seeing the results indicated above. BTW, there won't be an instance of `build` under `build`, but that's not the important part. I still see `path/build/file` and `path/build/dir/` as untracked. It does ignore `path/build/dir/anything` The whole point of the ,gitkeeps, btw, is just to keep otherwise empty `build/` and `path/build` for templating. – nelsonov Jun 09 '20 at 07:24
  • @nelsonov `BTW, there won't be an instance of build under build`: OK I have fixed that in my latest edit. But try and check what is and is not ignore with `git check-ignore -v -- a/file`. And, if possible, upgrade to Gti 2.27. – VonC Jun 09 '20 at 07:28
  • @nelsonov I have edited further the rules at the end of the answer: Give it another try. – VonC Jun 09 '20 at 07:31
  • This is what ended up working for me: `build/** !build/**/ !build/ !build/.gitkeep !**/build/ !**/build/.gitkeep **/build/** ` Do you want to update you answer or would you prefer to keep it as is? I wouldn't have gotten here without you. – nelsonov Jun 09 '20 at 07:44
  • @nelsonov Thank you for the feedback: I have included your comment in the answer for more visibility. – VonC Jun 09 '20 at 07:48