I am converting my Mercurial repository to Git. Part of the file system looks like this:
|-- .gitignore
|-- .hgignore
`-- var
|-- .dummy
|-- asdf
`-- log
|-- .dummy
`-- asdf
My .hgignore file uses regular expressions. Part of my .hgignore file is as follows:
^var/(?!\log|.dummy)
^var/log/(?!\.dummy)
I want to track the .dummy
files but not the asdf
files. hg status
returns:
? var/.dummy
? var/log/.dummy
How can I get the same effect in .gitignore? I have tried the following:
/var/**/*
!/var/.dummy
!/var/log/.dummy
But this will not ignore var/asdf
as desired. How can I track var/.dummy
and var/log/.dummy
and ignore var/asdf
and var/log/asdf
?
If you are only using the .dummy
files as placeholders to make sure that you always get those particular (nearly empty) directories when you make a clean checkout, then you should probably just exclude /var
and use git add -f var/.dummy var/log/.dummy
to start explicitly tracking the placeholder files. The effective result is that you will ignore everything except the .dummy
files that you explicitly tracked.
On the other hand, if you plan on expanding the hierarchy of nearly empty directories beyond just var/log
, then you might be able to make use of a bit of explanation.
The rules are described in gitignore(5), but sometimes it is difficult to make sense of all the rules and how they interact. The important part is that the last rule wins, and that later rules can only be effective if the directories they act on are not already wholly ignored. This means that you if you have ignored directories, you have to unignore them before you can unignore a bit of their contents (while re-ignoring the rest of their contents).
If you want to automatically ignore everything except .dummy
files under var
, then the simplest way of doing this involves putting a .gitignore
file in your var
directory instead of doing it at the top level. I described this solution in another SO answer.
# var/.gitignore
*
!/.gitignore
!.dummy
!*/
var
).git add -f
to start tracking this .gitignore
file)..dummy
files at any depth in the hierarchy rooted at this directory (var
).var
)..dummy
files.The last two patterns are “recursive” because they do not have a non-trailing slash (meaning that *
will match slashes in addition to other characters). A trailing slash makes the pattern match only directories. Leading and embedded slashes effectively anchor the pattern to the location of the .gitignore
file (or the root of the repository for patterns from other exclude files). The idea is that a plain *.o
should match anywhere, but dir/*.o
should only match items directly under dir
(and we can use /*.o
for this latter effect in dir/.gitignore
).
If you can not tolerate a var/.gitinore
file, then you can still do what you asked, but you can not automatically “unignore” new .dummy
files anywhere under var
without editing the exclude patterns.
# .gitignore at root of repository
/var/*
!/var/.dummy
!/var/log/
/var/log/*
!/var/log/.dummy
var
directory that is a sibling of this .gitignore
file.var/.dummy
.var/log
.var/log
.var/log/.dummy
.The pattern is: unignore an interesting directory (skip this the first time, since everything is “unignored” by default), ignore what is in the directory, unignore the .dummy
file in it. Repeat the pattern for each deeper part of the hierarchy.
You can replace log
with *
to make it work for any directory directly under var
, but it will not automatically work for directories that are deeper (e.g. it would work for var/cache/.dummy
, but not for var/log/ssh/.dummy
). This is because we are using non-trailing slashes and anchor the patterns. To manually make it work, you have to repeat the pattern to generate more exclusion rules for the deeper parts (unignore interesting dir, ignore contents of dir, unignore file).
You don't need to exclude .dummy
with regex. Just ignore everything and manually add then all your .dummy
.
Ignore affects only on the status command result.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With