Gitで複数のコミットの作成者とコミッターの名前と電子メールを変更するにはどうすればよいですか?


2392

私は学校のコンピューターで簡単なスクリプトを書いて、Gitへの変更をコミットしていました(自宅のコンピューターから複製した、ペンドライブにあるリポジトリで)。いくつかのコミットの後、私はrootユーザーとして何かをコミットしていることに気付きました。

これらのコミットの作者を私の名前に変更する方法はありますか?


13
質問:git filter-branchを使用すると、以前のタグ、バージョン、オブジェクトのSHA1が保持されますか?または、著者名を変更すると、関連するSHA1も強制的に変更されますか?
AndyL 2010

36
ハッシュは変更されます
利用不可

3
接線的に、私は小さなスクリプトを作成し、最終的に根本的な原因を修正しました。gist.github.com/tripleee/16767aa4137706fd896c
tripleee

2
@impinball質問の年齢はほとんど関係ありません。新しい複製質問を作成することは問題外です。私はこの特定の答えを頼む質問を作成できると思いますが、それがそれほど多くの可視性を得るだろうと私は完全には確信していません。ここではGitの質問が不足しているようではありません...とにかく私が手伝ってくれてうれしいです。
tripleee 2014

8
GitHubにはこのための特別なスクリプトがあります:help.github.com/articles/changing-author-info
Timur Bernikovich

回答:


1214

この回答ではを使用git-filter-branchしていますが、ドキュメントではこの警告が表示されます。

git filter-branchには、意図された履歴の書き換えの明白ではないマングリングを生成する可能性のある多くの落とし穴があります(そして、非常に低いパフォーマンスを備えているため、このような問題を調査する時間はほとんどありません)。これらの安全性とパフォーマンスの問題は、下位互換性を保って修正することはできないため、その使用は推奨されません。git filter-repoなどの別の履歴フィルタリングツールを使用してください。それでもgit filter-branchを使用する必要がある場合は、安全性(およびパフォーマンス)を注意深く読み、filter-branchの地雷について学び、そこに記載されている危険を可能な限りできるだけ慎重に回避してください。

著者(またはコミッター)を変更するには、すべての履歴を書き直す必要があります。それで大丈夫で価値があると思うなら、git filter-branchをチェックしてください。manページには、始めるためのいくつかの例が含まれています。また、環境変数を使用して作成者、コミッター、日付などの名前を変更できることにも注意してください。gitmanページの「環境変数」セクションを参照してください

具体的には、次のコマンドを使用して、すべてのブランチとタグの間違った作成者名とメールをすべて修正できます(ソース:GitHubヘルプ)。

#!/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

612
Githubには、help.github.com / articles / changing-author-infoの公開スクリプトがあり、うまく機能します!
defvol '25 / 06/25

34
スクリプトを実行した後、「git update-ref -d refs / original / refs / heads / master」を実行してバックアップブランチを削除できます。
2013

7
@rodowi、それは私のすべてのコミットを複製します。
Rafael Barros 14年

6
@RafaelBarros作成者情報(履歴の他の情報と同様)は、コミットのshaキーの一部です。履歴の変更はすべてのコミットの新しいIDにつながる書き換えです。したがって、共有リポジトリで書き換えたり、すべてのユーザーがそれを認識していることを確認したりしないでください...
johannes

20
使用して解決git push --force --tags origin HEAD:master
mcont 2016年

1577

注:この回答はSHA1を変更するため、すでにプッシュされているブランチで使用する場合は注意してください。名前のスペルを修正するか、古いメールを更新するだけの場合、gitを使用すると、を使用して履歴を書き換えることなくこれを実行できます.mailmap私の他の答えをください。

インタラクティブリベースの使用

あなたができる

git rebase -i -p <some HEAD before all of your bad commits>

次に、リベースファイルですべての不良コミットを「編集」としてマークします。最初のコミットも変更したい場合は、リベースファイルの最初の行として手動で追加する必要があります(他の行のフォーマットに従ってください)。次に、gitが各コミットを修正するように求めてきたら、次のようにします。

 git commit --amend --author "New Author Name <email@address.com>" 

開いているエディターを編集するか、単に閉じてから、

git rebase --continue

リベースを続行します。

--no-edit コマンドを次のように追加することにより、ここでエディターを開くのをスキップできます。

git commit --amend --author "New Author Name <email@address.com>" --no-edit && \
git rebase --continue

シングルコミット

一部のコメンターが指摘したように、最新のコミットを変更するだけの場合は、rebaseコマンドは不要です。するだけ

 git commit --amend --author "New Author Name <email@address.com>"

これは、指定された名前に作者を変更しますが、コミッターは、あなたのように構成でユーザーに設定されますgit config user.namegit config user.email。コミッターを指定したものに設定したい場合、これは作者とコミッターの両方を設定します:

 git -c user.name="New Author Name" -c user.email=email@address.com commit --amend --reset-author

マージコミットに関する注意

私の元の応答にはわずかな欠陥がありました。現在の間のいずれかのマージコミットがある場合HEAD、あなたは<some HEAD before all your bad commits>、その後、git rebaseそれらを平らにします(あなたはGitHubのプルリクエストを使用する場合の方法によって、あなたの歴史の中で、マージコミットのトンがあるように予定されています)。これは非常に頻繁に非常に異なる履歴につながる可能性があり(重複した変更が「リベースされる」可能性があるため)、最悪の場合、git rebase難しいマージの競合(マージコミットですでに解決されている可能性が高い)の解決を要求する可能性があります。解決策は、-pフラグをに使用することですgit rebase。これにより、履歴のマージ構造が保持されます。のマンページではgit rebase、使用する-p-i問題が発生する可能性があることを警告していますが、BUGS 「コミットの編集とコミットメッセージの言い換えは問題なく機能するはずです。」

-p上記のコマンドに追加しました。最新のコミットを変更するだけの場合、これは問題ではありません。


27
奇妙なコミットに
最適

32
典型的な1つの間違いの修正のユースケースを言及するための+1:git commit --amend --author = username
Nathan Kidd

12
これは完璧です。私の最も一般的な使用例は、別のコンピューターに座って作成者を設定するのを忘れているため、通常は5回未満の修正で修正できます。
Zitrax 2010

57
git commit --amend --reset-authorまた、一度だけ機能しuser.nameuser.email正しく構成されます。
2014

14
結局コミットの書き換え著者情報<commit>使用user.nameuser.emailから~/.gitconfig:実行しgit rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit'、保存し、終了します。編集する必要はありません!
ntc2

588

あなたも行うことができます:

git filter-branch --commit-filter '
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD

Windowsコマンドプロンプトでこのコマンドを使用している場合は、次の"代わりに使用する必要があります'

git filter-branch --commit-filter "
        if [ "$GIT_COMMITTER_NAME" = "<Old Name>" ];
        then
                GIT_COMMITTER_NAME="<New Name>";
                GIT_AUTHOR_NAME="<New Name>";
                GIT_COMMITTER_EMAIL="<New Email>";
                GIT_AUTHOR_EMAIL="<New Email>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi" HEAD

4
env-filterを使用する方が簡単な解決策ではありませんか?では、なぜこれがより多くの票を得ているのかわかりません。
stigkj

3
その後、リンクが壊れます。これらの変更を別のリポジトリにどのようにプッシュしますか?
ラッセル

28
env-filterはすべてのコミットを変更します。このソリューションは条件付きを可能にします。
user208769

5
"A previous backup already exists in refs/original/ Force overwriting the backup with -f"申し訳ありませんが、-fこのスクリプトを2回実行すると、-flag がどこにあるのでしょうか。実際、それはブライアンの答えです。フィルターブランチが解決策になった直後の妨害については申し訳ありません。
HHH

2
@ user208769 env-filterは条件付きも許可します。私の答えを見てください:-)
stigkj 2013

559

ライナーは1つですが、マルチユーザーリポジトリがある場合は注意してください。これにより、すべてのコミットが同じ(新しい)作成者とコミッターを持つように変更されます

git filter-branch -f --env-filter "GIT_AUTHOR_NAME='Newname'; GIT_AUTHOR_EMAIL='new@email'; GIT_COMMITTER_NAME='Newname'; GIT_COMMITTER_EMAIL='new@email';" HEAD

文字列に改行がある場合(bashでは可能です):

git filter-branch -f --env-filter "
    GIT_AUTHOR_NAME='Newname'
    GIT_AUTHOR_EMAIL='new@email'
    GIT_COMMITTER_NAME='Newname'
    GIT_COMMITTER_EMAIL='new@email'
  " HEAD

マイナーな点として、害はありませんが、輸出は実際には不必要です。例:git-filter-branch --env-filter "GIT_AUTHOR_NAME = 'New name'; GIT_AUTHOR_EMAIL = 'New email'" HEAD。
Alec the Geek

4
HEADコマンドの最後に指定した場合、なぜすべてのコミットを書き換えるのですか?
Nick Volynkin

1
これは私のbitbucketリポジトリでは機能しません。私はgit push --force --tags origin 'refs/heads/*'助言されたコマンドの後にaを行います
Olorin

1
このため、プッシュコマンドは次のとおりです。$git push --force --tags origin 'refs/heads/master'
過酷なNILESH PATHAK

1
きちんとした; これにより、古いタイムスタンプも保持されます。
DharmaTurtle

221

$ HOME / .gitconfigを初期化していない場合に発生します。あなたはこれを次のように修正できます:

git config --global user.name "you name"
git config --global user.email you@domain.com
git commit --amend --reset-author

gitバージョン1.7.5.4でテスト済み


9
それは最後のコミットで本当にうまくいきます。素敵でシンプル。作品も使用することで、地球規模の変化である必要はありませ--local
Ben

これは私にとって大きな勝者でした!このgit commit --amend --reset-author --no-editコマンドは、間違った作者情報でコミットを作成し、その後、正しい作者を事後的に設定した場合に特に役立ちますgit config。メールを更新する必要があったときに、今すぐa $$を保存しました。
ecbrodie

187

単一のコミットの場合:

git commit --amend --author="Author Name <email@address.com>"

(asmeurerの回答から抽出)


14
ただし、それが最新のコミットである場合に限ります
Richard

4
によるとgit help commitgit commit --amend「現在のブランチの先端」(HEAD)でコミットを変更します。これは通常、最新のコミットですが、最初にまたはでコミットをチェックアウトすることにより、任意のコミットにすることができます。git checkout <branch-name>git checkout <commit-SHA>
Rory O'Kane

12
しかし、これを行うと、そのコミットを親としてすでに持っているすべてのコミットが、間違ったコミットを指していることになります。その時点でフィルターブランチを使用する方が良いでしょう。
John Gietzen

3
@JohnGietzen:それを修正するために変更されたものにコミットをリベースできます。ただし、> 1コミットを実行している場合は、前述のように、フィルター分岐がおそらくはるかに簡単になります。
Thanatos 2013年

5
この変更はコミットのみでauthorあり、committer
Nick Volynkin 2015年

179

上位のいくつかのコミットだけに悪い作者がいる場合、次のようにgit rebase -iexecコマンドと--amendコミットを使用してこれをすべて行うことができます。

git rebase -i HEAD~6 # as required

コミットの編集可能なリストが表示されます:

pick abcd Someone else's commit
pick defg my bad commit 1
pick 1234 my bad commit 2

次に、exec ... --author="..."作者が悪いすべての行の後に行を追加します。

pick abcd Someone else's commit
pick defg my bad commit 1
exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD
pick 1234 my bad commit 2
exec git commit --amend --author="New Author Name <email@address.com>" -C HEAD

保存してエディターを終了します(実行します)。

この解決策は、他のいくつかの解決策よりも入力に時間がかかる場合がありますが、非常に制御可能です。どのようなコミットが発生したかを正確に把握しています。

インスピレーションを与えてくれた@asmeurerに感謝します。


26
間違いなく素晴らしいです。リポジトリのローカル設定でuser.nameとuser.emailを設定することで短縮できますexec git commit --amend --reset-author -C HEADか?そして各行は唯一ですか?
Andrew

1
フィルターブランチを使用するための標準的な答えは、refs / heads / masterを削除しただけです。したがって、制御可能で編集可能なソリューションに+1してください。ありがとう!
jmtd 2014年

Someone else's commit代わりになぜ始めるのmy bad commit 1ですか?私HEAD^^は最後の2つのコミットを修正しようとしたところ、完全にうまくいきました。
fredoverflow 2015年

3
代わりにgit rebase -i HEAD^^^^^^次のように書くこともできますgit rebase -i HEAD~6
PatrickSchlüter

1
これはコミットのタイムスタンプを変更することに注意してください。正しいタイムスタンプに戻すには、stackoverflow.com
a / 11179245/1353267

111

Githubには、次のシェルスクリプトである優れたソリューションがあります。

#!/bin/sh

git filter-branch --env-filter '

an="$GIT_AUTHOR_NAME"
am="$GIT_AUTHOR_EMAIL"
cn="$GIT_COMMITTER_NAME"
cm="$GIT_COMMITTER_EMAIL"

if [ "$GIT_COMMITTER_EMAIL" = "your@email.to.match" ]
then
    cn="Your New Committer Name"
    cm="Your New Committer Email"
fi
if [ "$GIT_AUTHOR_EMAIL" = "your@email.to.match" ]
then
    an="Your New Author Name"
    am="Your New Author Email"
fi

export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'

5
完璧に働きました。ちょうどに持っていたgit reset --hard HEAD^、以前のバージョンにそれらを得るために、他のローカルリポジトリに数回git pull改訂版を-ed、そしてここで私は含む任意の行せずにいますunknown <stupid-windows-user@.StupidWindowsDomain.local>(愛のgitのが不履行になりました)。
アランプラム2011年

1
これ以上押し込めません。「-f」を使用する必要がありますか?
魚モニター

9
しましたgit push -f。また、この後、ローカルリポジトリを再クローンする必要があります。
魚モニター

特定のブランチでシェルスクリプトを実行する必要がある場合は、最後の行を次のように変更できます。
Robert Kajic 2013年

スクリプトが更新されているため、リンク<nice solution>をクリックします
gxpr

82

docgnomeが述べたように、履歴の書き換えは危険であり、他の人のリポジトリを破壊します。

しかし、本当にそれを実行したい場合で、bash環境にいる場合(Linuxでは問題ありません。Windowsでは、gitのインストールで提供されるgit bashを使用できます)、git filter-branchを使用します。

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL'

スピードアップするために、書き換えたいリビジョンの範囲を指定できます:

git filter-branch --env-filter '
  if [ $GIT_AUTHOR_EMAIL = bad@email ];
    then GIT_AUTHOR_EMAIL=correct@email;
  fi;
export GIT_AUTHOR_EMAIL' HEAD~20..HEAD

2
これにより、すべてのタグが古いコミットを指すことに注意してください。--tag-name-filter cat「機能させる」オプションです。
ローマン・スターコフ2014年

@romkynsタグを変更する方法について何かアイデアはありますか?
Nick Volynkin

@NickVolynkinはい、指定します--tag-name-filter cat。これは本当にデフォルトの動作でした。
Roman Starkov

48

別の作者からマージされていないコミットを引き継ぐ場合、これを処理する簡単な方法があります。

git commit --amend --reset-author


1
単一のコミットの場合、ユーザー名を入れたい場合は、これが最も簡単な方法です。
Pedro Benevides

7
--no-editこれをさらに簡単にするために追加できます。一般的に、ほとんどの人はコミットメッセージではなく電子メールアドレスのみを更新することを望んでいるためです
PlagueHammer

あなたたちはただ新しいものとの電子メール/ユーザー名を最後のコミット更新するために、共有のgitコマンドを喜ばせることができます
ADI

やってみましたか?これは副作用です。そうでない場合、stackoverflow.com / a / 2717477/654245は適切なパスのように見えます。
Ryanmt 2016

47

これをエイリアスとして使用できるので、次のことができます。

git change-commits GIT_AUTHOR_NAME "old name" "new name"

または最後の10コミット:

git change-commits GIT_AUTHOR_EMAIL "old@email.com" "new@email.com" HEAD~10..HEAD

〜/ .gitconfigに追加:

[alias]
    change-commits = "!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ \\\"$`echo $VAR`\\\" = '$OLD' ]]; then export $VAR='$NEW'; fi\" $@; }; f "

ソース:https : //github.com/brauliobo/gitconfig/blob/master/configs/.gitconfig

お役に立てれば幸いです。


「git: 'change-commits'はgitコマンドではありません。'git--help 'を参照してください。」
Native_Mobile_Arch_Dev 2017

このコマンドとマスターとの同期の後、履歴内のすべてのコミットが複製されます!他のユーザーでも:(
ウラジミール

予想される@ウラジミール、gitでの歴史の変化について研究してください
brauliobo

私にとっては/ bin / shで実行されているように見えるため、bash固有のテスト[[ ]]をsh互換のテスト[ ](単一のブラケット)に置き換える必要がありました。その上、それは非常にうまく機能します、ありがとう!
Steffen Schwigon

39

これは、@ Brianのバージョンのより精巧なバージョンです。

著者とコミッターを変更するには、次のようにします(bashで可能な文字列に改行を入れます)。

git filter-branch --env-filter '
    if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
    then
        GIT_COMMITTER_NAME="<New name>";
        GIT_COMMITTER_EMAIL="<New email>";
        GIT_AUTHOR_NAME="<New name>";
        GIT_AUTHOR_EMAIL="<New email>";
    fi' -- --all

次のいずれかのエラーが発生する可能性があります。

  1. 一時ディレクトリはすでに存在します
  2. refs / originalで始まる参照はすでに存在します
    (これは、別のフィルターブランチが以前にリポジトリーで実行されており、元のブランチ参照がrefs / originalにバックアップされていることを意味します)

これらのエラーにもかかわらず強制的に実行したい場合は、--forceフラグを追加します。

git filter-branch --force --env-filter '
    if [ "$GIT_COMMITTER_NAME" = "<Old name>" ];
    then
        GIT_COMMITTER_NAME="<New name>";
        GIT_COMMITTER_EMAIL="<New email>";
        GIT_AUTHOR_NAME="<New name>";
        GIT_AUTHOR_EMAIL="<New email>";
    fi' -- --all

-- --allオプションの説明が少し必要になる場合があります。これにより、すべての参照のすべてのリビジョンでフィルターブランチが機能します。(すべてのブランチを含む)の。これは、たとえば、タグも書き換えられ、書き換えられたブランチに表示されることを意味します。

一般的な「間違い」はHEAD代わりに使用することです。つまり、現在のブランチのみのすべてのリビジョンをフィルタリングします。そして、書き換えられたブランチにはタグ(または他の参照)は存在しません。


すべての参照/ブランチでコミットを変更するプロシージャを提供することに対する称賛。
ジョニーUtahh

25

最後の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
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick abb60f9 add new feature
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit
pick dc18f70 bugfix
exec git commit --amend --author 'Author Name <author.name@mail.com>' --no-edit

その後、一部の行を変更して、作成者を変更する場所を確認できます。これにより、自動化と制御の中間点が得られます。実行されるステップが表示され、保存するとすべてが一度に適用されます。


驚くばかり!ありがとうございました!
Pablo Lalloni、

HEAD〜8を使用しましたが、最後の8回のコミットよりもはるかに多く表示されます。
ブライアンブライス

1
@BryanBryceマージコミットが関係している場合、事態は複雑になります:)
Chris Maes

@ChrisMaesああ、何が起こっているのかわかります。私はそれらを台無しにしたくありません、私がいるブランチ上でだけです。
ブライアンブライス

:その場合は、あなたは、あなたがマスターから分岐した可能性が想定さgit rebase -i master -x ...
クリスマース

23
  1. 走る git rebase -i <sha1 or ref of starting point>
  2. 変更するすべてのコミットにマークを付けるedit(またはe
  3. すべてのコミットを処理するまで、次の2つのコマンドをループします。

    git commit --amend --reuse-message=HEAD --author="New Author <new@author.email>" ; git rebase --continue

これにより、他のすべてのコミット情報(日付を含む)が保持されます。この--reuse-message=HEADオプションは、メッセージエディターが起動しないようにします。


23

以下を使用して、タグとすべてのブランチを含むリポジトリ全体の作成者を書き換えます。

git filter-branch --tag-name-filter cat --env-filter "
  export GIT_AUTHOR_NAME='New name';
  export GIT_AUTHOR_EMAIL='New email'
" -- --all

次に、filter-branchのMANページで説明されているように、によってバックアップされたすべての元の参照を削除しますfilter-branch(これは破壊的なため、最初にバックアップします)。

git for-each-ref --format="%(refname)" refs/original/ | \
xargs -n 1 git update-ref -d

2
を使用することは非常に重要--tag-name-filter catです。そうしないと、タグはコミットの元のチェーンに残ります。他の答えはこれに言及することに失敗します。
jeberle 14年

21

シンプルなものを取り込むことで機能するこのソリューションを採用しましたauthor-conv-file(形式はgit-cvsimportの場合と同じです)。author-conv-fileすべてのブランチで定義されているすべてのユーザーを変更することで機能します。

これをと組み合わせて使用​​してcvs2git、リポジトリをcvsからgitに移行しました。

すなわちサンプル author-conv-file

john=John Doe <john.doe@hotmail.com>
jill=Jill Doe <jill.doe@hotmail.com>

スクリプト:

 #!/bin/bash

 export $authors_file=author-conv-file

 git filter-branch -f --env-filter '

 get_name () {
     grep "^$1=" "$authors_file" |
     sed "s/^.*=\(.*\) <.*>$/\1/"
 }

 get_email () {
     grep "^$1=" "$authors_file" |
     sed "s/^.*=.* <\(.*\)>$/\1/"
 }

 GIT_AUTHOR_NAME=$(get_name $GIT_COMMITTER_NAME) &&
     GIT_AUTHOR_EMAIL=$(get_email $GIT_COMMITTER_NAME) &&
     GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME &&
     GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL &&
     export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
     export GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 ' -- --all

おかげで、なぜこれがgit(またはgit-svn)のコア機能ではないのでしょうか。これはgit svn cloneのフラグで行うことができますが、git filter-branchではできません...
Daniel Hershcovich

20

唯一の問題が作者/メールアドレスがいつもと違うということであれば、これは問題ではないことを指摘しておきます。正しい修正は、次の.mailmapような行でディレクトリのベースに呼び出されるファイルを作成することです

Name you want <email you want> Name you don't want <email you don't want>

それ以降、などのコマンドは、git shortlogこれら2つの名前が同じであると見なします(特に指示しない限り)。http://schacon.github.com/git/git-shortlog.htmlを参照してくださいを。

これには、上流を使用している場合に問題が発生する可能性がある履歴を書き換える必要がないという点で、他のすべてのソリューションの利点があり、常に誤ってデータを損失する良い方法です。

もちろん、自分で何かをコミットし、それが本当に他の誰かである必要があり、この時点で履歴を書き換えても構わない場合、コミットの作成者を変更することは、おそらく帰属目的のために良い考えです(この場合、他の答えはこちら)。


18

特に、他の開発者からのパッチをコミットする場合、これは本質的に彼らのコードを盗むでしょう。

以下のバージョンはすべてのブランチで機能し、それを防ぐために作成者とコミッターを個別に変更します。

allオプションのleif81への称賛。

#!/bin/bash

git filter-branch --env-filter '
if [ "$GIT_AUTHOR_NAME" = "<old author>" ];
then
    GIT_AUTHOR_NAME="<new author>";
    GIT_AUTHOR_EMAIL="<youmail@somehost.ext>";
fi
if [ "$GIT_COMMITTER_NAME" = "<old committer>" ];
then
    GIT_COMMITTER_NAME="<new commiter>";
    GIT_COMMITTER_EMAIL="<youmail@somehost.ext>";
fi
' -- --all

18
  1. コミットauthor name & emailAmendに変更し、次に置き換えold-commit with new-oneます。

    $ git checkout <commit-hash>                            # checkout to the commit need to modify  
    $ git commit --amend --author "name <author@email.com>" # change the author name and email
    
    $ git replace <old-commit-hash> <new-commit-hash>      # replace the old commit by new one
    $ git filter-branch -- --all                           # rewrite all futures commits based on the replacement                   
    
    $ git replace -d <old-commit-hash>     # remove the replacement for cleanliness 
    $ git push -f origin HEAD              # force push 
    
  2. 別の方法Rebasing

    $ git rebase -i <good-commit-hash>      # back to last good commit
    
    # Editor would open, replace 'pick' with 'edit' before the commit want to change author
    
    $ git commit --amend --author="author name <author@email.com>"  # change the author name & email
    
    # Save changes and exit the editor
    
    $ git rebase --continue                # finish the rebase
    

2
とてもいい答えです。変更が
最終

12

これを行う最も速くて簡単な方法は、git rebaseの--exec引数を使用することです。

git rebase -i -p --exec 'git commit --amend --reset-author --no-edit'

これにより、次のようなtodoリストが作成されます。

pick ef11092 Blah blah blah
exec git commit --amend --reset-author --no-edit
pick 52d6391 Blah bloh bloo
exec git commit --amend --reset-author --no-edit
pick 30ebbfe Blah bluh bleh
exec git commit --amend --reset-author --no-edit
...

これはすべて自動的に機能し、何百ものコミットがあるときに機能します。


9

このリポジトリの唯一のユーザーである場合は、(svickが書いたように)または/ plusフィルタースクリプト(docgnome answerで参照されている記事で説明されているように)、またはインタラクティブなリベースを使用して、履歴書き換えることができます。しかし、これらのどちらでも、最初に変更されたコミット以降のリビジョンが変更されます。これは、ブランチのリライトに基づいて変更を行った人にとっては問題になります。git filter-branchgit fast-exportgit fast-import

回復

他の開発者が自分の作業を書き換え前のバージョンに基づいて行わなかった場合、最も簡単な解決策は再クローン(再度クローン)することです。

またはgit rebase --pull、リポジトリに変更がない場合は早送りするか、書き直されたコミットに基づいてブランチをリベースすることもできます(書き換え前のコミットを永久に保持するため、マージは避けたい)。これらのすべては、彼らが仕事をコミットしていないことを前提としています。git stashそうでなければ変更を隠しておくために使用します。

他の開発者が機能ブランチを使用したりgit pull --rebase、アップストリームが設定されていないなどの理由で機能しない場合は、書き換え後のコミットに基づいて作業をリベースする必要があります。たとえば、新しい変更(git fetch)をフェッチした直後にmaster、/に基づくブランチの場合、origin/master実行する必要があります

$ git rebase --onto origin/master origin/master@{1} master

これorigin/master@{1}は、書き換え前の状態(フェッチ前)です。gitrevisionsを参照してください。


代わりの解決策は、バージョン1.6.5以降、Gitで利用可能なrefs / replace /メカニズムを使用することです。このソリューションでは、間違ったメールがあるコミットの代わりを提供します。その後、レフリー(のようなもの「置き換える」フェッチ誰fetch = +refs/replace/*:refs/replace/*で適切な場所にrefspec 彼らは .git/config)透過的に代替品になるだろう、とそれらのREFをフェッチしていない人たちは、古いコミットを見るでしょう。

手順は次のようになります。

  1. 間違ったメールですべてのコミットを見つけてください、例えば

    $ git log --author=user@wrong.email --all
    
  2. 間違ったコミットごとに、代わりのコミットを作成し、オブジェクトデータベースに追加します

    $ git cat-file -p <ID of wrong commit> | 
      sed -e 's/user@wrong\.email/user@example.com/g' > tmp.txt
    $ git hash-object -t commit -w tmp.txt
    <ID of corrected commit>
    
  3. オブジェクトデータベースのコミットを修正したので、次のgit replaceコマンドを使用して、間違ったコミットを修正されたコミットに自動的かつ透過的に置き換えるようにgitに指示する必要があります。

    $ git replace <ID of wrong commit> <ID of corrected commit>
    
  4. 最後に、すべての代替品をリストして、この手順が成功したかどうかを確認します

    $ git replace -l
    

    交換が行われるかどうかを確認します

    $ git log --author=user@wrong.email --all
    

もちろん、この手順を自動化することもできます。まあ、git replace(まだ)バッチモードがないものを使用する場合を除き、シェルループを使用するか、「手動」で置き換える必要があります。

未検証!YMMV。

refs/replace/メカニズムを使用すると、いくつかの荒いコーナーに遭遇する可能性があることに注意してください。それは新しいものであり、まだ十分にテストされていません


6

修正したいコミットが最新のものであり、それらだけのカップルの場合は、の組み合わせを使用することができますgit resetし、git stash右の名前とメールアドレスを設定した後、再びそれらをコミット戻って。

シーケンスは次のようになります(2つの誤ったコミット、保留中の変更がない場合)。

git config user.name <good name>
git config user.email <good email>
git reset HEAD^
git stash
git reset HEAD^
git commit -a
git stash pop
git commit -a

5

EGitでEclipseを使用している場合、非常に簡単な解決策があります。
前提:ローカルブランチ 'local_master_user_x'にコミットがありますが、ユーザーが無効なため、リモートブランチ 'master'にプッシュできません。

  1. リモートブランチ「マスター」をチェックアウト
  2. 'local_master_user_x'に変更が含まれているプロジェクト/フォルダー/ファイルを選択します
  3. 右クリック-置換-ブランチ-'local_master_user_x'
  4. 今回は正しいユーザーとして、ローカルブランチの「マスター」に、これらの変更を再度コミットします。
  5. リモートの「マスター」にプッシュ

5

インタラクティブなリベースを使用すると、変更する各コミットの後に修正コマンドを配置できます。例えば:

pick a07cb86 Project tile template with full details and styling
x git commit --amend --reset-author -Chead

3
この問題は、他のコミットメタデータ(日付や時刻など)も修正されることです。私はそれを難し​​い方法で見つけました;-)
2013

5

gitには2つの異なる電子メールアドレスが格納されていることに注意してください。1つはコミッター(変更をコミットした人)用で、もう1つは作成です。(変更を作成した人)用です。

コミッター情報はほとんどの場所で表示されませんが、それで確認できますgit log -1 --format=%cn,%ce(または特定のコミットを指定するshow代わりに使用logします)。

最後のコミットの作成者を変更するのはと同じくらい簡単git commit --amend --author "Author Name <email@example.com>"ですが、コミッター情報に対して同じことをするためのワンライナーまたは引数はありません。

解決策は、ユーザーの情報を(一時的に、または一時的に)変更し、次にコミットを修正することです。これにより、コミッターが現在の情報に更新されます。

git config user.email my_other_email@example.com 
git commit --amend

古い値がまだいくつかの場所にあることに注意してくださいpath\to\repo\.git。完全に抹消するために何をする必要があるのか​​、私にはまだわかりません。残念ながら修正(?)は消えないようです。
ruffin 2014年

5

今日、著者名のUTF8文字がビルドサーバーで問題を引き起こしているという問題が発生したため、これを修正するために履歴を書き直す必要がありました。実行された手順は次のとおりです。

手順1:https : //help.github.com/articles/setting-your-username-in-git/の指示に従って、将来のすべてのコミットのためにgitでユーザー名を変更します

ステップ2:次のbashスクリプトを実行します。

#!/bin/sh

REPO_URL=ssh://path/to/your.git
REPO_DIR=rewrite.tmp

# Clone the repository
git clone ${REPO_URL} ${REPO_DIR}

# Change to the cloned repository
cd ${REPO_DIR}

# Checkout all the remote branches as local tracking branches
git branch --list -r origin/* | cut -c10- | xargs -n1 git checkout

# Rewrite the history, use a system that will preseve the eol (or lack of in commit messages) - preferably Linux not OSX
git filter-branch --env-filter '
OLD_EMAIL="me@something.com"
CORRECT_NAME="New Me"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
fi
' --tag-name-filter cat -- --branches --tags

# Force push the rewritten branches + tags to the remote
git push -f

# Remove all knowledge that we did something
rm -rf ${REPO_DIR}

# Tell your colleagues to `git pull --rebase` on all their local remote tracking branches

概要:リポジトリを一時ファイルにチェックアウトし、すべてのリモートブランチをチェックアウトし、履歴を書き換えるスクリプトを実行し、新しい状態を強制的にプッシュし、変更を取得するためにリベースプルを行うようにすべての同僚に伝えます。

OS Xでこれを実行すると、コミットメッセージの行末がどういうわけか混乱し、後でLinuxマシンで再実行する必要があったため、問題が発生しました。


5

あなたの問題は本当に一般的です。「を参照してください修正著者GitリポジトリのリストにMailmapの使い方

簡単にするために、プロセスを簡単にするスクリプトを作成しました:git-changemail

そのスクリプトをパスに配置した後、次のようなコマンドを発行できます。

  • 現在のブランチで著者の一致を変更する

    $ git changemail -a old@email.com -n newname -m new@email.com
    
  • <branch>および<branch2>で作成者とコミッターの一致を変更します。-fフィルターブランチに渡して、バックアップの書き換えを許可する

    $ git changemail -b old@email.com -n newname -m new@email.com -- -f &lt;branch> &lt;branch2>
    
  • リポジトリに既存のユーザーを表示する

    $ git changemail --show-both
    

ちなみに、変更を行った後は、git-backup-cleanを使用してフィルターブランチからバックアップをクリーンアップします。


1
コマンドを実行すると、「fatal:cannot exec 'git-changemail':Permission denied」と表示される
Govind


3

私の例も追加したいと思います。与えられたパラメーターでbash_functionを作成します。

これはmint-linux-17.3で動作します

# $1 => email to change, $2 => new_name, $3 => new E-Mail

function git_change_user_config_for_commit {

 # defaults
 WRONG_EMAIL=${1:-"you_wrong_mail@hello.world"}
 NEW_NAME=${2:-"your name"}
 NEW_EMAIL=${3:-"new_mail@hello.world"}

 git filter-branch -f --env-filter "
  if [ \$GIT_COMMITTER_EMAIL = '$WRONG_EMAIL' ]; then
    export GIT_COMMITTER_NAME='$NEW_NAME'
    export GIT_COMMITTER_EMAIL='$NEW_EMAIL'
  fi
  if [ \$GIT_AUTHOR_EMAIL = '$WRONG_EMAIL' ]; then
    export GIT_AUTHOR_NAME='$NEW_NAME'
    export GIT_AUTHOR_EMAIL='$NEW_EMAIL'
  fi
 " --tag-name-filter cat -- --branches --tags;
}

2

あなたがこのリポジトリの唯一のユーザーであるか、他のユーザーのリポジトリを壊す可能性を気にしていない場合は、はい。これらのコミットをプッシュし、それらが他のどこかにアクセスできる場所に存在する場合は、他の人のリポジトリを壊すことを気にしない限り、できません。問題は、これらのコミットを変更することで、新しいSHAを生成し、別のコミットとして扱われるようにすることです。他の誰かがこれらの変更されたコミットを取り込もうとするとき、歴史は異なり、カブームです。

このページhttp://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.htmlでは、その方法について説明しています。(私はこれを試していないので、YMMV)


したがって、user.emailを書き換える安全な方法はありません。他の全員を爆破することなく。歴史を書き換えることは悪い考えであることは知っていましたが、安全にそれを行うためのクリーンな方法があるのではないかと思いました。ありがとう。
manumoomoo 2010

@mediaslave:refs/replace/メカニズムを試してください。
JakubNarębski10年

meta.stackexchange.com/a/8259/184684-別名、リンクを合計してそれらを回答にします。
ruffin 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.