That's maybe an overstatement, but just a little. I use these two simple scripts for over five years now and I just cannot imagine to not have them in my shell. What's the fuzz about?
Clean untracked files safely
There are some untracked files in your repository, probably some build artifacts or other trash, but you're not sure. You know only that there is something because you can see a little exclamation mark icon in ZSH command prompt. What are you doing?
Most probably, you'll start with git status
to see what exactly is there.
$ git status
?? tmp/
?? some_trash
Everything looks unnecessary, so you're deciding to remove it.
$ git clean -f
Removing some_trash
Hmm, what about tmp
? It's a directory! You didn't notice the little /
next to its name, so you have to repeat the command again with -d
switch.
$ git clean -f -d
Removing tmp/
Now the repository is clean, but three commands were needed. If you're watchful enough, you need two, but that's still quite a lot of typing. I suppose you know many better ways of spending those five seconds!
I do, that's why I wrote the script below. To make it available in each shell, just put it in ~/.bashrc
, ~/.zshrc
or similar file.
function git_clean_untracked_safely {
TO_REMOVE=`git clean -f -d -n`;
if [[ -n "$TO_REMOVE" ]]; then
echo "Cleaning...";
printf "\n$TO_REMOVE\n\n";
echo "Proceed?";
select result in Yes No; do
if [[ "$result" == "Yes" ]]; then
echo "Cleaning in progress...";
echo "";
git clean -f -d;
echo "";
echo "All files and directories removed!";
fi
break;
done;
else
echo "Everything is clean";
fi;
}
So, how does it work?
$ git_clean_untracked_safely
Cleaning...
Would remove some_trash
Would remove tmp/
Proceed?
1) Yes 2) No
?#
You see what would be removed and if you think it's all right, you can just proceed by entering 1
. Or decline with 2
.
Proceed?
1) Yes 2) No
?# 1
Cleaning in progress...
Removing some_trash
Removing tmp/
Cleaning finished!
Writing the function name would be a waste of keystrokes, so I'd recommend creating an alias, for example by adding a line to ~/.bash_aliases
file.
alias gcl='git_clean_untracked_safely'
# Use different name if you use GNU Common Lisp interpreter
Or, if you prefer, add a git alias.
$ git config --global alias.justclean '! bash -c "source ~/.bashrc && git_clean_untracked_safely"'
Both commands will call the script in the same way.
$ gcl
$ git justclean
Clean old local branches
How often you run git branch -vvv
and see dozens of local branches that you even not remember about? I bet it happened at least once! What can you do in such a case? You could start with git remote prune origin
to clean references to dead remote branches and then remove all local ones without the upstream. But picking each branch and removing it with git branch -d
(or -D
) doesn't sound like fun.
Can we do better than that? Guess what... A script!
function git_clean_local_branches {
OPTION="-d";
if [[ "$1" == "-f" ]]; then
echo "WARNING! Removing with force";
OPTION="-D";
fi;
TO_REMOVE=`git branch -r | awk "{print \\$1}" | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk "{print \\$1}"`;
if [[ -n "$TO_REMOVE" ]]; then
echo "Removing branches...";
echo "";
printf "\n$TO_REMOVE\n\n";
echo "Proceed?";
select result in Yes No; do
if [[ "$result" == "Yes" ]]; then
echo "Removing in progress...";
echo "$TO_REMOVE" | xargs git branch "$OPTION";
if [[ "$?" -ne "0" ]]; then
echo ""
echo "Some branches was not removed, you have to do it manually!";
else
echo "All branches removed!";
fi
fi
break;
done;
else
echo "You have nothing to clean";
fi
}
The usage looks like this:
$ git_clean_local_branches
Removing branches...
bugfix/foo
bugfix/bar
bugfix/baz
feature/qux
feature/tux
feature/fux
Proceed?
1) Yes 2) No
?#
As with the previous script, you're able to both proceed or abort. By default, branches are removed gracefully, so the command may fail when the branch wasn't merged to the master (or at least when git says that).
$ git_clean_local_branches
Proceed?
1) Yes 2) No
?# 1
Removing in progress...
Deleted branch bugfix/foo (was 7ff047995).
Deleted branch feature/qux (was cfad3e00c).
Deleted branch feature/tux (was 6529123af).
Deleted branch feature/fux (was b12ec9091).
error: The branch 'bugfix/bar' is not fully merged.
If you are sure you want to delete it, run 'git branch -D bugfix/bar'.
error: The branch 'bugfix/baz' is not fully merged.
If you are sure you want to delete it, run 'git branch -D bugfix/baz'.
Some branches were not removed, you have to do it manually!
If you want to prune the branches anyway, use -f
switch.
$ git_clean_local_branches -f
WARNING! Removing with force
Removing branches...
bugfix/bar
bugfix/baz
1) Yes 2) No
?# 1
Removing in progress...
Deleted branch bugfix/bar (was 7ff047995).
Deleted branch bugfix/baz (was cfad3e00c).
All branches removed!
Both bash and git alias are available as well.
alias glpo='git_clean_local_branches'
$ git config --global alias.localprune '! bash -c "source ~/.bashrc && git_clean_local_branches"'
And that's it! Enjoy!