使用 shell 脚本更改 git *n* 次提交的历史记录(提交日期)

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

我的问题概况:

我想为 今天 的最后 n 个提交中的 change the history 写一个脚本,例如:./myscript.sh 5 会将最后 5 次提交的 提交日期 更改为 今天 .

来自 this link,我可以:

  1. 上次提交的日期设置为当前日期
  2. 最后一次提交的日期设置为任意日期
  3. 任意提交的日期设置为任意或当前日期

因为我想要的是改变最后n次提交的历史记录,而不仅仅是1次,所以我必须采用第三种技术,它需要调用git rebase -i 并打开一个编辑器。我想写一个脚本来自动完成这个任务。


这是手动完成任务的方式(将最后 5 次提交的提交日期更改为今天):

git rebase -i HEAD~5

然后它打开编辑器

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`

关闭编辑器,重复以下5次

GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"
git rebase --continue

完成。


约束:因为我提前知道我在编辑器中所做的部分是将所有 pick 关键字替换为 edit,所以我希望它静默完成。只需键入 ./myscript.sh 5 即可完成工作,没有打开任何编辑器。我该怎么做 (在脚本中)?


在答案的帮助下,这是我的最终脚本:

#!/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 [[  =~ $integer_pattern ]]; then
  count=

  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] "

fi

如所述here

Interactive rebase 打开提交列表中的默认 $EDITOR。它也可以被名为 GIT_SEQUENCE_EDITOR 的环境变量覆盖,因此您需要拦截调用并将此变量与某些脚本一起使用

运行:GIT_SEQUENCE_EDITOR=<script> git rebase -i <params>。您的 <script> 应该接受一个参数:包含标准 rebase 提交列表的文件的路径。它应该就地重写并退出。通常的变基处理在那之后发生。

示例:

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

但您也可以使用一些 bash/python/whatever 脚本。

将 n 次提交压缩为一个提交可以在没有 rebase interactive 的情况下完成……甚至根本不需要 rebase。要压缩最后 5 次提交,您可以这样做:

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

大功告成