Skip to content

Commit cb32250

Browse files
committed
git-ignore.sh: Adding git-ignore command
The 'git ignore' command modifies a .gitignore file in your path easily. By default, it adds lines to the .gitignore found in the root of your repository. It can, however, add lines to a gitignore anywhere inbetween the file(s) passed in and the root of the repository. The lines added to the gitignore can be based on filename, extension, directory, or recursive glob. Also, you can easily open the gitignore file using your $EDITOR with 'git ignore --edit'. This can make things much easier when ignore files in subdirectories. No longer will you have to run: echo "path/to/the/file.txt" >../../../../../../.gitignore instead: git ignore file.txt Signed-off-by: Thurston Stone <[email protected]>
1 parent b697d92 commit cb32250

File tree

5 files changed

+514
-0
lines changed

5 files changed

+514
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
/git-http-backend
7777
/git-http-fetch
7878
/git-http-push
79+
/git-ignore
7980
/git-imap-send
8081
/git-index-pack
8182
/git-init

Documentation/git-ignore.txt

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
git-ignore(1)
2+
=============
3+
4+
NAME
5+
----
6+
git-ignore - Easily add entries to your .gitignore file
7+
8+
9+
SYNOPSIS
10+
--------
11+
[verse]
12+
'git ignore' [--dry-run | -n] [--ext | -e] [--all-ext | -E] [--dir | -d]
13+
[--all-file | -a] [--parent-level | -p <parent_level>] pathspec [...]
14+
'git ignore' --edit [--parent-level | -p <parent_level>]
15+
16+
17+
DESCRIPTION
18+
-----------
19+
The command modifies a .gitignore file in your path easily. By default,
20+
it adds lines to the .gitignore found in the root of your path. It
21+
can, however, add lines to a gitignore anywhere inbetween the file(s)
22+
passed in and the root directory. The lines added can be based on
23+
filename, extension, directory, or recursive glob.
24+
25+
Also, you can easily open the gitignore file using your $EDITOR.
26+
27+
28+
OPTIONS
29+
-------
30+
<pathspec>...::
31+
Files to add to a gitignore. Fileglobs (e.g. `*.c`) can
32+
be given to add all matching files. Also a
33+
directory name can be given to add it to the gitignore
34+
as well.
35+
36+
--edit::
37+
Open the appropriate gitignore file in your default editor (using the
38+
$EDITOR variable. This option can be combined with `--parent-level` based
39+
on your current working directory.
40+
41+
-n::
42+
--dry-run::
43+
Don't actually edit the gitignore(s), just show if what changes
44+
would have taken place.
45+
46+
-e::
47+
--ext::
48+
Add the relative filepath based on extension. If pathspec
49+
references path/to/file.log, the added gitignore line would
50+
be path/to/*.log.
51+
52+
-E::
53+
--all-ext::
54+
Add a global exclusion of the given extension. If pathspec
55+
references path/to/file.log, the added gitignore line would
56+
be **/*.log.
57+
58+
-d::
59+
--dir::
60+
Add the contents of the parent directory. If pathspec references
61+
path/to/file.log, the added gitignore line would be path/to/*.
62+
63+
-a::
64+
--all-file::
65+
Add a global exclusion of the given filename. If pathspec references
66+
path/to/file.log, the added gitignore line would be **/file.log.
67+
'git ignore' [--dry-run | -n] [--ext | -e] [--all-ext | -E] [--dir | -d]
68+
[--all-file | -a] [--parent-level | -p] pathspec [...]
69+
70+
-p::
71+
--parent-level <parent_level>::
72+
Modifications will go to a gitignore located <parent_level>
73+
directories above each of the files passed in. If the number
74+
of parent levels causes the directory to fall outside of the
75+
root of the git repository, a warning is printed and the root
76+
of the repository is used instead. Using a parent-level of 0
77+
will use the gitignore in the directory of each file passed in.
78+
79+
+
80+
Note that the parent level is calculated for each file passed in. If multiple
81+
files are passed in that have different parents at a given parent level, then
82+
they will cause separate gitignore files to be written.
83+
84+
85+
EXAMPLES
86+
--------
87+
88+
* Adds all `*.log` files under `tmp` directory
89+
and its subdirectories to the gitignore file found at the
90+
root of the repository:
91+
+
92+
------------
93+
$ pwd
94+
/user/test/git_repo/src
95+
$ git ignore -e tmp/file.log
96+
------------
97+
+
98+
Results in `tmp/*.log` added to /user/test/git_repo/.gitignore
99+
100+
101+
* Add the files under the `var/uploaded` to the gitignore above
102+
103+
+
104+
------------
105+
$ git ignore -d --parent-level=1 www/var/uploaded/\*
106+
------------
107+
Results in `var/uploaded/*` added to /user/test/git_repo/www/.gitignore
108+
109+
SEE ALSO
110+
--------
111+
linkgit:gitignore[5]
112+
113+
GIT
114+
---
115+
Part of the linkgit:git[1] suite

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ TEST_PROGRAMS_NEED_X =
610610
unexport CDPATH
611611

612612
SCRIPT_SH += git-bisect.sh
613+
SCRIPT_SH += git-ignore.sh
613614
SCRIPT_SH += git-difftool--helper.sh
614615
SCRIPT_SH += git-filter-branch.sh
615616
SCRIPT_SH += git-merge-octopus.sh

git-ignore.sh

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2016, Thurston Stone
4+
#
5+
# unit test: t7900
6+
7+
_verbose=0
8+
9+
SUBDIRECTORY_OK=Yes
10+
OPTIONS_KEEPDASHDASH=
11+
OPTIONS_STUCKLONG=t
12+
# Would be nice to have examples, but rev-parse sees '*' as a symbol to hide everything afterwards
13+
#e,ext add relative path for any file of that type (ex. path/to/*.ext)
14+
#E,all-ext all files of that extention anywhere (ex. **/*.ext)
15+
#d,dir all files under the parent directory (ex. directory/*)
16+
#a,all-file all files of that file name (ex. **/filename.ext)
17+
OPTIONS_SPEC="git ignore [options] [file|glob ...]
18+
--
19+
Miscelleneous
20+
edit open the pertinent gitignore with your default text editor (Requires \$EDITOR to be set)
21+
v,verbose show verbose output
22+
n,dry-run do not actually edit any .gitignore files
23+
Determine what files to add to the gitignore(s):
24+
e,ext add relative path for any file of that type
25+
E,all-ext all files of that extention anywhere
26+
d,dir all files under the parent directory
27+
a,all-file all files of that file name
28+
Determine what gitignore(s) to use:
29+
p,parent-level= number of parent directories containing the gitignore to edit. Set to 0 to put it in the local directory"A
30+
31+
. git-sh-setup
32+
. git-sh-i18n
33+
34+
write_output () {
35+
if test $_verbose -eq 1
36+
then
37+
say $1
38+
fi
39+
}
40+
41+
get_git_ignore () {
42+
directory=$1
43+
44+
# if we don't yet have the repo root directory, get it
45+
if test -z "$repo_root"
46+
then
47+
#First, determine the root of the repository
48+
repo_root="$(git rev-parse --show-toplevel)/"
49+
write_output "repo_root=$repo_root"
50+
fi
51+
52+
# get the path relative to the repo root
53+
rel_directory="${directory#$repo_root}"
54+
# if the relative path is the same as it was, try converting it to aa *nix
55+
# style path
56+
if test "$rel_directory" = "$directory"
57+
then
58+
# repo root 2 (cygwin-ified path) didn't work
59+
# try the other one
60+
write_output "changing repo_root from $repo_root"
61+
#On windows, this turns to C:\... instead of /c/... from some other commands
62+
repo_root=$(printf "$repo_root" | awk -F":" '{ if ($2) print "/" tolower($1) $2; else print $1 }')
63+
write_output " to $repo_root"
64+
rel_directory="${directory#$repo_root}"
65+
fi
66+
# default gitignore
67+
gitignore="${repo_root}.gitignore"
68+
69+
# ------------------------------------------------
70+
# Determine the correct git ignore and the path of
71+
# the file relative to it
72+
# ------------------------------------------------
73+
if test $_parent_level -ge 0
74+
then
75+
parent=${directory}
76+
write_output "parent=${parent}"
77+
78+
if test $_parent_level -ne 0
79+
then
80+
for i in $(seq 1 $_parent_level)
81+
do
82+
parent="$(dirname "$parent")/"
83+
write_output "parent=${parent}"
84+
done
85+
fi
86+
root_len=$(printf "${repo_root}" | wc -m)
87+
parent_len=$(printf "${parent}" | wc -m)
88+
if test $root_len -ge $parent_len
89+
then
90+
write_output "root_len(${root_len}) >= parent_len(${parent_len})...
91+
uh-oh"
92+
gettextln "WARNING: Parent directory is outside of the repository"
93+
parent="${repo_root}"
94+
else
95+
write_output "root_len(${root_len}) < parent_len(${parent_len})...
96+
good"
97+
fi
98+
rel_directory="${directory#$parent}"
99+
gitignore="${parent}.gitignore"
100+
fi
101+
102+
write_output "rel_directory=${rel_directory}"
103+
write_output "gitignore=${gitignore}"
104+
105+
}
106+
107+
add_ignore () {
108+
# get the absolute path of the file
109+
file="$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
110+
write_output "file=$file"
111+
112+
directory="$(dirname "$file")/"
113+
write_output "directory=$directory"
114+
get_git_ignore "$directory"
115+
116+
filename=$(basename "$file")
117+
write_output "filename=$filename"
118+
extension="${filename##*.}"
119+
write_output "extension=$extension"
120+
# defaault line
121+
line="${rel_directory}${filename}"
122+
123+
# ------------------------------------------------
124+
# Determine the correct line to add to the gitignore
125+
# based on user inputs
126+
# ------------------------------------------------
127+
if test $_ext -eq 1
128+
then
129+
line="${rel_directory}*.$extension"
130+
fi
131+
if test $_directory -eq 1
132+
then
133+
line="${rel_directory}*"
134+
fi
135+
if test $_file_anywhere -eq 1
136+
then
137+
line="**/$filename"
138+
fi
139+
if test $_ext_anywhere -eq 1
140+
then
141+
line="**/*.$extension"
142+
fi
143+
write_output "line=${line}"
144+
dryrun=""
145+
if test $_dry_run -eq 1
146+
then
147+
dryrun="$(gettext "DRY-RUN!")"
148+
fi
149+
say "$dryrun $(eval_gettext "Adding \$line to \$gitignore")"
150+
if test $_dry_run -eq 0
151+
then
152+
echo "$line" >>"$gitignore"
153+
fi
154+
}
155+
156+
_ext=0
157+
_directory=0
158+
_file_anywhere=0
159+
_ext_anywhere=0
160+
_parent_level=-1
161+
_edit=0
162+
_dry_run=0
163+
164+
while test $# != 0
165+
do
166+
case "$1" in
167+
--ext)
168+
_ext=1
169+
;;
170+
--all-ext)
171+
_ext_anywhere=1
172+
;;
173+
--dir)
174+
_directory=1
175+
;;
176+
--all-file)
177+
_file_anywhere=1
178+
;;
179+
--parent-level=*)
180+
_parent_level="${1#--parent-level=}"
181+
if ! echo $_parent_level | grep -q '^[0-9]\+$'
182+
then
183+
gettextln "ILLEGAL PARAMETER: -p|--parent-level requires a numerical argument"
184+
usage
185+
fi
186+
;;
187+
--dry-run)
188+
_dry_run=1
189+
;;
190+
--edit)
191+
if test -z $EDITOR
192+
then
193+
gettextln "ERROR: Shell variable \$EDITOR must be set"
194+
usage
195+
fi
196+
_edit=1
197+
;;
198+
--verbose)
199+
_verbose=1
200+
;;
201+
--)
202+
only_files_left=1
203+
;;
204+
*)
205+
if test $only_files_left -eq 1
206+
then
207+
add_ignore "$1"
208+
fi
209+
;;
210+
esac
211+
shift
212+
done
213+
if test $_edit -eq 1
214+
then
215+
get_git_ignore "$(pwd)/"
216+
git_editor "$gitignore"
217+
fi
218+
exit 0

0 commit comments

Comments
 (0)