2

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
Larry N
  • 261
  • 1
  • 9
  • Does this answer your question? [Git interactive rebase without opening the editor](https://stackoverflow.com/questions/29094595/git-interactive-rebase-without-opening-the-editor) – phd Dec 29 '19 at 21:57
  • https://stackoverflow.com/search?q=%5Bgit-rebase%5D+interactive+automatic – phd Dec 29 '19 at 21:57
  • It looks like someone's asked a related question, but I don't understand what they've talked about. Can someone explain it in a more beginner-friendly manner? Like in my case what I should do? What should I type on the terminal? What should I write on my script to get the job done? – Larry N Dec 29 '19 at 22:10
  • Is there a _specific_ need to use **interactive** rebase? I mean... if you want your script to do stuff without user intervention, why do you want to run rebase **interactively** in the first place? I guess you could have fun with either rebase _without -i_ or with cherry-picks, and then there's no need to care about the interactive rebase control-by-the-editor part. – eftshift0 Dec 30 '19 at 03:21
  • @eftshift0 I'm mostly a beginner trying to playing around with the limited knowledge I've already known. Honestly all I knew about `rebase` is `rebase -i` to *combine* multiple commits into one. What I'm doing is writing a script to combine `n` last commits into one and `edit/e` when `rebase -i` to [change the *date commit* to *today*](https://codewithhugo.com/change-the-date-of-a-git-commit/). Like `./myscript.sh 5` will combine last 5 commits into one and change the date commit of that combined commit to *today*. – Larry N Dec 30 '19 at 09:24

2 Answers2

2

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

eftshift0
  • 26,375
  • 3
  • 36
  • 60
  • Really sorry, I described my problem incorrectly, I don't need to combine those commits into one, just to change their commit dates, as I edit my question accordingly. Anyway this answer really helped me learn a new thing, if someday I need to combine last 5 commits and change its commit date (as I misdescribed), this'll be obviously the answer that'd save my day. – Larry N Jan 02 '20 at 05:32
1

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.

Hasturkun
  • 35,395
  • 6
  • 71
  • 104
Jiri Kremser
  • 12,471
  • 7
  • 45
  • 72
  • Thank you, it looks like you're delivering what I want but I don't understand all yet, I'll mark accepted answer when I totally solved my problem. Sorry because I'm still a beginner, there're terms I don't know like *`$EDITOR` on the commit list*, *env variable called `GIT_SEQUENCE_EDITOR`*, ... But I think I'll figure them out soon. – Larry N Dec 29 '19 at 22:30