简体   繁体   中英

change git history (commit date) of *n* commits with shell script

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:

  1. Set the date of the last commit to the current date
  2. Set the date of the last commit to an arbitrary date
  3. 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

Squashing n commits into one can be done without rebase interactive.... or even rebase at all. To squash the last 5 commits you can do this:

git reset --soft HEAD~5
git commit -m "some comment"

And you are done

As described here .

Interactive rebase opens the default $EDITOR on the commit list. It can be also overriden by env variable called GIT_SEQUENCE_EDITOR , so you need to intercept the call and use this variable with some script

Run: GIT_SEQUENCE_EDITOR=<script> git rebase -i <params> . Your <script> should accept a single argument: the path to the file containing the standard rebase commit list. It should rewrite it in-place and exit. Usual rebase processing happens after that.

Example:

GIT_SEQUENCE_EDITOR="sed -i -re 's/^pick /e /'" git rebase -i

But you can use also some bash/python/whatever script instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM