Last active
April 20, 2020 19:30
-
-
Save kirelagin/70abed1c291e42b198c9970bbe5368e5 to your computer and use it in GitHub Desktop.
Quickly edit a file that was changed in the last git commit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# SPDX-FileCopyrightText: 2020 Kirill Elagin <https://kir.elagin.me/> | |
# SPDX-License-Identifier: MPL-2.0 | |
### | |
# | |
# Quickly edit a file that was changed in the last git commit. | |
# | |
# Sometimes you want to make a quick amendment to what you did in your last | |
# commit, but you already closed your editor. So you have to remember what | |
# file you edited, launch your editor, and type the file name again – it is | |
# somewhat cumbersome. Wouldn’t it be cool if you could just type: | |
# | |
# $ git fixup | |
# | |
# and have your editor launched with the file you edited in it? And if your | |
# last commit changed multiple files, you could choose which file to edit? | |
# This small script does exactly this. | |
# | |
# Use: | |
# | |
# * Download this script and put it somewhere on your $PATH. | |
# * $ git fixup | |
# * or $ git fixup <commit> | |
# | |
# Requirements: | |
# | |
# * git (obviously) | |
# * tput (probably comes with your distribution) | |
# * $EDITOR set to the editor you use | |
# | |
# https://gist.github.com/kirelagin/70abed1c291e42b198c9970bbe5368e5 | |
### | |
changed=() | |
mode='' | |
while IFS= read -r -d '' line ; do | |
if [ -z "$mode" ]; then | |
mode="$line" | |
else | |
mode='' | |
changed+=( "$line" ) | |
fi | |
done < <(git diff-tree --no-commit-id --name-status --diff-filter=AM -r -z "${@:-HEAD}") | |
chosen='' | |
if [ "${#changed[@]}" -lt 1 ]; then | |
printf 'No files to edit!\n' | |
exit 1 | |
elif [ "${#changed[@]}" -eq 1 ]; then | |
chosen="${changed[0]}" | |
fi | |
if [ -z "$chosen" ]; then | |
i=1 | |
for file in "${changed[@]}"; do | |
printf '[%d]\t%s\n' "$i" "$file" | |
i=$((i + 1)) | |
done | |
printf '\n' | |
while [ -z "$chosen" ]; do | |
read -r -p 'Choose a file to edit: ' c || exit 1 | |
if [ "$c" -ge 1 ] 2>/dev/null && [ "$c" -le "${#changed[@]}" ] 2>/dev/null; then | |
chosen="${changed[$((c - 1))]}" | |
else | |
tput cuu 1 | |
printf 'Enter a number between %d and %d.\n' 1 "${#changed[@]}" | |
fi | |
done | |
fi | |
printf 'Editing `%s`\n' "$chosen" | |
# shellcheck disable=SC2086 | |
exec $EDITOR "$chosen" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment