174 lines
4.9 KiB
Plaintext
174 lines
4.9 KiB
Plaintext
# Tools
|
|
alias g="git"
|
|
|
|
y() {
|
|
unignore="$XDG_CONFIG_HOME/yadm/unignore"
|
|
test -r "$unignore" && cat "$unignore" | while read f; do eval ls -d $f; done | yadm add --intent-to-add --pathspec-from-file=-
|
|
test "$#" -eq 0 && yadm s || yadm "$@"
|
|
}
|
|
yc() {
|
|
folder=${1:-${PWD/$XDG_CONFIG_HOME\/}}
|
|
echo "config/$folder:" >/tmp/yc-msg
|
|
yadm commit -v --template /tmp/yc-msg ${@:2} -- "$XDG_CONFIG_HOME/$folder"
|
|
}
|
|
|
|
gcn() {
|
|
root="$(git rev-parse --show-toplevel)"
|
|
if test "$root" = "$DATA"
|
|
then
|
|
if test $# -eq 0 || test -e $1
|
|
then
|
|
fulldir="$(realpath ${1:-$PWD})"
|
|
dir="${fulldir#$root/*/}"
|
|
else
|
|
dir="notes/$1"
|
|
fulldir="$root/2-standards/$dir"
|
|
fi
|
|
else
|
|
fulldir="$(realpath ${1:-$PWD})"
|
|
dir="${fulldir#$root/}"
|
|
fi
|
|
echo "$dir:" >/tmp/gcn-msg
|
|
git commit -v --template /tmp/gcn-msg ${@:2} -- $fulldir
|
|
}
|
|
|
|
# if in home or under XDG_CONFIG_HOME and not within a git directory, replace git by yadm
|
|
git() {
|
|
case "$1" in
|
|
reset) test "$2" = "--hard" && return 1;;
|
|
config) ;;
|
|
clone) ;;
|
|
*) case "$PWD" in
|
|
$HOME|$XDG_CONFIG_HOME|$LAST_YADM)
|
|
yadm "$@"
|
|
return
|
|
;;
|
|
$XDG_CONFIG_HOME*|$HOME/.local*)
|
|
if ! command git rev-parse --show-toplevel &>/dev/null; then
|
|
export LAST_YADM="$PWD"
|
|
yadm "$@"
|
|
return
|
|
fi;;
|
|
esac;;
|
|
esac
|
|
command git "$@";
|
|
}
|
|
|
|
# BRANCHES
|
|
# Remove list of tags local & remote
|
|
gitrmtag() {
|
|
declare -a refs
|
|
local index=1
|
|
for tag in $@; do refs[index++]=":refs/tags/$tag"; done
|
|
git push origin "${refs[@]}" && git tag -d "$@"
|
|
}
|
|
# Rename a tag
|
|
gitretag() {
|
|
git push origin refs/tags/${1}:refs/tags/${2} :refs/tags/$1 && git tag -d $1
|
|
}
|
|
|
|
# Open or select a project
|
|
project() {
|
|
cd $projects_dir
|
|
if [ -d $2 ]
|
|
then cd "$2" && gitorigin "$@"
|
|
else gitclone "$@"
|
|
fi
|
|
}
|
|
|
|
# Rewriting history {{{
|
|
|
|
# gets the AuthorDate of a given committish
|
|
git-authordate() {
|
|
local date=$(git log --pretty=fuller --date=raw -1 $1 | grep AuthorDate)
|
|
echo ${date##*: }
|
|
}
|
|
# executes a git command (usually commit) with the date of a given committish
|
|
git-withdate() {
|
|
date=$(git-authordate $1)
|
|
GIT_AUTHOR_DATE="$date" GIT_COMMITTER_DATE="$date" git "${@:2}"
|
|
}
|
|
|
|
# takes all changes in the current working tree and amends them to the given commit
|
|
gitedit() {
|
|
git stash
|
|
gitcommits -q $1
|
|
git reset --keep $1
|
|
git stash pop
|
|
git-withdate $1 commit --all --amend "${@:2}"
|
|
gitcommits
|
|
}
|
|
|
|
# takes two committishs and squashes them with all commits between them into a single commit
|
|
# this will rewrite the full history from then on, but should not create any conflicts
|
|
gitsquash() {
|
|
local -a options
|
|
while [ $# -gt 0 ]; do
|
|
case $1 in
|
|
-i) ignore=true; shift 1;;
|
|
-f|--force) force=true; shift 1;;
|
|
-*) options+=($1); exit 1;;
|
|
*) break;;
|
|
esac
|
|
done
|
|
|
|
((#!=2)) && echo "Usage: [options] <startcommit> <endcommit>" && return 1
|
|
[[ -n $(git status -s) ]] && [ ! $force ] && echo -e "Tree is dirty, commit or stash your changes first!\nIf you want to execute the command regardless, run again with --force" && return 1
|
|
|
|
1=$(git rev-parse $1)
|
|
2=$(git rev-parse $2)
|
|
[ $(git rev-list $1 --count) -lt $(git rev-list $2 --count) ] && t=$1 && 1=$2 && 2=$t
|
|
|
|
gitcommits -q $1
|
|
git reset --hard $1
|
|
if [ $(git rev-list $2 --count) = 1 ]; then
|
|
git update-ref -d HEAD
|
|
git add .
|
|
git-withdate $1 commit -c $1
|
|
else
|
|
git reset -q $2
|
|
git add .
|
|
git commit --amend
|
|
fi
|
|
gitcommits
|
|
}
|
|
|
|
# given a committish, this command saves a list of commits between the HEAD and the given committish into the .git directory
|
|
# when ran without parameters it applies the saved list of commits onto the current HEAD
|
|
gitcommits() {
|
|
verbosity=1
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-v) verbosity=2; shift 1;;
|
|
-q|--quiet) verbosity=0; shift 1;;
|
|
--theirs) params=(-X theirs); shift 1;;
|
|
*) break;;
|
|
esac
|
|
done
|
|
|
|
stashed="$(git rev-parse --show-toplevel)/.git/stashed-commits"
|
|
if [ $1 ]; then
|
|
if [ $verbosity -eq 0 ]
|
|
then git rev-list --reverse HEAD...$1 >$stashed
|
|
else git rev-list --reverse HEAD...$1 | tee $stashed
|
|
fi
|
|
else
|
|
local aborted
|
|
for commit in $(cat $stashed); do
|
|
[ $aborted ] && rest+=($commit) && continue
|
|
[ $verbosity -gt 0 ] && git --no-pager log --oneline -1 $commit
|
|
git-withdate $commit cherry-pick $commit ${params:0} >/dev/null
|
|
last=$?
|
|
[ $last -gt 0 ] && aborted=true && typeset -a rest && continue
|
|
[ $verbosity -gt 0 ] && echo -e "\e[1A$(git log --color=always --pretty=format:"%C(yellow)$(git rev-parse --short HEAD^^)%C(bold) -> %Creset%C(yellow)%h%Creset %s" -1)"
|
|
[ $verbosity -gt 1 ] && git status -s
|
|
done
|
|
echo $rest >$stashed
|
|
[ $aborted ] && echo "A problem was encountered. Fix it and run 'gitcommits' again to apply the remaining ${#rest} commits."
|
|
fi
|
|
}
|
|
# }}}
|
|
|
|
# Testing
|
|
gittestcommit() { touch file$((++i)) && git add 'file*' && git commit -m "Create file$i"; }
|