gpt4 book ai didi

How to amend several commits in Git to change author(如何修改Git中的多个提交以更改作者)

转载 作者:bug小助手 更新时间:2023-10-22 18:18:18 31 4
gpt4 key购买 nike



I have made a series of commits in Git and I realise now that I forgot to set my user name and user email properties correctly (new machine). I have not yet pushed these commits to my repository, so how can I correct these commits before I do so (only the 3 latest commits on the master branch)?

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



I have been looking at git reset and git commit -C <id> --reset-author, but I don't think I'm on the right track.

我一直在研究git reset和git commit-C<id>-reset author,但我认为我没有走上正轨。


更多回答

Another reason you might want to change the email property is this github error: remote: error: GH007: Your push would publish a private email address. ... ` ! [remote rejected] master -> master (push declined due to email privacy restrictions)`.

您可能想要更改电子邮件属性的另一个原因是github错误:remote:error:GH007:您的推送将发布一个私人电子邮件地址…`![远程拒绝]master->master(由于电子邮件隐私限制,推送被拒绝)`。

Also see stackoverflow.com/q/750172/1340631.

另请参见stackoverflow.com/q/750172/1340631。

优秀答案推荐

Warning: now deprecated in favor of filter-repo.

警告:现在不赞成使用过滤器回购。


Rebase/amend seems inefficient, when you have the power of filter-branch at your fingertips:

当你指尖有过滤分支的力量时,回扣/修正似乎效率低下:


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

(split across lines for clarity, but not necessary)

(为清晰起见,可拆分为多条线,但并非必要)


Be sure to inspect the result when you're done, to make sure that you didn't change anything you didn't mean to!

完成后一定要检查结果,确保你没有改变任何你不想改变的事情!



The interactive rebase approach is pretty nice when used in conjunction with exec. You can run any shell command against a specific commit or all commits in the rebase.

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


First set your git author settings

首先设置git作者设置


git config --global user.name "John Doe"
git config --global user.email [email protected]

Then to reset the author for all commits after the given BASE_SHA:

然后,要为给定BASE_SHA之后的所有提交重置作者:


git rebase -i BASE_SHA -x \
"git commit --amend --author 'John Doe <[email protected]>' -CHEAD"

This will pop up your editor to confirm the changes. All you need to do here is save and quit and it will go through each commit and run the command specified in the -x flag.

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



To change the author only for the last commit:

要仅在最后一次提交时更改作者,请执行以下操作:


git commit --amend --author 'Author Name <[email protected]>' --no-edit

Suppose you only want to change the author for the last N commits:

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


git rebase -i HEAD~4 -x "git commit --amend --author 'Author Name <[email protected]>' --no-edit"

Change the committer as well:

同时更改提交人:


as noted by @sshine and @Hermann.Gruber, the previous commands change the author only. To change the committer as well, you can use the solution proposed by @Hermann.Gruber:

正如@shine和@Hermann.Gruber所指出的,以前的命令只会更改作者。要更改提交人,您可以使用@Hermann.Gruber提出的解决方案:


git rebase -i HEAD~4 -x "GIT_COMMITTER_NAME='Author Name' GIT_COMMITTER_EMAIL='[email protected]' git commit --amend --author 'Author Name <[email protected]>' --no-edit"

NOTES

注释



  • the --no-edit flag makes sure the git commit --amend doesn't ask an extra confirmation

  • when you use git rebase -i, you can manually select the commits where to change the author,


the file you edit will look like this:

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


pick 897fe9e simplify code a little
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <[email protected]>' --no-edit
pick dc18f70 bugfix


The highest voted answer here is now out of date. Git shows this scary warning when using git filter-branch -

这里投票率最高的答案现在已经过时了。Git在使用gitfilter分支时显示了这个可怕的警告-


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 is not (yet) part of git and needs to be installed separately.

filter repo(还)不是git的一部分,需要单独安装。


# Requires git v2.22+ and python v3.5+. Check with -
git --version && python3 --version

# Install using pip
pip3 install git-filter-repo


To replace only the email in previous commits run the the command like this -

要仅替换以前提交中的电子邮件,请运行以下命令-


git filter-repo --email-callback '
return email if email != b"incorrect@email" else b"correct@email"
'

To replace both, email and author name in the previous commits run the the command like this -


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

Make sure the indents are there when you paste the command in your terminal. The callback uses python syntax so indents are important.


Read more about filter-repo callbacks in the docs.



This method was documented by GitHub for this very purpose (though GitHub has since removed it). The steps are:



  1. Open the terminal and make a bare clone of your repo


git clone --bare https://github.com/user/repo.git
cd repo


  1. Edit the following script (replacing OLD_EMAIL, CORRECT_EMAIL, and CORRECT_NAME)


#!/bin/sh

git filter-branch --env-filter '
OLD_EMAIL="[email protected]"
CORRECT_NAME="Your Correct Name"
CORRECT_EMAIL="[email protected]"
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. Copy/paste the script into your terminal and press enter to run it.

  2. Push your changes with git push --force --tags origin 'refs/heads/*' and you're done!



I believe what you are looking for is git rebase --interactive



It allows you to go reset to an specific commit and then go throw the history changing adding or grouping commits



Here you have an explanation https://web.archive.org/web/20100213104931/http://blog.madism.org/index.php/2007/09/09/138-git-awsome-ness-git-rebase-interactive



If you're looking for a script, this one came handy for me.



  1. Download the script from GitHub and save it to an easily-accessible location.



  2. Change the permissions of the script file to allow it to execute:


    chmod +x changeauthor.sh



  3. Navigate into the repository with the incorrect commit history


    cd path/to/repo



  4. Run the script (with or without flags)


    ../path/to/changeauthor.sh --old-email [email protected] \
    --new-email ruto.ka[email protected] --new-name "Kaka Ruto" --remote origin



Be careful as this will rewrite all history in your current dir repository! Good thing is the script give you warnings and info about what you're about to do


Read more here
https://www.adamdehaven.com/blog/update-commit-history-author-information-for-git-repository/



As suggested in this answer git-filter-repo is preferred for the task.


However to simply change author name and/or email one can use --mailmap or --use-mailmap instead of callbacks.


You need to create a mailmap file according to the format (see git-filter-repo/docs or git-scm.com/docs)


Then simply run


git filter-repo --mailmap .mailmap

更多回答

mind explaining this a bit more? not sure what filter branch is

@maxpleaner git filter-branch --help is pretty straightforward :)

see also help.github.com/articles/changing-author-info, which also adds --tag-name-filter cat to the filter-branch in order to migrate tags to the new history. It also uses --branches --tags instead of --all, which only rewrites branch and tag history and leaves other refs alone (though that probably doesn't make much of a difference unless e.g. you're using git-notes)

to perform this on just the last two commits, I replaced -- --all with HEAD~1..HEAD

@nmz787 How many logs are shown if you do git log HEAD~2..HEAD ?

Thank you for introducing me to the -x option. Its pretty awesome! for the -i option I used HEAD~4 to fix my email address on my last 4 commits. worked like a charm.

This is much simpler than filter-branch if you just want to fix your last commits :). Note however, that this changes the timestamp of the commits.

To change the author but maintain the original timestamps, use git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <[email protected]>' -CHEAD"

@Connor git log also showed old authorship for me, but git status correctly identified new commits and after force push they were as I intended.

To rebase all commits including the root use: git rebase -i --root … instead of passing a SHA.

for all commits from root. git rebase -i --root UPTO_COMMIT_SHA -x "git commit --amend --author 'NEW_CHANGE' --no-edit"

I recommend to add --rebase-merges (short -r) option, to keep the topology of your branch intact if it contains some merges.

@ChrisMaes: Please note that git commit --amend --author ... does not change the committer, only the author! So while it may appear that your email was changed, there is, in fact, metadata in the repository that says who the old committer is. While the filter-branch (or filter-repo) methods are more crude, they actually change both. Proof: curl -s https://api.github.com/repos/sshine/author-committer/commits | jq '.[0].commit | { author, committer }' -- I did a git commit --amend --author="John Doe ..." here, and you can see that the committer is not John Doe.

As a note, you can use --root in place of HEAD if trying to specify every commit of the rreo.

@ChrisMaes @sshine to change also the committer information of the 4 latest commits, you can use git rebase -i HEAD~4 -x \ "GIT_COMMITTER_NAME='Author Name' GIT_COMMITTER_EMAIL='Author Name <[email protected]>' git commit --amend --author 'Author Name <[email protected]>' --no-edit"

Thank you. It worked! If you're getting zsh: command not found: pip on a Mac, try pip3 - pip3 install git-filter-repo.

on Windows (in ConEmu terminal), in a venv, I had to swap quotes and make it a one-liner, and add --force (because I made commits since last pushing): git filter-repo --force --email-callback " return email if email != b'wrong@email' else b'correct@email'"

Since the question asked about amending several commits, it's worth noting that filter-repo works on the complete repository by default, and you can specify --refs=branchname or a range of commits like --refs=HEAD^^..HEAD to override.

I followed the same instructions on GitHub that you referenced, and GitHub looks right now. However, I'm a Git newb and not sure how to sync my local repo back up after that. When I pull I get the same "refusing to merge unrelated histories" error mentioned in another answer. I think I need to rebase against that new commit history, but I'd very much appreciate more specific steps.

@enigment if you are happy with the repo as it is on github, you can delete (or perhaps move to another location) the folder you have locally and simply clone from github

Thanks, I know, but that doesn't seem like the idiomatic GitHub/Git way.

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com