在100个git提交的rebase期间自动转换(通过脚本)

1l5u6lss  于 2023-08-01  发布在  Git
关注(0)|答案(1)|浏览(87)

我有一个git分支B,它比它的祖先A提前了大约100次提交。对于这100个提交中的每一个,我想运行一个脚本:
1.运行一个现有的脚本edit.sh,对一个源文件进行大约一千次自动搜索和替换编辑。
1.将原始提交的SHA附加到基于变更的提交的提交消息中。
除了这两个自动化的步骤,我不想在变基过程中做任何更改。
我可以通过git rebase -i运行脚本并重写提交消息100次来手动完成这一任务,但是有什么好的方法可以自动完成整个任务呢?(不需要手动命令或编辑这100个提交中的每一个。
不过,我确实需要在历史中保留所有100个提交,因为我的分支不是一个功能分支。相反,我们的repo是另一个repo的分支,我的分支正在上游捕获我们的分支。能够在我的fork历史中显示每个上游提交是非常有帮助的,即使内容有点不同。但首先我需要修改这些提交以匹配我们的fork中的更改!
请注意,我们希望在forked repo中保持线性历史,因此我们正在rebase而不是使用merge commits。到目前为止,我们一直通过git rebase --onto来实现这一点,它对所有文件都运行得很好,除了一个文件,这个文件在我们的fork中有太多的更改,以至于在其变基期间处理合并冲突是一个巨大的痛苦。
我只是在上游仓库中合并了一个PR,这将使有问题的文件与我们的fork更加相似。该PR中的更改通过此脚本自动执行。我证实了重新设定文件的基础变得容易多了。但是在此期间,我从upstream=>fork向port(又名git rebase --onto)提交了大约100次,直到fork赶上upstream中的PR。
因此,我在这里尝试做的是创建一个本地分支,其中包含100个新提交,这些提交与上游的最后100个提交相同,除了在每个提交中,我使用创建上游PR时使用的脚本重写这些提交中的有问题的文件。然后,我可以对这个临时本地分支进行交互式的重新基化,这样就可以更容易地处理合并冲突。

更多信息(无需阅读)

顺便说一句,这里有更多关于我们为什么这样做的背景:
我是两个开源仓库的维护者之一:JavaScript repo tc39/proposal-temporal和该repo的TypeScript端口:js-temporal/temporal-polyfill
JS repo是我们团队的“主要”repo:改变起源于那里,并且随后被移植到TS存储库。理想情况下,它可以以相反的顺序完成,所以我们可以自动化TS=>JS步骤,但repo是对JavaScript本身进行更改的建议。拥有JavaScript规范的ECMA TC 39标准委员会将不赞成使用TypeScript编写的JavaScript功能的引用polyfill。:-)所以我们需要维护两个polyfill:一个是标准委员会的JavaScript,一个是生产使用的TypeScript。
在大多数情况下,这个过程工作正常:TS repo将JS repo设置为远程,我们从JS repo获取提交并使用git rebase --onto将提交重播到TS repo上。(我们实际上使用了一些由维护者编写的很酷的tools来使这种重基化更容易。
如果我们能够移植这100个提交,那么将来维护这个分支将会容易得多!

bxjv4tth

bxjv4tth1#

一种可能的方法是创建一个脚本,通过利用GIT_SEQUENCE_EDITOR环境变量(即I mentioned here)来自动化变基过程。该变量允许我们以编程方式更改rebase todo-list,这是将在rebase操作期间应用的提交列表。
下面是这样一个脚本的示例:

#!/bin/bash
set -e

edit_script_path=/path/to/edit.sh

# That function will be called for each commit
process_commit() {
    sha="$1"
    message="$2"

    # Apply the edit.sh script
    chmod +x "$edit_script_path"
    "$edit_script_path"

    # Amend the commit
    git commit -a --amend -C HEAD --no-edit

    # Append the original SHA to the commit message
    git commit --amend -m "$message" -m "Original SHA: $sha"
}

export -f process_commit

# Kick off the rebase
git rebase --onto target_branch source_branch^ \
    -x 'bash -c "process_commit $GIT_COMMIT \"$(git log --format=%B -n 1 $GIT_COMMIT)\""'

字符串
该脚本定义了一个process_commit bash函数,该函数将在变基期间为每次提交调用。该函数运行您的edit.sh脚本,使用这些更改修改提交,并将原始提交SHA附加到提交消息。
它使用git rebase --onto target_branch source_branch^命令启动rebase操作,该命令将来自source_branch的提交重新应用到target_branch上。-x标志告诉git对每个被重新应用的提交执行一个shell命令。
shell命令是对bash -c "process_commit $GIT_COMMIT \"$(git log --format=%B -n 1 $GIT_COMMIT)\""的调用。该命令在每次重新应用提交时执行一次。GIT_COMMIT变量由git提供,包含被重新应用的提交的SHA。git log --format=%B -n 1 $GIT_COMMIT命令检索原始提交消息。
请将/path/to/edit.sh替换为edit.sh脚本的实际路径,并将target_branchsource_branch^替换为实际的分支名称。
该脚本应该会自动执行整个变基过程。但是,请注意,如果分支之间存在任何合并冲突,它仍然可能会停止。

相关问题