Skip to content

Instantly share code, notes, and snippets.

@whi-tw
Created December 18, 2024 16:13
Show Gist options
  • Save whi-tw/38f377985c3bbbe1dad3a6ad3e3c2be9 to your computer and use it in GitHub Desktop.
Save whi-tw/38f377985c3bbbe1dad3a6ad3e3c2be9 to your computer and use it in GitHub Desktop.
Script to fixup commit a bunch of changed files in a git repo

Fixup a bunch of things

Usage

./fixup_to_last_changed.sh <file> <file> <file> [optional git cli flags]

Description

  • ./fixup_to_last_changed.sh <file> - will find the last commit where file was changed, and create a fixup commit for that commit.
  • ./fixup_to_last_changed.sh <file> <file1> - as above, but individually with two files, creating two fixup commits
  • ./fixup_to_last_changed.sh - as above, but with all unstaged files. Confirms before actually creating the commits.
  • ./fixup_to_last_change.sh <file> --no-verify - fixup's one file, but using --no-verify in the commit.

Git Alias

This allows you to run the script via git fixlastchange <file> <file>

git config --global alias.fixlastchange '! ~/.local/bin/fixup_last_change.sh'

~/.gitconfig:

...
[alias]
	fixlast = commit --fix HEAD
	fixlastchange = ! /Users/tom.whitwell/.local/bin/fixup_last_change.sh
...
#!/usr/bin/env bash
set -euo pipefail
files=()
extra_args=()
for arg in "${@}"; do
if [ -f "${arg}" ]; then
files+=("${arg}")
else
extra_args+=("${arg}")
fi
done
if [ ${#files[@]} -eq 0 ]; then
while IFS= read -r line; do
if [[ "${line}" =~ ^M ]]; then
files+=("$(echo "${line}" | cut -d' ' -f2)")
fi
done < <(git status --porcelain | xargs -L1 echo)
if [ ${#files[@]} -eq 0 ]; then
echo "No files found to fixup" >&2
exit 1
else
echo "No files provided, using all modified files" >&2
fi
fi
function fixup_last_change() {
local file="${1}"
local extra_args=("${@:2}")
last_sha=$(git log -1 --pretty=format:%H -- "${file}")
if [ -z "${last_sha}" ]; then
echo "No commits found for ${file}"
return 1
fi
git commit --fix "${last_sha}" "${extra_args[@]}" -- "${file}"
}
if [ ${#files[@]} -gt 1 ]; then
# ask for confirmation
echo "Multiple files found:"
for file in "${files[@]}"; do
echo " ${file}"
done
read -p "Continue? [y/N] " -n 1 -r
if [[ ! ${REPLY} =~ ^[Yy]$ ]]; then
echo "Aborting" >&2
exit 1
fi
fi
for file in "${files[@]}"; do
fixup_last_change "${file}" "${extra_args[@]}"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment