【问题标题】:Git rebase: fixup by running commandGit rebase:通过运行命令修复
【发布时间】:2018-08-27 15:32:50
【问题描述】:

我在一个分支上,在我的develop 分支之前有许多提交(在历史直线上),并且在每条提交消息中都是我正在处理的问题跟踪票的名称。现在我想通过每个提交重新设置并将该票证的名称更改为不同的票证,概念上类似于:

perl -pi -e 's/BB-123/BB-456/' .git/COMMIT_EDITMSG

有没有办法告诉 rebase 的 reword 操作,我不想打开交互式编辑器,而是想对消息文本运行命令?

我想出的最好办法是在每次运行 git commit --amend 的提交之后放置一个 exec 操作,并将 $EDITOR 变量更改为上述命令或其他内容,但这太可怕了。

如果没有一个好的自动解决方案,我通常会在每次提交时使用reword 操作进行变基并手动编辑所有消息。

【问题讨论】:

    标签: git rebase git-amend


    【解决方案1】:

    是的:当交互式变基打开编辑器时,它会根据不同的环境设置打开一个:

    • GIT_SEQUENCE_EDITOR 用于命令运行,但是
    • GIT_EDITOR 用于reword 操作。

    (如果其中一项未设置,Git 会像往常一样退回到sequence.editorcore.editor 或内置编辑器。您可以暂时更改这些设置,但环境变量更容易。)

    因此你可以使用:

    GIT_SEQUENCE_EDITOR=script1 GIT_EDITOR=script2 git rebase -i <arguments>
    

    例如,script1edit 替换为 reword,而 script2 则替换为您想要的 s/BB-123/BB-456/

    【讨论】:

    • 谢谢,这听起来正是我想要的。不过,我无法让它正常工作:% GIT_SEQUENCE_EDITOR='perl -pi -e "s/^keep/reword/m"' GIT_EDITOR='perl -pi -e "s/BB-123/BB-456/g"' git rebase -i develop 似乎只接受所有提交而不更改任何内容。
    • 嗯。在前面使用GIT_TRACE=1 运行它可能会很有趣,所以你可以看到它运行。在较旧的 Git 中,rebase 是一个 shell 脚本,每个操作都是显而易见的。在较新的 Git 中,它已用 C 重写以使用序列器,因此它可能不那么明显。它应该工作......
    • 我试了一下,这里有一个要点:gist.github.com/kenahoo/99a16f2afcd274ebafad9e318a1ff90d。不确定那两条git-sh-i18n--envsubst 是什么,应该是编辑器调用吗?
    • 哎呀。这东西对我来说是新的,the documentation for it 是一个真正的射门。 :-)“不要使用它”确实......无论如何,在这种情况下,它似乎决定不需要选择提交(?!),所以它没有生成脚本。如果有的话,那里至少会有更多的“运行命令”行。
    • GIT_SEQUENCE_EDITOR='perl -pi -e "s/^keep/reword/m"' 至少在 git 版本 2.31.1 上应该是 GIT_SEQUENCE_EDITOR='perl -pi -e "s/^pick/reword/m"'
    【解决方案2】:

    您可能正在寻找git filter-branch。假设您的日志如下所示:

    * commit 7534b4609b84b87232ad933c83d5b802adfe2814 (HEAD -> wip/T1234)
    |
    |     More work on ticket #1234
    |
    * commit e23ef0941b7a52dbb46876db4c985a1c30ec5e16
    |
    |     Some work on ticket #1234
    |
    * commit b660a05e4d90fc8ae61b7d39e716ee3cdcc382ec (develop)
    |
    |     Current develop branch head
    |
    * commit 1b67c0b8b1b4f4c22ddc38ba78c499dde749006f
    
          Initial commit
    

    所以,您有从developwip/T1234 的直线提交历史。你意识到票应该读到 #1236,所以你运行:

    $ git filter-branch --msg-filter 'sed -e s/1234/1236/g' \
    >    develop..wip/T1234
    Rewrite 7534b4609b84b87232ad933c83d5b802adfe2814 (2/2) (0 seconds passed,
    remaining 0 predicted)
    Ref 'refs/heads/wip/T1234' was rewritten
    $
    

    现在提交被重写:

    * commit c30e8becea1221d563d2be0e5a8c048c2c5bf608 (HEAD -> wip/T1234)
    |
    |     More work on ticket #1236
    |
    * commit 0417b49944b3c9311031a657bc8be3c8bf05b54d
    |
    |     Some work on ticket #1236
    |
    * commit b660a05e4d90fc8ae61b7d39e716ee3cdcc382ec (develop)
    |
    |     Current develop branch head
    |
    * commit 1b67c0b8b1b4f4c22ddc38ba78c499dde749006f
    
          Initial commit
    

    原始参考的副本将写入refs/original,因此您仍然可以访问预过滤的版本:

    $ git log refs/original/logs/refs/heads/wip/T1234
    ... version with #1234 still in place
    

    显然,您要在删除原件之前仔细检查重写!

    【讨论】:

    • 效果很好,谢谢!我只使用过filter-branch 来摆脱历史记录中的提交或大文件,这是一个很好的学习技能。
    猜你喜欢
    • 1970-01-01
    • 2012-04-24
    • 2017-12-22
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 2015-11-14
    相关资源
    最近更新 更多