Much ado about .gitignore

satya - 4/18/2018, 5:00:20 PM

Reference on gitignore

Reference on 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:24:00 PM

What is $git_dir

What is $git_dir

Search for: What is $git_dir

satya - 4/18/2018, 5:27:41 PM

Here is some relevant info on SOF

Here is some relevant info on SOF

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

Search for: .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

Search for: .gitignore patterns a simple guide

satya - 7/15/2020, 1:35:03 PM

Some examples for atlassian

Some examples for atlassian

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

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, 1:54:29 PM

gitignore repo on github

gitignore repo on github

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:00:46 PM

Read this as well

Read this as well

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

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/15/2020, 11:21:18 PM

Some discussion on double *

Some discussion on double *

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:11:31 PM

2.A running journal on .gitignore

2.A running journal on .gitignore

satya - 7/18/2020, 1:12:05 PM

3. Reference on gitignore at git

3. Reference on gitignore at git

satya - 7/18/2020, 1:12:38 PM

4. An Atlassian article

4. An Atlassian article

satya - 7/18/2020, 1:13:21 PM

5. A Pluralinsight article

5. A Pluralinsight article

satya - 7/18/2020, 1:13:57 PM

6. An SOF discussion

6. An SOF discussion

satya - 7/18/2020, 1:15:24 PM

7. A repo for gitignore samples

7. A repo for gitignore samples

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