One contributor has consistently disagreed with formatting standards and has repeatedly changed the Prettier config file, or not used Prettier at all. As a result, the git history is a sort of tug-of-war of cosmetic changes with huge diffs, and the real changes are difficult to find.
The name of the front-end directory was renamed at some point. We load the project from within that directory, making it a nuisance to access earlier git history from VSCode.
A TypeScript transpiler was added at some point, generating a file.js
and file.js.map
for every file.ts
across the project. The files aren't generated consistently (sometimes they have a particular comment at the end, sometimes not), which adds to the noise in the git history.
I'll keep a backup of the repo just in case, and then rebase, doing the following on every commit:
file.js
and file.js.map
files.Our team would then move to the new repo.
Specifically:
GIT_SEQUENCE_EDIT=cat git rebase
--strategy recursive --strategy-option theirs --rebase-merges \
--exec '../cleanup.sh && git add . && git commit --amend --no-edit --no-verify --allow-empty' \
e709bcd1
where e709bcd1
is the SHA of a good place to start, using the script cleanup.sh
:
#! /usr/bin/env zsh
setopt nullglob
echo $(git rev-parse HEAD) > commit.log
# If both directories exist, assume old_front_end is the real one,
# so delete new_front_end to allow us to rename old_front_end.
# (Otherwise, `mv` will move the one directory into the other.)
if [[ -d "old_front_end" ]] && [[ -d "new_front_end" ]]; then
rm -rf new_front_end
fi
# Rename old_front_end if necessary
if [[ -d "old_front_end" ]] && [[ ! -d "new_front_end" ]]; then
mv old_front_end new_front_end
fi
if [[ -d "new_front_end" ]]; then
# Clean up JS files
for file in "new_front_end/src/**/*.ts"; do
[[ ! -e $file ]] && continue # skip following if no such file
rm "${file%.*}.js"
rm "${file%.*}.js.map"
done
# Apply consistent Prettier settings
prettier --config ~/external_source_of_truth/.prettierrc -w "new_front_end/src/**/*.{js,ts,svelte,gql,css,scss}" || true
fi
git add . && git rebase --continue
, but I'd rather not have to do this hundreds of times. Can I automate this?I solved the problem using git filter-repo
and the associated tool lint-history
:
git filter-repo --path-rename old_front_end/:new_front_end/
git filter-repo --force --filename-callback '
if filename.endswith(b".js"):
ts_file = filename[:-3] + b".ts"
if os.path.isfile(ts_file.decode("utf-8")):
return None
if filename.endswith(b".js.map"):
ts_file = filename[:-7] + b".ts"
if os.path.isfile(ts_file.decode("utf-8")):
return None
return filename
'
lint-history --relevant '
return filename.endswith(b".ts") or filename.endswith(b".js")
or filename.endswith(b".svelte") or filename.endswith(b".css")
or filename.endswith(b".scss") or filename.endswith(b".gql")
' --filenames-important maybe-prettier
I needed to write a helper script called maybe-prettier
because some commits had bad files with unresolved merge symbols (<<<<<<<< HEAD
and so on). Prettier was unable to format those files and exited with an error, halting the progress of filter-repo
. To get around this, maybe-prettier
first checks to see if a file is able to be formatted; it always exits with success.
#! /usr/bin/env zsh
# Prettier gives three exit codes:
# 0 file is good
# 1 needs formatting
# 2 error
prettier --config ~/external_source_of_truth/.prettierrc -c $1
if [[ $? = 1 ]]; then
prettier --config ~/external_source_of_truth/.prettierrc -w $1
fi