# Tools alias g="git" y() { local 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() { local folder="$(test -e "${1:-$PWD}" && realpath --relative-to="$XDG_CONFIG_HOME" "${1:-$PWD}" || echo "$1")" echo "config/$folder:" >/tmp/yc-msg yadm commit -v --template /tmp/yc-msg ${@:2} -- "$XDG_CONFIG_HOME/$folder*" } gcn() { local 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="box/$1" fulldir="$root/2-standards/$dir" fi else fulldir="$(realpath ${1:-$PWD})" dir="${fulldir#$root/}" fi echo "$dir: " >/tmp/gcn-msg git add $fulldir git moves -q 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 66;; (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 } # 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() { local 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) local ignore=true; shift 1;; -f|--force) local force=true; shift 1;; -*) options+=($1); exit 1;; *) break;; esac done ((#!=2)) && echo "Usage: [options] " && 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 local 1=$(git rev-parse $1) local 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() { local verbosity=1 while [[ $# -gt 0 ]]; do case $1 in -v) verbosity=2; shift 1;; -q|--quiet) verbosity=0; shift 1;; --theirs) local params=(-X theirs); shift 1;; *) break;; esac done local 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 local last=$? [ $last -gt 0 ] && local 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"; }