著者を変更するためにGitのいくつかのコミットを修正する方法


180

私はGitで一連のコミットを行いましたが、ユーザー名とユーザーのメールプロパティを正しく設定するのを忘れたことに気づきました(新しいマシン)。これらのコミットをリポジトリにまだプッシュしていません。そうする前に、これらのコミットを修正するにはどうすればよいですか(masterブランチの最新の3つのコミットのみ)。

とを見てきましたが、正しい方向に進んでいるgit resetgit commit -C <id> --reset-authorは思いません。


1
emailプロパティを変更したいもう1つの理由は、次のgithubエラーです:remote: error: GH007: Your push would publish a private email address.... `![リモートで拒否されました]マスター->マスター(メールのプライバシー制限によりプッシュが拒否されました) `。
craq

stackoverflow.com/q/750172/1340631も参照してください。
scai

回答:


232

あなたの指先にフィルターブランチの力があるとき、リベース/修正は非効率的に見えます:

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

(明確にするために行をまたいで分割していますが、必須ではありません)

完了したら必ず結果を調べて、意図していないものを変更していないことを確認してください。


これについてもう少し説明してもらえますか?フィルターブランチが何かわからない
max pleaner 2014

1
@maxpleaner git filter-branch --helpは非常に単純です:)
アレディアフェリア

3
また、help.github.com / articles / changing-author-infoも参照してください。これ--tag-name-filter catfilter-branch、タグを新しい履歴に移行するためにに追加されます。また、の--branches --tags代わりに使用します--all。これは、ブランチとタグの履歴を書き換えるだけで、その他refsはそのままにします(たとえば、を使用している場合を除いて、それほど大きな違いはありませんgit-notes
Tobias Kienzler

12
でこれを実行するだけで、最後の2つのコミット、私は交換し-- --allHEAD~1..HEAD
nmz787

1
@ nmz787すると、いくつのログが表示されますかgit log HEAD~2..HEAD
Jona

148

インタラクティブなリベースアプローチは、execと組み合わせて使用​​すると非常に便利です。リベース内の特定のコミットまたはすべてのコミットに対して任意のシェルコマンドを実行できます。

最初にgit author設定を設定します

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"

3
-xオプションを紹介していただきありがとうございます。そのかなり素晴らしい!-iオプションの場合、HEAD〜4を使用して、最後の4つのコミットでメールアドレスを修正しました。魅力のように働いた。
Brad Hein

2
これはfilter-branch、最後のコミットを修正したいだけの場合よりもはるかに簡単です:)。ただし、これによりコミットのタイムスタンプが変更されることに注意してください。
Luator、2015年

24
作成者を変更して元のタイムスタンプを維持するには、git rebase -i YOUR_SHA -x "git commit --amend --author 'New Name <new_address@example.com>' -CHEAD"
Dave

2
@Connor git logも古い作成者を示しましたが、gitステータスは新しいコミットを正しく識別し、強制プッシュ後は意図したとおりでした。
Dan M.

6
ルートを含むすべてのコミットをリベースするにはgit rebase -i --root …、SHAを渡す代わりに、次を使用します。
gfullam

80

最後のコミットについてのみ作成者を変更するには:

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

1
ルートからのすべてのコミット。git rebase -i --root UPTO_COMMIT_SHA -x "git commit --amend --author 'NEW_CHANGE' --no-edit"
Ashish Negi

1
--rebase-merges(short -r)オプションを追加することをお勧めします。ブランチにマージが含まれている場合、ブランチのトポロジをそのまま維持するためです。
ドンキホーテ

4

このメソッドは、まさにこの目的のために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

@enigment github上にあるリポジトリに満足している場合は、ローカルにあるフォルダーを削除(または別の場所に移動)して、githubからクローンを作成することができます
stevec

ありがとう、私は知っていますが、それは慣用的なGitHub / Gitの方法のようには見えません。
enigment


0

デベースと修正について不安を感じている場合は、この方法で行うことができます。同時に、おそらくあなたがとにかくやろうとしていたであろうグローバル設定も設定しているでしょう。

git reset HEAD~ (最後のコミットを元に戻す)

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

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

git commit -m "message"

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.