Much ado about .gitignore
satya - 4/18/2018, 5:00:30 PM
Ignore the files in a directory from tracking them
Ignore the files in a directory from tracking them
satya - 4/18/2018, 5:00:58 PM
Ignore one file among many in a directory
/aspire_jsdk23.jar
satya - 4/18/2018, 5:01:36 PM
Ignore multiple sub directories
/META-INF/
/com/
satya - 4/18/2018, 5:02:04 PM
.gitignore file itself is tracked and part of the commit
.gitignore file itself is tracked and part of the commit
satya - 4/18/2018, 5:28:29 PM
$Git_dir from the SOF article above
Note on $GIT_DIR: This is a notation used all over the git manual simply to indicate the path to the git repository. If the environment variable is set, then it will override the location of whichever repo you're in, which probably isn't what you want.
satya - 7/24/2018, 8:57:28 AM
.gitignore samples for java
.gitignore samples for java
satya - 10/19/2019, 6:22:27 PM
You can use a staging directory in git like this
# Ignore all files and sub directories
# in this sub directory
# except the .gitignore file
/**
!.gitignore
# Such a directory is useful for holding
# local temporary processed files.
satya - 7/15/2020, 12:23:05 PM
How to ignore all directories with a certain name in gitignore
How to ignore all directories with a certain name in gitignore
Search for: How to ignore all directories with a certain name in gitignore
satya - 7/15/2020, 1:32:19 PM
.gitignore patterns a simple guide
.gitignore patterns a simple guide
satya - 7/15/2020, 1:36:31 PM
Placement of .gitignore
Name: .gitignore
usually: in the root folder (recommended)
Can be: placed in sub directories as well
satya - 7/15/2020, 1:37:25 PM
This is a link from Plural insight: Seem better
satya - 7/15/2020, 1:54:11 PM
Some hints
#ignore any file or directory with this name
abc.txt
#ignore any file or sub directory
#file can be anywhere in the subdirectory structure
xyz
#Only if any sub directory matches this name
bin/
satya - 7/15/2020, 2:14:32 PM
A dot (.) has no special meaning
A dot (.) has no special meaning
satya - 7/15/2020, 2:17:26 PM
A * matches anything except a slash
*xyz*
#a directory match in the hierarchy
/abc/dddxyzbbb/a.log #a match
#a file match in the hierarchy
/abc/xyz.log #a match
#Match only sub directories ending in xyz
#not files
*xyz/
satya - 7/15/2020, 2:18:12 PM
** means a set of subdirectories: I think
** means a set of subdirectories: I think
satya - 7/15/2020, 2:18:46 PM
A name by itself matches a directory or filename anywhere in the hierarchy
A name by itself matches a directory or filename anywhere in the hierarchy
satya - 7/15/2020, 2:20:43 PM
So few often useful patterns
So few often useful patterns
satya - 7/15/2020, 2:24:07 PM
Ignore any name directory anywhere in the hierarchy
#Directory anywhere
abc #any file or sub dir
abc\ #only any sub dir
#Sub directory
\abc #file or dir
\abc\ #only dir
satya - 7/15/2020, 2:26:13 PM
some examples: ignore any directory named "bin"
bin/
satya - 7/15/2020, 2:27:52 PM
Ignore any file named ".jar" anywhere in the hierarchy
*.jar
satya - 7/15/2020, 2:32:42 PM
Few example from a pthon repo
#Any sub directory named this way
__pycache__/
#Ignore these file extensions anywhere .pyc, .pyo, .pyd
#No special meaning to "." also "*" means any thing
*.py[cod]
#any file with this pattern. $ has no meaning
*$py.class
satya - 7/15/2020, 2:35:10 PM
More....
#File or dir anywhere
# "." has no meaning
.Python
#Any sub dir named build
build/
develop-eggs/
dist/
#Any sub directory that ends in ".egg-info"
*.egg-info/
#Any file or sub directory named like this
.installed.cfg
#Any file or sub dir ending in ".egg"
*.egg
#Any file or subdirectory anywhere
MANIFEST
satya - 7/15/2020, 2:38:17 PM
More ....
#Any depth sub directory that has "docs" as its parent
docs/_build/
# any sub dir named target
target/
# Any file or sub dir: for Jupyter Notebook
# usually it is a sub dir
# i suspect placing a / at the end would work as well
.ipynb_checkpoints
# file or directory anywhere
.python-version
satya - 7/15/2020, 3:02:14 PM
I may be wrong on docs/build/ ...
1. Behavior seem to be different if there is an "embedded" "/" in the path.
2. vs the "/" only at the end
satya - 7/15/2020, 11:02:59 PM
The "/" behaves differently where it is at: begin, middle, end
The slash / is used as the directory separator. Separators may occur at the beginning, middle or end of the .gitignore search pattern.
If there is a separator at the beginning or middle (or both) of the pattern, then the pattern is relative to the directory level of the particular .gitignore file itself. Otherwise the pattern may also match at any level below the .gitignore level.
If there is a separator at the end of the pattern then the pattern will only match directories, otherwise the pattern can match both files and directories.
For example, a pattern doc/frotz/ matches doc/frotz directory, but not a/doc/frotz directory; however frotz/ matches frotz and a/frotz that is a directory (all paths are relative from the .gitignore file).
satya - 7/15/2020, 11:04:38 PM
See this URL to understand it better
satya - 7/15/2020, 11:07:49 PM
Beginning or middle only matches the named sub directories
dir1/dir2/
will only match
/dir1/dir2
but not
/a/b/c/dir1/dir2
satya - 7/15/2020, 11:08:54 PM
But the one at the end....
dir2/
will match
/dir2
/dir1/dir2
/a/b/c/dir2
satya - 7/15/2020, 11:13:59 PM
Now the "**" makes sense to use
foo/bar
will only match
/foo/bar
will not match
/a/b/foo/bar
For that to match you have to do
**/foo/bar
at any depth will match
/a/b/foo/bar
/foo/bar
/x/foo/bar
etc..
satya - 7/15/2020, 11:14:24 PM
Essentially that is one way to locate any "sub trees" to ignore
Essentially that is one way to locate any "sub trees" to ignore
satya - 7/16/2020, 9:44:50 AM
How to assemble work: TOC
What is obvious
Obvious patterns
What is not obvious
Not so obvious patterns
Role of /
Role of **
Role of *
What is unclear to me yet
References
At Git
Article 1
Art 2
SOF
gitignore at github
Aggregated examples
satya - 7/17/2020, 12:52:00 PM
Experimenting with *, */, /*, /**: Interesting and behaves as expected
#
# Hello this is a sample .gitignore file
#
# ******************************************
# Understand: * (ig: Any file or directory at any depth):
# Result: Hide all
# ******************************************
# Lets try with */ (a directory approach)
# Only files under directories are hidden
#
# Lets see what happens a * is in the root
# Seem to block all files and directories including .gitignore
#*
# ******************************************
# Understand: */ (ig: Any directory at any depth)
# Result: Only root files show
# ******************************************
# Lets try with */ (a directory approach)
# Only files under directories are hidden
# Because all directories are ignored, only root files show
# when a directory is ignored all its children are ignored
#*/
# ******************************************
# Understand: /** (Actual directive to ignore this directory and all below)
# Result: as expected
# ******************************************
# Meanning: Hide all sub directories including this one
# Hide this directory and everything underneath
# Similar behavior as *
#/**
# ******************************************
# Understand: /*
# ******************************************
# Lets see a relative path with a /*
# Any Directory or a file name in the root
#
# Children directory behavior (as expected)
# ******************************************
# 1. First level directories are hidden
# 2. First level files are hidden
# 3. Because of 1 all sub directories and their files are hidden as well
#
# Similar behavior as: *, /*, /**
#
# *******************************************
# /*
satya - 7/18/2020, 7:54:59 AM
Real Simple things First
1. The filename for git ignore is: .gitignore
2. Look for or create this file at the root of the git repo
3. This file can also exist for each sub directory as well
satya - 7/18/2020, 7:56:51 AM
Convention for placement of .gitignore, however is at the root
1. Many many things can be done by having just one file at the root
2. So convention is to control most of the behavior from the one under the root
3. One does not need specialize at a sub directory level often
satya - 7/18/2020, 8:01:29 AM
The confusion about the rules of the .gitignore
1. The rules of the .git ignore can get very confusing.
2. However the simple things are kept simple
3. I will provide the URL where these rules are documented in the References section below
4. There are also some rules that are short cuts and often used
5. It took me a few days to fully understand MOST rules
6. I will also point out what I am still not too clear, if they remain at the end
satya - 7/18/2020, 8:02:46 AM
Lets get to the easiest rules to understand first
Lets get to the easiest rules to understand first
satya - 7/18/2020, 8:05:28 AM
1. Ignore a specific file either at the root or a deeper in the hierarchy
# This is a comment line
#ignore a file a.txt at the root
/a.txt
#ignore a deeper file
/dir1/dir2/a.obj
#you can obviously have empty lines
satya - 7/18/2020, 8:10:27 AM
2. The "/" at the beginning is mandatory for relative addressing of the file
1. If this "/" is at the beginning the pattern can be interpreted differently. Later on this.
2. Same with "/" at the middle of a pattern
3. So the "/", as you will soon find has some special treatment
4. For now it is sufficient to know that for a relative path start with a "/"
satya - 7/18/2020, 8:15:33 AM
3. Ignore a specific relative directory and all its sub directories
# ignore this directory and all its sub directories
/dir1/
# deeper tree
/dir1/dir2/
/dir1/dir3/
etc...
satya - 7/18/2020, 8:18:04 AM
4. The last "/" has a meaning here
1. In "/dir1/" if the trailing "/" is eliminated then "dir1" refers to either a directory or a filename, both
2. So by placing a trailing "/" one forces ignoring only directory with this name.
satya - 7/18/2020, 8:20:07 AM
5. So "/dir1/" behavior
# consider this
/dir1/
# This would allow a filename
/dir1
# as long as there is such a filename
satya - 7/18/2020, 8:27:37 AM
6. Enter the "*" and it works like its role in a relative path spec
1. There is no special meaning in the context of gitignore
2. Like in a path, it represents multiple files that matches the pattern. it plays the same role here.
satya - 7/18/2020, 8:29:14 AM
7. Revisiting ignoring a specific set of of files (plural)
# ignore all root level files starting with name "test"
/test*
# or
/dir1/test*.txt
satya - 7/18/2020, 8:34:40 AM
8. Ignoring a specific set of directories (multiple)
# ignore directories that match these patterns
# ignore all directories at the root that start
# with testdir-
/testdir-*/
# Notice the trailing "/"
# it tells that this applies only directories and not files
/a/b/dir*xys*/
satya - 7/18/2020, 8:37:50 AM
9. This allows files but not directories
#Ignore directories under /dir1 starting with test
/dir1/test*/
#However this will allow the following
/dir1/test.txt
/dir1/test4.txt
# not allowed are
/dir1/testdir
/dir1/test4dir
satya - 7/18/2020, 8:46:33 AM
10. Summarizing what is obvious
1. Ignoring relative paths are pretty straight forward and few surprises.
2. They do have to start with "/" even though they are relative
3. You can use "*" for pattern matching
4. The "*" doesn't cross boundaries of directory separators "/"
satya - 7/18/2020, 8:47:22 AM
Slightly less obvious rules
Slightly less obvious rules
satya - 7/18/2020, 9:20:19 AM
1. There are two
1. Placement of "/" in a path
2. Files vs Directories based on a path
satya - 7/18/2020, 9:24:28 AM
2. Placement of "/" at the beginning or middle makes a path relative
# The following is not relative
# this pattern has a special meaning. will cover later
dir1
# This is NOT realative either
dir1/
#make this relative: / at the beginning
/dir1
#relative as well
/dir1/dir2
#the following is relative: / at the middle
dir1/dir2
dir1/a.txt
satya - 7/18/2020, 9:27:11 AM
3. Placement of "/" at the end indicates a directory vs a file
/dir1
#dir1 above can be a file or a directory
#force a directory with a trailing "/"
#So the following only applies to a directory
/dir1/
satya - 7/18/2020, 9:27:37 AM
4. "/" at the end almost always says the preceding spec is a directory spec
4. "/" at the end almost always says the preceding spec is a directory spec
satya - 7/18/2020, 9:30:04 AM
5. So summarizing slightly less obvious rules
1. For a path to be relative there must be a "/" at the beginning or in the middle of a path
2. The "/" at the end indicates that the spec applies only to directory and not files
3. Eliminating the trailing "/" means the entire namespace (file or directory) is not allowed in that relative path
satya - 7/18/2020, 9:31:02 AM
Shortcuts: The most used rules in gitignore
I will now move on to the most seen rules in a gitignore file.
satya - 7/18/2020, 9:35:43 AM
1. These are
1. A spec with no interrupting (beginning or middle) "/" has a special meaning
2. Such a spec applies to anywhere in the hierarchy of directories
3. Spec does allow "*" to generalize the spec
4. The trailing "/" is allowed and retains its meaning of files vs directories or both
satya - 7/18/2020, 11:55:04 AM
2. Please ignore any file or directory anywhere in the repo that is named "xyz"
# No file or directory anywhere named "xys" is ignored
xyz
what does it mean in gitignore? It means, do not allow any where in the repo a directory or a file that is named "xyz"
satya - 7/18/2020, 11:57:34 AM
3. Examples of ignoring files or dirs anywhere
#All of the following files and directories are ignored
/dir1/xyz #where xyz is a file is ignored
/dir2/dir3/xyz #where xyz is a directory
/xyz #where xyz is a directory
satya - 7/18/2020, 11:59:45 AM
4. Pattern for ignoring directories (only) any where
# The following ignores directories anywhere
# file are allowed with that name
xyz/
#Notice the LACK OF BEGINNING "/"
satya - 7/18/2020, 12:01:09 PM
5. Examples
/dir1/xyz #where xyz is a file so it is allowed
/dir2/dir3/xyz #where xyz is a directory so it is ignored
/xyz #where xyz is a directory so it is ignored
satya - 7/18/2020, 12:04:28 PM
6. Introducing the "*" into the anywhere shortcut rules
# Ignore File or a directory anywhere whose name
# starts with "xyz"
xyz*
# Ignore all files anywhere with this extension
*.obj
# Ignore all directories (not files)
# with this kind of name anywhere.
.profile/
satya - 7/18/2020, 12:05:46 PM
7. This is the most often used pattern
1. So this is the most often used pattern
2. which is, ignoring files or directories anywhere in the hierarchy based on a name (and not relative path)
satya - 7/18/2020, 12:09:58 PM
8. Remember, this is not an anywhere spec "abc/testdir/"
# Consider this line in gitignore
abc/testdir/
# it may look like an anywhere spec
# because it has no beginning "/"
#But it is not.
# Because it lacks the criteria that
# there cannot be a "/" interrupting the name
# as in this case in the middle.
satya - 7/18/2020, 12:11:24 PM
9. Summarizing the most used Shortcut rules: anywhere specs
1. A spec with no interrupting (beginning or middle) "/" has a special meaning
2. Such a spec applies to anywhere in the hierarchy of directories
3. Spec does allow "*" to generalize the spec
4. The trailing "/" is allowed and retains its meaning of files vs directories or both
5. This pattern is the most used in .gitignore files, you will find.
satya - 7/18/2020, 12:18:45 PM
10. Implications of "/"
1. You can ignore files and directories (no trailing "/")
2. You can ignore directories only but allow files (trailing "/")
3. You cannot allow directories while ignoring files
4. so if you ignore files, directories are automatically ignored.
satya - 7/18/2020, 12:22:01 PM
Really specialized rules: Clearly not obvious
There are some rules involving "**" that are really not obvious and sometimes have overlapping effects with the previous rules. These are
1. "**" at the beginning of a line
2. "**" at the end
3. "**" in the middle
satya - 7/18/2020, 12:35:50 PM
1. How do you avoid a sub tree that looks like "/foo/bar" anywhere?
# if it is at the root you can say
/foo/bar/
# Or
/foo/bar
# Or
foo/bar
#But what if you want to avoid
/foo/bar
/dir1/dir2/foo/bar
/dir1/foo/bar
# but allow the directory "bar" when it appears by itself
# with out preceding by "foo"
/bar
/dir1/dir2/bar
/dir1/bar
satya - 7/18/2020, 12:37:32 PM
2. This is done by saying "**/foo/bar/"
# you can avoid the tree /foo/bar anywhere
# by indicating
**/foo/bar
# the "**" must be at the beginning
# No "/" is at the front to note
satya - 7/18/2020, 12:40:56 PM
3. "**" in the middle reads "any number of sub directories"
/dir1/**/foo/bar/
# This means
# Any number of sub directories under "dir1"
#So this avoids
/dir1/a/foo/bar
/dir1/b/foo/bar
/dir1/a/b/foo/bar
/dir1/a/b/c/foo/bar
satya - 7/18/2020, 12:43:04 PM
5. "**" at the end has a different meaning
/dir1/**
# This means
# ignore everything under the relative /dir1 to any depth
satya - 7/18/2020, 12:43:54 PM
6. So "/**" means ignore this directory and everything underneath
/**
# means ignore this directory and
# everything underneath
satya - 7/18/2020, 12:56:32 PM
Summarizing the really specialized rules involving "**"
1. "**" at the beginning of a line ignores the following directory hierarchy anywhere in the repo. So "**/foo/bar" ignores "/foo/bar" anywhere.
2. "**" at the end means ignore all sub directories. So "/foo/**" is same as "/foo/".
3. "**" in the middle like "/dir1/**/foo/bar" means any sub directory depth after "/dir1" but followed by "/foo/bar"
satya - 7/18/2020, 1:03:44 PM
8. Now Understanding similarities in *, */, /*, /**
# ******************************************
# Understand: * (ig: Any file or directory at any depth):
# Result: Hide all
# ******************************************
# Lets see what happens a * is in the root gitignore
# Seem to block all files and directories including .gitignore
# Because its instruction is
# "ignore anything with this pattern anywhere file or dir")
*
# ******************************************
# Understand: */ (ig: Any directory at any depth)
# Result: Only root files show
# ******************************************
# Because all directories are ignored, only root files show
# when a directory is ignored all its children are ignored
*/
# ******************************************
# Understand: /** (Actual directive to ignore this directory and all below)
# Result: Hides all as expected
# ******************************************
# Meanning: Hide all sub directories including this one
# Hide this directory and everything underneath
# Similar behavior as *
/**
# ******************************************
# Understand: /* (Ignore immediate files or directories under the root)
# Result: Hides all again
# ******************************************
# 1. First level directories are hidden
# 2. First level files are hidden
# 3. Because of 1 all sub directories and their files are hidden as well
#
# Similar behavior as: *, /*, /**
#
# *******************************************
/*
satya - 7/18/2020, 1:09:51 PM
Key References
Key References
satya - 7/18/2020, 1:10:10 PM
1. An article on Linked In:Curious experiment with \*, \*/, /\*, /\*/, and /\*\* in .gitignore
1. An article on Linked In:Curious experiment with \*, \*/, /\*, /\*/, and /\*\* in .gitignore
satya - 7/18/2020, 1:16:09 PM
8. A Git Repo to experiment with .gitignore with instructions
8. A Git Repo to experiment with .gitignore with instructions
satya - 9/19/2024, 12:28:14 PM
Ignoring any temporary office files
satya - 9/19/2024, 12:31:14 PM
Suggestions by Copilot
#
# Avoid office backup files
# They start with ~
# ~* means ignore all files that start with ~ anywhere in the directory or sub directories
# ~$* means ignore all files that start with ~$ anywhere in the directory or sub directories
#
# The pattern for office backup files is:~$*
#
# ~$ seem to be the starting pattern for office backup files
# I will leave for now the ~* pattern
#
~*
~$*
*.tmp
*.~*