diff --git a/conf.d/forgit.plugin.fish b/conf.d/forgit.plugin.fish index a9c6971..f7025cb 100644 --- a/conf.d/forgit.plugin.fish +++ b/conf.d/forgit.plugin.fish @@ -22,7 +22,7 @@ test -z "$forgit_pager"; and set -g forgit_pager (git config core. test -z "$forgit_show_pager"; and set -g forgit_show_pager (git config pager.show || echo "$forgit_pager") test -z "$forgit_diff_pager"; and set -g forgit_diff_pager (git config pager.diff || echo "$forgit_pager") test -z "$forgit_ignore_pager"; and set -g forgit_ignore_pager (type -q bat >/dev/null 2>&1 && echo 'bat -l gitignore --color=always' || echo 'cat') -test -z "$forgit_log_format"; and set -g forgit_log_format "-%C(auto)%h%d %s %C(black)%C(bold)%cr%reset" +test -z "$forgit_log_format"; and set -g forgit_log_format "-%C(auto)%h%d %s %C(black)%C(bold)%cr%Creset" # https://github.com/wfxr/emoji-cli type -q emojify >/dev/null 2>&1 && set -g forgit_emojify '|emojify' @@ -242,6 +242,48 @@ function forgit::cherry::pick -d "git cherry-picking" --argument-names 'target' xargs -I% git cherry-pick % end +function forgit::fixup -d "git fixup" + forgit::inside_work_tree || return 1 + git diff --cached --quiet && echo 'Nothing to fixup: there are no staged changes.' && return 1 + + if set -q FORGIT_LOG_GRAPH_ENABLE + set graph "--graph" + else + set graph "" + end + + set cmd "git log $graph --color=always --format='$forgit_log_format' $argv $forgit_emojify" + set files (echo $argv | sed -nE 's/.* -- (.*)/\1/p') + set preview "echo {} |grep -Eo '[a-f0-9]+' |head -1 |xargs -I% git show --color=always % -- $files | $forgit_show_pager" + + + if test -n "$FORGIT_COPY_CMD" + set copy_cmd $FORGIT_COPY_CMD + else + set copy_cmd pbcopy + end + + set opts " + $FORGIT_FZF_DEFAULT_OPTS + +s +m --tiebreak=index + --bind=\"ctrl-y:execute-silent(echo {} |grep -Eo '[a-f0-9]+' | head -1 | tr -d '[:space:]' |$copy_cmd)\" + $FORGIT_FIXUP_FZF_OPTS + " + + set target_commit (eval "$cmd" | FZF_DEFAULT_OPTS="$opts" fzf --preview="$preview" | grep -Eo '[a-f0-9]+' | head -1) + + if test -n "$target_commit" && git commit --fixup "$target_commit" + # "$target_commit~" is invalid when the commit is the first commit, but we can use "--root" instead + set prev_commit "$target_commit~" + if test "(git rev-parse '$target_commit')" = "(git rev-list --max-parents=0 HEAD)" + set prev_commit "--root" + end + + GIT_SEQUENCE_EDITOR=: git rebase --autostash -i --autosquash "$prev_commit" + end + +end + function forgit::rebase -d "git rebase" forgit::inside_work_tree || return 1 @@ -433,4 +475,10 @@ if test -z "$FORGIT_NO_ALIASES" else alias grb 'forgit::rebase' end + + if test -n "$forgit_fixup" + alias $forgit_fixup 'forgit::fixup' + else + alias gfu 'forgit::fixup' + end end diff --git a/forgit.plugin.zsh b/forgit.plugin.zsh index f32ffb3..ae8945a 100755 --- a/forgit.plugin.zsh +++ b/forgit.plugin.zsh @@ -202,11 +202,11 @@ forgit::fixup() { target_commit=$(eval "$cmd" | FZF_DEFAULT_OPTS="$opts" fzf --preview="$preview" | grep -Eo '[a-f0-9]+' | head -1) if [[ -n "$target_commit" ]] && git commit --fixup "$target_commit"; then - # "$commit~" is invalid when the commit is the first commit, but we can use "--root" instead + # "$target_commit~" is invalid when the commit is the first commit, but we can use "--root" instead if [[ "$(git rev-parse "$target_commit")" == "$(git rev-list --max-parents=0 HEAD)" ]]; then prev_commit="--root" else - prev_commit="$commit~" + prev_commit="$target_commit~" fi # rebase will fail if there are unstaged changes so --autostash is needed to temporarily stash them # GIT_SEQUENCE_EDITOR=: is needed to skip the editor