Compare commits

..

4 Commits

5 changed files with 172 additions and 0 deletions

41
_git-ls-ignored Normal file
View File

@@ -0,0 +1,41 @@
#compdef git-ls-ignored
#description List files which exist and are ignored by this repository.
# Offer the paths the script would actually list, so the candidates match its
# rules rather than the --exclude-standard set used by zsh's own
# __git_ignored_other_files. _multi_parts descends one component at a time, so
# a directory holding ignored files completes as a way to narrow the listing.
__git-ls-ignored_files() {
local common_dir expl
local -a excludes files
if (( $+opt_args[-g] + $+opt_args[--global] )); then
excludes=(--exclude-standard)
else
common_dir=$(_call_program common-dir git rev-parse --git-common-dir 2>/dev/null)
[[ -n $common_dir ]] || return 1
[[ $common_dir == /* ]] || common_dir=$PWD/$common_dir
excludes=(--exclude-per-directory=.gitignore)
[[ -f $common_dir/info/exclude ]] &&
excludes+=(--exclude-from=$common_dir/info/exclude)
fi
files=(${(0)"$(_call_program ignored-files git ls-files -z --others --ignored \
${(q)excludes} 2>/dev/null)"})
(( $#files )) || return 1
_wanted ignored-files expl 'ignored file' _multi_parts -f - / files
}
_git-ls-ignored() {
_arguments -s -S \
'(-d --directory)'{-d,--directory}'[list an ignored directory by name instead of its contents]' \
'(-g --global)'{-g,--global}'[also apply the global core.excludesfile]' \
'(-z)-z[terminate entries with NUL instead of newline]' \
'(- *)'{-h,--help}'[show usage information]' \
'*:pathspec:__git-ls-ignored_files'
}
_git-ls-ignored "$@"
# vim: ft=zsh

3
config
View File

@@ -92,3 +92,6 @@
path = ~/.config/private/gitconfig
path = ~/.config/work/gitconfig
path = ~/.config/git/local
[advice]
skippedCherryPicks = false

17
git-find-merged Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
# Find local branches that have been squash-merged into a target branch.
# Usage: git-find-merged [target-branch]
# Default target branch: main
target="${1:-main}"
git for-each-ref refs/heads/ --format='%(refname:short)' | while read branch; do
[[ "$branch" == "$target" ]] && continue
merge_base=$(git merge-base "$target" "$branch" 2>/dev/null) || continue
tree=$(git rev-parse "$branch^{tree}" 2>/dev/null) || continue
squash_commit=$(git commit-tree "$tree" -p "$merge_base" -m "test" 2>/dev/null) || continue
cherry_result=$(git cherry "$target" "$squash_commit" 2>/dev/null)
if [[ "$cherry_result" == "-"* ]]; then
echo "$branch"
fi
done

77
git-ls-ignored Executable file
View File

@@ -0,0 +1,77 @@
#!/bin/bash
# List files which exist in the working tree and are ignored by this
# repository's own rules: any .gitignore file, plus $GIT_DIR/info/exclude.
#
# Unlike `git status --ignored`, the global core.excludesfile is not consulted
# unless --global is given, so the output only contains paths this repository
# chose to ignore.
#
# Works inside a linked worktree, where .git is a file and info/exclude lives in
# the common git directory rather than next to the worktree.
#
# Usage: git-ls-ignored [<options>] [--] [<pathspec>...]
#
# -d, --directory list an ignored directory by name instead of its contents
# -g, --global also apply the global core.excludesfile
# -z terminate entries with NUL instead of newline
# -h, --help show this message
#
# Paths are relative to the top of the working tree. Without a <pathspec> the
# whole working tree is listed, not just the current directory.
# Print the comment block above, minus the shebang, as the help text.
usage() {
awk 'NR == 1 { next } /^#/ { sub(/^# ?/, ""); print; next } { exit }' "$0"
}
global=false
options=()
paths=()
while [ $# -gt 0 ]; do
case "$1" in
-d | --directory) options+=(--directory) ;;
-g | --global) global=true ;;
-z) options+=(-z) ;;
-h | --help)
usage
exit 0
;;
--)
shift
paths+=("$@")
break
;;
-*)
echo "error: unknown option: $1" >&2
usage >&2
exit 1
;;
*) paths+=("$1") ;;
esac
shift
done
# In a worktree .git is a file pointing at .git/worktrees/<name>, which has no
# info/exclude of its own; Git reads the one in the common directory, so that is
# the file to point --exclude-from at. The common directory is reported relative
# to the current directory unless it happens to be absolute.
common_dir=$(git rev-parse --git-common-dir) || exit $?
case "$common_dir" in
/*) ;;
*) common_dir="$PWD/$common_dir" ;;
esac
if $global; then
# .gitignore, info/exclude and core.excludesfile.
excludes=(--exclude-standard)
else
excludes=(--exclude-per-directory=.gitignore)
# --exclude-from is fatal on a missing file, and info/exclude is optional.
if [ -f "$common_dir/info/exclude" ]; then
excludes+=("--exclude-from=$common_dir/info/exclude")
fi
fi
git ls-files --others --ignored --full-name "${excludes[@]}" "${options[@]}" \
-- "${paths[@]:-:/}"

34
install.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
symlink() {
local source=$1
local dest=$2
mkdir -p $(dirname $dest)
if [ -L $dest ]; then
local target=`readlink $dest`
if [ "$target" != "$source" ]; then
rm $dest
ln -s $source $dest
echo changed replace incorrect symlink $dest
fi
elif [ -f $dest ]; then
error symlink failed $dest exists but is a regular file
else
ln -s $source $dest
echo changed created symlink $dest
fi
}
symlink ~/.config/git/_git-changes \
~/.local/share/zsh/site-functions/_git-changes
symlink ~/.config/git/git-sync \
~/.local/bin/git-sync
symlink ~/.config/git/git-find-merged \
~/.local/bin/git-find-merged
symlink ~/.config/git/git-ls-ignored \
~/.local/bin/git-ls-ignored
symlink ~/.config/git/_git-ls-ignored \
~/.local/share/zsh/site-functions/_git-ls-ignored