explain gitignore pattern matching - regex

I have the following directory tree:
> #pwd is the repo
> tree -a
.
├── .git
│   |.....
├── .gitignore
├── README.md
├── f1.html
├── f2.html ... and some more html
├── images
│   └── river.jpg
>
I also have the following in my .gitignore:
> cat .gitignore
*
!*.html
!images/*.*
>
I would like all files in the images directory to be included in the repo. But that is not happening. I got it to work using the following in gitignore:
*
!*.html
!images*
!*.jp*g
What is happening here? Is there a foolproof way to test gitignore. I checked the documentation. Here is the point it don't understand (this is under pattern format heading):
Otherwise, Git treats the pattern as a shell glob suitable for
consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the
pattern will not match a / in the pathname. For example,
"Documentation/*.html" matches "Documentation/git.html" but not
"Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html".

Firstly the tricky part in your question is the first line in the .gitignore file:
* // Says exclude each and every file in the repository,
// unless I specify with ! pattern explicitly to consider it
First we will consider the first version of your .gitignore.
* exclude every file in the repository.
!*.html allow all html files.
!images/*.* consider all types of file in images folder.
To include all JPG/JPEG you could have simply added !*.jp*g at 3rd line, which would have made git to consider all jpg and jpeg irrespective of any folder where that file is. But you specifically wanted only from images folder and not only jpg, any type of file in the images folder. Let's read some documentation related to it and in 3rd section we will go to solution part.
Git ignore pattern regarding the folder consideration:
Pattern ending only with slash: If a pattern ends with <dir-name>/ then git will ignore the files contained in that directory and all other sub-directories. As example given in the docs
foo/ will match a directory foo and paths underneath it, but will not
match a regular file or a symbolic link foo
but also note, if any pattern matches a file in the excluded directory, git doesn’t consider it.
Pattern does not have slash: If you are specifying the dir name in the ignore list which does not end with a slash, git will consider it as just a pattern, which can match any file having that pathname.
If the pattern does not contain a slash /, Git treats it as a shell
glob pattern and checks for a match against the pathname relative to
the location
Pattern with slash and special character (*/?) : If the pattern ends like the 1st example you gave, images/*.* It works as specified in the documentation
Example: "Documentation/*.html" matches "Documentation/git.html" but not
"Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html".
Solution
Considering 3rd point git should consider all the files in the images directory for !images/*.* pattern. But it is not doing that because the documentation says one more important point
Git doesn’t list excluded directories
Because of the first line * the "images" directory itself is ignored. So first we should tell the git to consider images directory and later additional lines explicitly to say consider the other types (if needed).
*
!*.html
!images/ // <- consider images folder
!images/*.*
Note : the last line considers all types of files only from images directory not from any of its sub-directories. (3rd point in section 2)

Related

Git - Ignore directories based on their contents

Using .gitignore, is there a way to ignore a directory if it contains a certain file (or directory)?
This would be something like look-ahead assertions, though my use case is a little different: I want to ignore Mercurial repos in my project, to keep from accidentally committing them as part of the project. That is, I want to ignore all directories containing .hg, not just .hg itself.
I can work around this using the answer from this question, adding each directory name to .gitignore, but I'd like to make it more general if I can.
There is no way to do it beside adding all of them to your .gitignore file.
What you can do it to write a scipt which append all the desired paths to your .gitignore.
The content of .gitignore is alist of paths so git can be configured based upon content.
Each line in a gitignore file specifies a pattern

More convention examples

I've been trying to get my head around the Brunch conventions configuration – my lack of comprehension is more than likely due to my lack of experience/knowledge in the world of regex.
It would be great to see an example of how to change the default build location of specific files in the assets/ folder.
A use case
I want to move only the HTML pages to a folder that isn't the public folder. Here's my current folder setup:
app
assets
_inc
header.html
footer.html
...
_layouts
main.html
404.html
...
styles
main.scss
..
node_modules
public
craft
templates
In this case I'd like to move all the HTML files: assets/**/*.html (in glob parlance) to the craft/templates folder.
Any advice, tips, etc would be excellent!
Please & thank you!
In my opinion, you just need to loop through all files in your current folder, use a regex like assets\/.*\/*\.html to search for a match. If match is found, then move to the folder of your choice (i.e, craft/templates).
Here is the regex demo.

File name pattern for ignore files in Mercurial

I use TortoiseHg and I have folders structure, as below:
testSet1
test1
filesystem
input_1.obj
output_1.obj
etalon_1.obj
result_1.obj
test2
filesystem
input_1.obj
output_1.obj
etalon_1.obj
result_1.obj
......
errors.txt
......
result.xml
I need to ignore only .obj files located in directories "testSetN/testN", but not in directories "testSetN/testN/filesystem".
I use glob pattern "*/*/*.obj" in .hgignore, but it doesn't work. Mercurial just ignores all .obj files in all directories (including "filesystem" directory). But if I use, for example, "testSet1/*/*.obj", then everything works fine. How can I do what I need?
It's not necessary for me to use only glob syntax. I would be grateful for any way.
Looking at https://www.selenic.com/mercurial/hgignore.5.html#syntax
Neither glob nor regexp patterns are rooted. A glob-syntax pattern of the form *.c will match a file ending in .c in any directory, and a regexp pattern of the form .c$ will do the same. To root a regexp pattern, start it with ^.
According to this, the glob */*/*.obj will match .obj files inside the filesystem directory, because the glob is not rooted. So it matches those files by rooting the glob at testSetN/
If you have the prefix of testSet on all folders, you can use the glob testSet*/*/*.obj. This way, it will ignore .obj files in a subdirectory of a directory that begins with testSet. - it would also ignore a/testSetX/testY/Z.obj as well as testSetN/testN/N.obj
Mercurial will also let you manually add files that would otherwise be ignored according to .hgignore, so you could simply ignore all .obj files, or use your original glob of */*/*.obj and hg add the files you want to track.
Edit: adding regex as discussed in the comments.
If you prefer regex, or don't have a pattern to root the glob at, you need to use a regex. The regex ^[^/]*/[^/]*/[^/]*\.obj$ to match any .obj file at exactly two levels from the repository root. That is:
^ to anchor the match at the root of the repository
[^/]*/ to match any first-level directory. That is any sequence of characters that does not contain the directory separator /
[^/]*/ again, to match any second-level directory.
[^/]*\.obj$ to match any filenames that end with .obj

Delete only directories in maven

I am Using maven to create a war file
my folder <app> contains folder1 folder2 file1 ..
i want to get only file1
I have tried with the following..
<packagingExcludes>app/*/*.js</packagingExcludes>
any help here
The configuration is correct but the regex looks different.We use ** to indicate multiple directories and * to indicate an optional part of a file or directory name, as mentioned here. If I am not wrong, your regex looks like excluding all .js files in all folders of app, which is different from your requirement

.gitignore regex for emacs temporary files

I'm trying to .gitignore emacs temporary/autosave files. I'm using...
\.\#.*
in my .gitignore.
But git add -A run in a subfolder is still giving me:
# new file: .#make_collections.py
# new file: .#norm_collections.py
# new file: make_collections.py
# new file: norm_collections.py
even though
\.\#.*
is clearly getting the right file names and not the wrong ones when I test it with a regex tester.
You can also instruct emacs to save the autosave files in a different directory altogether by setting the variable auto-save-file-name-transforms, I have this in my init file
(setq auto-save-file-name-transforms
`((".*" ,(concat user-emacs-directory "auto-save/") t)))
This instructs emacs to store the auto-saves inside the auto-save folder in the user-emacs-directory (usually ~/.emacs.d).
To save backup files in a different directory set the variable backup-directory-alist, the following will save backup files inside backups folder in the user-emacs-directory
(setq backup-directory-alist
`(("." . ,(expand-file-name
(concat user-emacs-directory "backups")))))
gitignore doesn't use regular expressions. Instead it uses shell glob patters. The man page tells you two things important for this situation:
Otherwise, Git treats the pattern as a shell glob suitable for
consumption by fnmatch(3) with the FNM_PATHNAME flag.
and
A line starting with # serves as a comment. Put a backslash ("\")
in front of the first hash for patterns that begin with a hash.
This means that the pattern you want to use is simply .#*.
Now the second pattern that matov mentioned, #*, doesn't do anything as it is treated as a comment by git. Hence me quoting that second sentence from the man page.
Emacs autosave files are ignored with
\#*#
files are ignored with:
\#*\#
.\#*
If you want an easy way to ignore files, you can also use http://www.gitignore.io which helps create useful .gitignore files for your project.
Here is the emacs template: https://www.gitignore.io/api/emacs
There is also documentation demonstrating how to run gi from the command line.
To suppress the temporary Emacs files appearing on git status globally, you can do the following:
Configure git to use a global excludesfile
Since this is a common problem, git has a specific solution to that:
Patterns which a user wants Git to ignore in all situations (e.g., backup or temporary files generated by the user’s editor of choice) generally go into a file specified by core.excludesFile in the user’s ~/.gitconfig
git config --global core.excludesfile ~/.gitignore_global
Create the respective file
cd
touch .gitignore_global
Paste the following template into the file
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
dist/
# Flycheck
flycheck_*.el
# server auth directory
/server/
# projectiles files
.projectile
# directory configuration
.dir-locals.el
# network security
/network-security.data
Watch git do its magic! :)