【问题标题】:How to amend several commits in Git to change author如何修改 Git 中的多个提交以更改作者
【发布时间】:2011-06-26 06:02:30
【问题描述】:

我在 Git 中进行了一系列提交,现在我意识到我忘记正确设置我的用户名和用户电子邮件属性(新机器)。我还没有将这些提交推送到我的存储库,那么在我这样做之前如何更正这些提交(只有主分支上的 3 个最新提交)?

我一直在关注git resetgit commit -C <id> --reset-author,但我认为我的方向并不正确。

【问题讨论】:

  • 您可能想要更改电子邮件属性的另一个原因是这个 github 错误:remote: error: GH007: Your push would publish a private email address. ... `! [远程拒绝] master -> master(由于电子邮件隐私限制而拒绝推送)`。

标签: git git-commit git-rewrite-history


【解决方案1】:

当您触手可及 filter-branch 的功能时,rebase/amend 似乎效率低下:

git filter-branch --env-filter 'if [ "$GIT_AUTHOR_EMAIL" = "incorrect@email" ]; then
     GIT_AUTHOR_EMAIL=correct@email;
     GIT_AUTHOR_NAME="Correct Name";
     GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL;
     GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; fi' -- --all

(为了清楚起见,分行,但不是必需的)

请务必在完成后检查结果,以确保您没有更改任何您无意更改的内容!

【讨论】:

  • 介意再解释一下吗?不确定过滤器分支是什么
  • @maxpleaner git filter-branch --help 非常简单:)
  • 另请参阅help.github.com/articles/changing-author-info,它还将--tag-name-filter cat 添加到filter-branch,以便将标签迁移到新的历史记录。它还使用--branches --tags 而不是--all,它只会重写分支和标签历史记录,而单独留下其他refs(尽管这可能没有太大区别,除非您使用git-notes)跨度>
  • 为了在 just 最后两次提交上执行此操作,我将 -- --all 替换为 HEAD~1..HEAD
  • @nmz787 git log HEAD~2..HEAD 会显示多少日志?
【解决方案2】:

与 exec 结合使用时,交互式 rebase 方法非常好。您可以针对特定提交或 rebase 中的所有提交运行任何 shell 命令。

首先设置你的 git 作者设置

git config --global user.name "John Doe"
git config --global user.email johndoe@example.com

然后为给定 SHA 之后的所有提交重置作者

git rebase -i YOUR_SHA -x "git commit --amend --reset-author -CHEAD"

这将弹出您的编辑器以确认更改。您需要在这里做的就是保存并退出,它将通过每次提交并运行 -x 标志中指定的命令。

根据下面@Dave 的评论,您还可以在保持原始时间戳的同时更改作者:

git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"

【讨论】:

  • 感谢您向我介绍 -x 选项。它非常棒!对于 -i 选项,我使用 HEAD~4 来修复我最近 4 次提交的电子邮件地址。像魅力一样工作。
  • 如果你只想修复你的最后一次提交,这比filter-branch 简单得多:)。但是请注意,这会更改提交的时间戳。
  • 要更改作者但保持原始时间戳,请使用git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name &lt;new_address@example.com&gt;' -CHEAD"
  • @Connor git log 也显示了我的旧作者身份,但 git status 正确识别了新提交,并且在强制推送后它们符合我的预期。
  • 要 rebase 所有提交,包括 root 使用:git rebase -i --root … 而不是传递 SHA。
【解决方案3】:

仅更改最后一次提交的作者:

git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit

假设您只想更改最后 N 次提交的作者:

git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit"

注意事项

  • --no-edit 标志确保git commit --amend 不要求额外确认
  • 当你使用git rebase -i时,你可以手动选择要更改作者的提交,

您编辑的文件将如下所示:

pick 897fe9e simplify code a little
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick dc18f70 bugfix

【讨论】:

  • 来自根目录的所有提交。 git rebase -i --root UPTO_COMMIT_SHA -x "git commit --amend --author 'NEW_CHANGE' --no-edit"
  • 我建议添加--rebase-merges(简称-r)选项,以保持分支的拓扑结构完整,如果它包含一些合并。
【解决方案4】:

GitHub 出于此目的记录了此方法(尽管 GitHub 已将其删除)。步骤是:

  1. 打开终端并为您的仓库制作一个克隆
git clone --bare https://github.com/user/repo.git
cd repo
  1. 编辑以下脚本(替换 OLD_EMAILCORRECT_EMAILCORRECT_NAME
#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="your-old-email@example.com"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="your-correct-email@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
  1. 将脚本复制/粘贴到您的终端,然后按 Enter 键运行它。
  2. 使用git push --force --tags origin 'refs/heads/*' 推送您的更改,您就完成了!

【讨论】:

  • 我在 GitHub 上按照您引用的相同说明进行操作,现在 GitHub 看起来很像。但是,我是一个 Git 新手,不知道之后如何同步我的本地仓库。当我拉动时,我得到另一个答案中提到的相同的“拒绝合并不相关的历史”错误。我认为我需要根据新的提交历史重新设置基准,但我非常感谢更具体的步骤。
  • @enigment 如果你对 github 上的 repo 感到满意,你可以删除(或者移动到另一个位置)你在本地拥有的文件夹,然后简单地从 github 克隆
  • 谢谢,我知道,但这似乎不像是惯用的 GitHub/Git 方式。
【解决方案5】:

我相信你要找的是git rebase --interactive

它允许您重置到特定的提交,然后抛出历史更改添加或分组提交

这里有解释https://web.archive.org/web/20100213104931/http://blog.madism.org/index.php/2007/09/09/138-git-awsome-ness-git-rebase-interactive

【讨论】:

    【解决方案6】:

    如果您正在寻找脚本,这个对我来说很方便。

    1. GitHub 下载脚本并将其保存到易于访问的位置。

    2. 更改脚本文件的权限以允许其执行:

      chmod +x changeauthor.sh

    3. 使用错误的提交历史导航到存储库

      cd path/to/repo

    4. 运行脚本(带或不带标志)

      ../path/to/changeauthor.sh --old-email kaka.ruto@example.com \
          --new-email ruto.kaka@example.com --new-name "Kaka Ruto" --remote origin
      

    小心,因为这将重写您当前目录存储库中的所有历史记录!好消息是脚本会为您提供有关您将要执行的操作的警告和信息

    在这里阅读更多 https://www.adamdehaven.com/blog/update-commit-history-author-information-for-git-repository/

    【讨论】:

      【解决方案7】:

      此处投票最高的答案现已过时。 Git 在使用 git filter-branch 时显示这个可怕的警告 -

      WARNING: git-filter-branch has a glut of gotchas generating mangled history
               rewrites. Hit Ctrl-C before proceeding to abort, then use an
               alternative filtering tool such as 'git filter-repo'
               (https://github.com/newren/git-filter-repo/) instead.
      

      要将filter-repo 命令用作suggested by git-

      1. 安装命令,使用 pip -

        pip install git-filter-repo
        (需要 git v2.22+ 和 python v3.5+。检查git --version &amp;&amp; python3 --version

      2. 修复提交

        • 仅限电子邮件

          git filter-repo --email-callback '
              return email if email != b"incorrect@email" else b"correct@email"
          ' 
          
        • 电子邮件和作者姓名

          git filter-repo --commit-callback '
              if commit.author_email == b"incorrect@email":
                  commit.author_email = b"correct@email" 
                  commit.author_name = b"Correct Name"
                  commit.committer_email = b"correct@email" 
                  commit.committer_name = b"Correct Name"
          ' 
          

      当您将命令粘贴到终端时,请确保有缩进。回调使用 python 语法,所以缩进很重要。

      阅读更多关于 filter-repo 回调的信息here

      【讨论】:

        【解决方案8】:

        如果您对贬低和修改感到不安全,您可以这样做。同时,您还将设置您可能打算做的全局配置。

        git reset HEAD~(撤消上次提交)

        git config --global user.name "Your Name"

        git config --global user.email you@example.com

        git commit -m "message"

        【讨论】:

          猜你喜欢
          • 2018-11-21
          • 1970-01-01
          • 2013-12-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多