The big picture of my problem:
I want to write a script to change the history of the last n commits to today, for example: ./myscript.sh 5
will change the commit dates of the last 5 commits to today.
From this link, I can either:
- Set the date of the last commit to the current date
- Set the date of the last commit to an arbitrary date
- Set the date of an arbitrary commit to an arbitrary or current date
Because what I want is to change the history of the last n commits, not only 1, so I have to go with the 3rd technique, which need to invoke git rebase -i
and an editor open. I want to write a script to automate this task.
Here's how the task is done manually (change the commit dates of last 5 commits to today):
git rebase -i HEAD~5
then it opens the editor
pick 81888d1 committed 9 months ago
pick 7363124 committed a month ago
pick eea43f7 committed yesterday
pick 48c3e85 committed yesterday
pick a62cbec commit recently
# change all the `pick` to `edit`
close the editor, repeat the following for 5 times
GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
git rebase --continue
Done.
Constraints: Because I know ahead of time that the part I do in editor is to replace all pick
keywords with edit
, so I want it to be done silently. Just type ./myscript.sh 5
and the job done, no editors opened. How can I do this (in script)?
With the help of the answers, here's my final script:
#!/bin/bash
# wish design:
#./myscript.sh [number of days]
#./myscript.sh 5 # make the last 5 commits's commit dates to today
declare -r integer_pattern="^[0-9]+$"
if [[ $1 =~ $integer_pattern ]]; then
count=$1
GIT_SEQUENCE_EDITOR="sed -i -re 's/^pick /e /'" git rebase -i "HEAD~$count"
for ((i=0; i<count; i++)); do
GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
git rebase --continue
done
else
echo "invalid argument [number of days] $1"
fi