【问题标题】:What's the fastest way to edit hundreds of Git commit messages?编辑数百条 Git 提交消息的最快方法是什么?
【发布时间】:2013-01-15 06:56:59
【问题描述】:

我有一个相当大的 Git 存储库,其中包含 1000 次提交,最初是从 SVN 导入的。在我公开我的 repo 之前,我想清理数百条在我的新 repo 中没有意义的提交消息,并删除所有添加的 git-svn 信息文本。

我知道我可以使用 'git rebase -i' 然后 'git commit --amend' 来编辑每个单独的提交消息,但是要编辑数百条消息,这对你来说是一个巨大的痛苦 -什么。

有没有更快的方法来编辑所有这些提交消息?理想情况下,我会将每条提交消息都列在一个文件中,我可以在一个地方对其进行编辑。

谢谢!

【问题讨论】:

    标签: git


    【解决方案1】:

    这是一个老问题,但由于没有提到git filter-branch,我只加了两分钱。

    我最近不得不在提交消息中大量替换文本,用另一个文本块替换一个文本块,而不更改其余的提交消息。例如,我必须将 Refs: #xxxxx 替换为 Refs: #22917

    我像这样使用git filter-branch

    git filter-branch --msg-filter 'sed "s/Refs: #xxxxx/Refs: #22917/g"' master..my_branch
    
    • 我使用选项 --msg-filter 仅编辑提交消息,但您可以使用其他过滤器来更改文件、编辑完整提交信息等。
    • 我通过将 filter-branch 仅应用于不在 master (master..my_branch) 中的提交来限制filter-branch,但您可以通过省略提交范围将其应用于整个分支。

    按照文档中的建议,在您的分支副本上尝试此操作。 希望对您有所帮助。


    用于回答的来源

    【讨论】:

    • --msg-filter 选项在 STDOUT 上输出提交消息并在 STDIN 上接收新的提交消息,因此您需要使用“sed”而不是“sed -i”:
      git filter -branch --msg-filter 'sed "s/Refs: #xxxxx/Refs: #22917/g"' master..my_branch 
    • @SimonDesfarges 你完全正确!不行,我马上更新答案
    • 如果您按照@LexLustor 的建议在您的分支副本中执行此操作,您可能会在git filter-branch 操作之后留下一个杂散的引用。如果是这样,您可以这样做以摆脱剩余的引用:git update-ref -d refs/original/refs/heads/your-temp-branch-name
    【解决方案2】:

    这很容易做到:

    • 执行首次导入。
    • 将所有提交导出为文本:

      git format-patch -10000
      

      数量应大于提交总数。这将创建大量名为 NNNNN-commit-description.patch 的文件。

    • 使用一些脚本编辑这些文件。 (不要触摸其中的任何内容,除了带有提交消息的顶部)。
    • 将已编辑的文件复制或移动到空的 git 存储库或分支。
    • 将所有已编辑的提交导入回来:

      git am *.patch
      

    这仅适用于单个分支,但效果很好。

    【讨论】:

    • 看起来很有希望,谢谢!不幸的是,在运行 'git am *.patch' 时出现“错误的文件编号”错误。我在 Windows 7 上,快速的 Google 搜索似乎表明它与超过命令行参数的最大数量有关,考虑到每个提交都有一个补丁文件,这是有道理的。稍后我会在我的 Mac 上尝试一下。
    • 你可以小批量做,只要确保顺序递增
    • ls *.patch | xargs git am 自动完成。
    • 当然可以,但是在 Windows 上,您需要先安装 mingw 或 cygwin。在 Linux 或 Mac 上启动它要容易得多。
    • 使用“git am --committer-date-is-author-date”保存提交日期
    【解决方案3】:

    现在推荐使用 git-filter-repo https://github.com/newren/git-filter-repo。我像这样使用它:

    PS C:\repository> git filter-repo --commit-callback '
    >> msg = commit.message.decode(\"utf-8\")
    >> newmsg = msg.replace(\"old string\", \"new string\")
    >> commit.message = newmsg.encode(\"utf-8\")
    >> ' --force
    New history written in 328.30 seconds; now repacking/cleaning...
    Repacking your repo and cleaning out old unneeded objects
    HEAD is now at 087f91945a blah blah
    Enumerating objects: 346091, done.
    Counting objects: 100% (346091/346091), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (82068/82068), done.
    Writing objects: 100% (346091/346091), done.
    Total 346091 (delta 259364), reused 346030 (delta 259303), pack-reused 0
    Completely finished after 443.37 seconds.
    PS C:\repository>
    

    你可能不想复制powershell额外的东西,所以这里只是命令:

    git filter-repo --commit-callback '
    msg = commit.message.decode(\"utf-8\")
    newmsg = msg.replace(\"old string\", \"new string\")
    commit.message = newmsg.encode(\"utf-8\")
    ' --force
    

    如果您想击中所有分支,请不要使用--refs HEAD。如果您不想使用--force,您可以在干净的git clone --no-checkout 上运行它。这让我开始了:https://blog.kawzeg.com/2019/12/19/git-filter-repo.html

    【讨论】:

      【解决方案4】:

      您可以使用git rebase -i 并将pick 替换为reword(或只是r)。然后 git rebase 在每次提交时停止,让您有机会编辑消息。

      唯一的缺点是您不会一次看到所有消息,并且在发现错误时无法返回。

      【讨论】:

      • 这不是要走的路。一次打开 1000 条提交消息大约需要 8.5 小时才能完成所有这些消息。计算大约 30 秒的消息
      • @Whitecat 我误解了这个问题,所以你想做一些手动清理,但你想要一些自动化的东西。那么another answer中提到的git filter-branch有什么问题呢?
      • 我遇到了git filter-patch 的问题,它只显示补丁而不是提交。我有超过 6000 条要更改的提交消息。但是当我使用git filter-patch -100000 HEAD 时,我只得到 500 个补丁文件。
      • @Whitecat 这很奇怪。我刚刚尝试过git filter-branch --msg-filter 'echo "foo: " && cat',它在 20 秒内重写了近 3000 次提交(我所拥有的全部)。恕我直言,非常适合您的需要。如果它对您不起作用,请将详细信息添加到问题中 - 或者最好再写一个。 +++ 我假设,您的意思是过滤器-branch,而不是过滤器-patch
      • @Whitecat 这很简单,使用你最喜欢的 Unix 工具,例如,git filter-branch --msg-filter 'perl -pe "s/issue-\\d{1,4}/Task/"'。我不确定是否需要转义,因此请尝试添加或删除反斜杠。如果事情变得复杂,编写一个 shell 或 perl 脚本。
      【解决方案5】:

      一个伟大而简单的方法是使用git filter-branch --msg-filter "" 和python 脚本。

      python 脚本看起来像这样:

      import os
      import sys
      import re
      
      pattern = re.compile("(?i)Issue-\d{1,4}")
      
      
      commit_id = os.environ["GIT_COMMIT"]
      message   = sys.stdin.read()
      
      if len(message) > 0:
      
          if pattern.search(message):
              message = pattern_conn1.sub("Issue",message)
      
      print message
      

      您要进行的命令行调用是git filter-branch -f --msg-filter "python /path/to/git-script.py"

      【讨论】:

        【解决方案6】:

        作为替代方案,请考虑跳过整个存储库的导入。我会简单地检查、清理并提交历史记录中的重要点。

        【讨论】:

          【解决方案7】:

          我混合使用这两种解决方案:

          1. Vscodium 和扩展“Git rebase shortcut”以简单的方式使用git rebase -i

          2. Git history editor,它允许:

          • 批量修改姓名+电子邮件
          • 在精美的界面中改写 Git 提交消息
          • 使用日期选择器更改提交日期

          您粘贴提交,然后使用 Web 界面进行更改,它会为您提供正确的 git filter-branch 命令以粘贴到终端中。

          界面截图:

          祝你好运!

          【讨论】:

            猜你喜欢
            • 2011-11-30
            • 2018-11-10
            • 2015-05-19
            • 1970-01-01
            • 2023-03-12
            • 2011-11-27
            • 1970-01-01
            • 2011-11-08
            • 2011-04-25
            相关资源
            最近更新 更多