Skip to content

Commit 43fa0d8

Browse files
committed
feat: ✨ add script to rewrite commit messages
1 parent a6724e3 commit 43fa0d8

2 files changed

Lines changed: 104 additions & 1 deletion

File tree

src/gitutils/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The following aliases are included: [./alias.json](./src/gitutils/alias.json)
1919
## Options
2020

2121
| Options Id | Description | Type | Default Value |
22-
| ---------- | ------------------------------------ | ------ | -------------- |
22+
| ---------- | ----------------------------------- | ------ | ------------- |
2323
| version | The version of GitUtils to install. | string | latest |
2424

2525
## Functional Coverage
@@ -48,6 +48,7 @@ The feature includes the following interactive utilities:
4848
- `git align` - Align the current branch with its remote counterpart.
4949
- `git degit <repository> [directory]` - Download and extract a repository from GitHub, GitLab, or Bitbucket.
5050
- `git fix date [options] [<commit>]` - Fix commit dates and times in git history. Options include rescheduling commits on specific days of week outside certain time ranges.
51+
- `git fix message -m <message> [--force|<commit>]` - Rewrite the commit message of a specific commit.
5152
- `git fixup [--force|<commit>]` - Amend the specified commit with current changes and rebase.
5253
- `git forall <command>` - Execute a command for all files in the repository.
5354
- `git getcommit [--force|<commit>]` - Get the commit to fixup.

src/gitutils/_git-fix-message.sh

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/bin/sh
2+
3+
# Function to print help and manage arguments
4+
eval $(
5+
zz_args "Rewrite an arbitrary commit message" $0 "$@" <<-help
6+
f - force allow overwritting pushed history
7+
p - push push to remote
8+
m msg msg new commit message
9+
- sha sha sha commit to rewrite message
10+
help
11+
)
12+
13+
# Navigate to the repository root
14+
cd "$(git rev-parse --show-toplevel)" >/dev/null
15+
16+
# Fetch updates from the remote repository
17+
git fetch --progress --prune --recurse-submodules=no origin >/dev/null
18+
19+
# Make sure we don't have uncommitted changes
20+
if ! git diff-index --quiet HEAD --; then
21+
zz_log e "You have uncommitted changes. Please commit or stash them before running this script."
22+
exit 1
23+
fi
24+
25+
# Prevent running while a rebase is in progress
26+
if git isRebase >/dev/null 2>&1; then
27+
zz_log e "A rebase is in progress. Please finish or abort it before running this script."
28+
exit 1
29+
fi
30+
31+
# Retrieve the commit SHA to edit
32+
sha=$(git getcommit $force $sha)
33+
34+
# Validate commit exists
35+
if ! git rev-parse --verify --quiet "$sha^{commit}" >/dev/null; then
36+
zz_log e "Invalid commit: $sha"
37+
exit 1
38+
fi
39+
40+
# Ensure commit belongs to current branch history
41+
if ! git merge-base --is-ancestor "$sha" HEAD; then
42+
zz_log e "Commit $(echo "$sha" | cut -c1-7) is not in the current branch history."
43+
exit 1
44+
fi
45+
46+
# Ask for the new message if not provided as argument
47+
if [ -z "$msg" ]; then
48+
read -p "New commit message: " msg
49+
fi
50+
51+
# Ensure message is not empty
52+
if [ -z "$msg" ]; then
53+
zz_log e "Commit message cannot be empty."
54+
exit 1
55+
fi
56+
57+
old_msg=$(git log -1 --pretty=%s "$sha")
58+
zz_log w "Commit to rewrite: $(echo "$sha" | cut -c1-7)"
59+
zz_log - "Current message: $old_msg"
60+
zz_log - "New message: $msg"
61+
zz_log w "This will rewrite git history. Make sure you understand the consequences."
62+
63+
if ! zz_ask "Yn" "Do you want to proceed?"; then
64+
zz_log i "Operation cancelled by user."
65+
exit 1
66+
fi
67+
68+
# Build a minimal range that includes target commit and descendants.
69+
if [ -n "$(git rev-list --parents -n 1 "$sha" | cut -d' ' -f2)" ]; then
70+
range="$sha^..HEAD"
71+
else
72+
range="--all"
73+
fi
74+
75+
TARGET_SHA="$sha" NEW_MESSAGE="$msg" git filter-branch -f --msg-filter '
76+
if [ "$GIT_COMMIT" = "$TARGET_SHA" ]; then
77+
printf "%s\n" "$NEW_MESSAGE"
78+
else
79+
cat
80+
fi
81+
' --tag-name-filter cat -- $range
82+
83+
# Clean up the original refs
84+
rm -rf .git/refs/original/
85+
git reflog expire --expire=now --all
86+
git gc --prune=now
87+
88+
# Push rewritten history if requested
89+
if [ -n "$push" ]; then
90+
if git rev-parse --verify --quiet origin/HEAD >/dev/null; then
91+
zz_log i "Pushing to remote..."
92+
if [ -n "$force" ]; then
93+
git push --force origin HEAD
94+
else
95+
git push --force-with-lease origin HEAD
96+
fi
97+
else
98+
zz_log i "Branch not pushed, skipping push..."
99+
fi
100+
fi
101+
102+
zz_log s "Commit message rewritten successfully."

0 commit comments

Comments
 (0)