3 #=======================================================================
4 # git-delete-old-branches
5 # File ID: b2a8aec0-3649-11e6-912b-02010e0a6634
7 # Delete obsolete Git branches after displaying some info about them
9 # Author: Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later.
11 #=======================================================================
13 progname
=git-delete-old-branches
31 " -n "$progname" -- "$@
")"
32 test "$?" = "0" ||
exit 1
43 -d|
--dbname) opt_dbname
="$2"; shift 2 ;;
44 -h|
--help) opt_help
=1; shift ;;
45 -l|
--load) opt_load
=1; shift ;;
46 -o|
--once) opt_once
=1; shift ;;
47 -q|
--quiet) opt_quiet
=$
(($opt_quiet + 1)); shift ;;
48 -v|
--verbose) opt_verbose
=$
(($opt_verbose + 1)); shift ;;
49 --version) echo $progname $VERSION; exit 0 ;;
51 *) echo $progname: Internal error
>&2; exit 1 ;;
54 opt_verbose
=$
(($opt_verbose - $opt_quiet))
56 if test "$opt_help" = "1"; then
57 test $opt_verbose -gt 0 && { echo; echo $progname $VERSION; }
60 Delete obsolete Git branches locally and from all remotes. For each
61 branch, display a "git diff --stat" against all local and remote
62 branches with this name, a simplified --graph log, and finally a git log
63 with patch against all branches. Display this in less(1), and ask if all
64 branches with this name should be deleted.
65 The following responses are valid:
67 "y" - Delete all branches with this name locally and from all remotes
68 and mark it as garbage.
69 "n" - Don't delete the branch. If -o/--once is used later, files marked
70 with "n" will not be checked.
71 "d" - Mark branch as "don't know", to be perused later.
72 "q" - Exit the program.
74 Usage: $progname [options] BRANCH [BRANCH [...]]
78 -d FILE, --dbname FILE
79 Store answers in the SQLite database FILE. Can be used to automate
84 Store the specified branches in the "refs" database table along with
85 the commit date. This makes it possible to sort the branches by age.
86 Must be used together with the -d/--dbname option. If -v is
87 specified, progress is shown while the branches are stored.
89 Don't ask about branches that have been answered "n" to earlier.
91 Be more quiet. Can be repeated to increase silence.
93 Increase level of verbosity. Can be repeated.
95 Print version information.
105 git br
-a | rmspcall |
grep -E "(^|/)$1\$"
109 test -z "$db" && return
110 echo "$@" | sqlite3
"$db"
116 INTO branches (yn, branch, date)
117 VALUES('$1', '$2', datetime('now'));
123 CREATE TABLE IF NOT EXISTS branches (
125 CONSTRAINT branches_yn_contents
126 CHECK (yn = 'y' OR yn = 'n' OR yn = 'd' OR yn IS NULL),
128 CONSTRAINT branches_branch_length
129 CHECK (length(branch) > 0)
133 DEFAULT (datetime('now'))
134 CONSTRAINT branches_date_length
135 CHECK (date IS NULL OR length(date) = 19)
136 CONSTRAINT branches_date_valid
137 CHECK (date IS NULL OR datetime(date) IS NOT NULL)
139 CREATE TABLE IF NOT EXISTS meta (
141 CONSTRAINT meta_key_length
142 CHECK (length(key) > 0)
147 INSERT OR IGNORE INTO meta (key, value)
148 VALUES('program', 'git-delete-old-branches');
149 INSERT OR IGNORE INTO meta (key, value)
151 'https://gitlab.com/oyvholm/utils/blob/master/git-delete-old-branches');
152 INSERT OR IGNORE INTO meta (key, value)
153 VALUES('dbversion', '$dbversion');
154 CREATE TABLE IF NOT EXISTS refs (
156 CONSTRAINT refs_date_length
157 CHECK (date IS NULL OR length(date) = 19)
158 CONSTRAINT refs_date_valid
159 CHECK (date IS NULL OR datetime(date) IS NOT NULL),
161 CONSTRAINT refs_branch_length
162 CHECK (length(branch) > 0)
169 if test "$opt_load" = "1" -a -z "$opt_dbname"; then
170 echo $progname: -l/--load doesn
\'t work without
-d/--dbname >&2
174 currversion
=$
(sql
"SELECT value FROM meta WHERE key = 'dbversion';")
175 if test -n "$currversion"; then
176 if test $currversion -gt $dbversion; then
177 (echo $progname: Database version of
$db is too new.
178 echo $progname: The db version is
$currversion, and this program can
179 echo $progname: only handle databases up to version
$dbversion.
) >&2
184 if test "$opt_load" = "1"; then
185 test $opt_verbose -ge 1 && tput sc
>&2
187 s
="$(echo "$f" | sed "s
/'/''/g")"
188 if test $opt_verbose -ge 1; then
193 GIT_PAGER=cat git log -1 "$f" \
194 --format=tformat:"INSERT INTO refs (date, branch) VALUES (datetime('%cI
'), '$s');"
196 test $opt_verbose -ge 1 && tput rc el >&2
203 s="$(echo "$f" | sed "s/'/''/g
")"
204 if test -n "$db" -a "$opt_once" = "1"; then
205 sql
"SELECT branch FROM branches WHERE branch = '$s' AND yn = 'n';" |
206 grep -q .
&& continue
208 if test $opt_verbose -ge 1; then
210 echo $progname: Check
\"$f\" branches
213 listbr
"$f" |
grep -q . ||
continue
218 git
diff --stat $
(listbr
"$f" | perl
-pe 's/^/.../;')
220 git log
-C -C -M -M --abbrev-commit --decorate=short
--format=oneline \
222 listbr
"$f" | perl
-pe 's/^/../;'
225 git log
-C -C -M -M --date-order --date=iso
--decorate=short \
226 --format=fuller
--graph -c -p $
(listbr
"$f" | perl
-pe 's/^/../;')
228 echo -n "Delete all '$f' branches? " >&2
231 if test "$valg" = "y"; then
232 git dbr $
(listbr
"$f")
234 elif test "$valg" = "n"; then
236 elif test "$valg" = "d"; then
238 elif test "$valg" = "q"; then