Skip to content

Instantly share code, notes, and snippets.

@jmarrec
Last active May 28, 2024 06:14
Show Gist options
  • Save jmarrec/0ca3f74dede13b5e494b2a8f253e0039 to your computer and use it in GitHub Desktop.
Save jmarrec/0ca3f74dede13b5e494b2a8f253e0039 to your computer and use it in GitHub Desktop.
Git alias for fixing up a commit
[alias]
fixup = "!f() { \
git diff --cached --quiet && echo \"Nothing is staged\" && exit 1; \
fixup_commit=$(git log --oneline | fzf --height=40% --layout=reverse --prompt='git log>' --with-nth='2..' --preview='git show --color=always {1}'); \
echo \"Amending commit: $fixup_commit\"; \
fixup_commit_sha=$(echo $fixup_commit | awk '{print $1}'); \
git commit --fixup=$fixup_commit_sha; \
git rebase --update-refs --autosquash -i $fixup_commit_sha^1; \
}; \
f"
fixup2 = "!f() { \
git diff --cached --quiet && echo \"Nothing is staged\" && exit 1; \
local filter; \
if [ -n $@ ] && [ -e $ ]; then \
filter=\"-- $@\"; \
fi; \
fixup_commit=$(git log \
--graph --color=always --abbrev=7 \
--format=\"%C(auto)%h%d - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)\" $@ | \
fzf --ansi --no-sort --layout=reverse --tiebreak=index \
--preview=\"f() { set -- \\$(echo -- \\$@ | rg -o '\\b[a-f0-9]{7,}\\b'); [ \\$# -eq 0 ] || git show --color=always \\$1 $filter; }; f {}\" \
--preview-window=right:60%); \
echo \"Amending commit: $fixup_commit\"; \
fixup_commit_sha=$(echo $fixup_commit | rg -o '\\b[a-f0-9]{7,}\\b'); \
echo \"SHA: '$fixup_commit_sha'\"; \
git commit --fixup=$fixup_commit_sha; \
git rebase --update-refs --autosquash -i $fixup_commit_sha^1; \
}; \
f"

Assuming you have fzf installed. Tested on Ubuntu 20.04.

Adapted from https://twitter.com/ericniebler/status/1789843284027728166 and https://twitter.com/foonathan/status/1789943474994745494

This is helpful in a situation where you mean to ammend a commit back in history (not the last one, for that one you can just git commit --amend).

After staging some changes:

  • This opens a fzf picker to select the commit you want to amend with your changes, with a preview pane that shows the commit detail when you select one
  • This git commit --fixup=<commit>
    • see git docs for --fixup
    • This new fixup! will be automatically squashed with the target commit during the rebase below
  • This performs a git rebase --update-refs --autosquash -i <commit_before>
    • --autosquash squashes the fixup! commit
    • --update-refs: Automatically force-update any branches that point to commits that are being rebased
@jmarrec
Copy link
Author

jmarrec commented May 15, 2024

fixup, simpler

git_fixup

@jmarrec
Copy link
Author

jmarrec commented May 15, 2024

fixup2, with a graph

git_fixup2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment