나는 학교 컴퓨터에서 간단한 스크립트를 작성하고 Git (내 펜 드라이브에있는 저장소에서 집의 컴퓨터에서 복제 된 저장소)에 변경 사항을 적용했습니다. 몇 번의 커밋 후에 나는 루트 사용자로 물건을 커밋하고 있음을 깨달았습니다.
이 커밋의 저자를 내 이름으로 바꿀 수있는 방법이 있습니까?
나는 학교 컴퓨터에서 간단한 스크립트를 작성하고 Git (내 펜 드라이브에있는 저장소에서 집의 컴퓨터에서 복제 된 저장소)에 변경 사항을 적용했습니다. 몇 번의 커밋 후에 나는 루트 사용자로 물건을 커밋하고 있음을 깨달았습니다.
이 커밋의 저자를 내 이름으로 바꿀 수있는 방법이 있습니까?
답변:
이 답변에 사용
git-filter-branch
하는, 워드 프로세서는 지금이 경고를 :git filter-branch는 의도 한 히스토리 재 작성의 명백한 맹 글링을 생성 할 수있는 많은 함정을 가지고 있습니다. 이러한 안전 및 성능 문제는 이전 버전과 호환되지 않으므로 사용하지 않는 것이 좋습니다. git filter-repo 와 같은 대체 히스토리 필터링 도구를 사용하십시오 . 여전히 git filter-branch를 사용해야하는 경우 SAFETY (및 PERFORMANCE )를 주의 깊게 읽고 filter-branch의 지뢰에 대해 배우고 거기에 열거 된 많은 위험을 합리적으로 피하십시오.
저자 (또는 커미터)를 변경하면 모든 히스토리를 다시 작성해야합니다. 괜찮다면 가치가 있다고 생각되면 git filter-branch을 확인하십시오 . 매뉴얼 페이지에는 시작하기위한 몇 가지 예가 포함되어 있습니다. 또한 환경 변수를 사용하여 작성자, 커미터, 날짜 등의 이름을 변경할 수 있습니다 . git man page 의 "Environment Variables"섹션을 참조하십시오 .
특히이 명령을 사용하여 모든 브랜치 및 태그에 대해 잘못된 작성자 이름과 이메일 을 모두 수정할 수 있습니다 (출처 : GitHub help ).
#!/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
git push --force --tags origin HEAD:master
참고 :이 답변은 SHA1을 변경하므로 이미 푸시 된 지점에서 사용하십시오. 이름의 철자를 수정하거나 오래된 전자 메일을 업데이트하려는 경우 git을 사용하여 기록을 다시 쓰지 않고도이 작업을 수행 할 수 있습니다 .mailmap
. 내 다른 답변을 참조하십시오 .
넌 할 수있어
git rebase -i -p <some HEAD before all of your bad commits>
그런 다음 rebase 파일에서 모든 잘못된 커밋을 "편집"으로 표시하십시오. 첫 번째 커밋도 변경하려면 rebase 파일에서 첫 번째 커밋을 수동으로 추가해야합니다 (다른 줄의 형식에 따름). 그런 다음 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.name
및 에서 구성된 사용자로 설정됩니다 git 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
위의 명령에 추가 했습니다. 가장 최근의 커밋을 변경하는 경우에는 문제가되지 않습니다.
git commit --amend --reset-author
또한 한 번 작동 user.name
하고 user.email
올바르게 구성되었습니다.
<commit>
사용 user.name
및 user.email
from 후 모든 커밋에 대한 작성자 정보를 다시 작성하십시오 . 편집 할 필요가 없습니다! ~/.gitconfig
git rebase -i <commit> --exec 'git commit --amend --reset-author --no-edit'
당신은 또한 할 수 있습니다 :
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
"A previous backup already exists in refs/original/ Force overwriting the backup with -f"
죄송하지만 -f
이 스크립트를 두 번 실행할 때 -flag가있을 위치 입니다. 실제로 그것은 브라이언의 대답에 있습니다. 필터 브랜치가 해결책이 된 직후의 방해에 대해 죄송합니다.
하나의 라이너이지만 다중 사용자 저장소가있는 경우주의하십시오. 이렇게하면 모든 커밋이 동일한 (새로운) 작성자 및 커미터를 갖도록 변경 됩니다 .
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
HEAD
명령 끝에 지정하면 왜 모든 커밋을 다시 작성 합니까?
git push --force --tags origin 'refs/heads/*'
권고 명령 후
$git push --force --tags origin 'refs/heads/master'
$ HOME / .gitconfig가 초기화되지 않은 경우 발생합니다. 이 문제를 다음과 같이 해결할 수 있습니다.
git config --global user.name "you name"
git config --global user.email you@domain.com
git commit --amend --reset-author
자식 버전 1.7.5.4로 테스트
--local
너무 작품
git commit --amend --reset-author --no-edit
명령은 잘못된 작성자 정보로 커밋을 만든 다음을 통해 정확한 작성자를 설정하는 경우 특히 유용합니다 git config
. 이메일을 업데이트해야 할 때 바로 $$를 저장했습니다.
단일 커밋의 경우 :
git commit --amend --author="Author Name <email@address.com>"
(asmeurer의 답변에서 추출)
git help commit
, git commit --amend
“현재 지점의 끝”(HEAD)에서 커밋을 변경합니다. 이것은 일반적으로 가장 최근의 커밋이지만 먼저 또는로 커밋을 확인하여 원하는 커밋을 만들 수 있습니다 . git checkout <branch-name>
git checkout <commit-SHA>
author
되며committer
상위 커밋 몇 개만 잘못된 작성자를 가지고있는 경우 다음과 같이 명령과 커밋을 git rebase -i
사용 하여이 작업을 모두 수행 할 수 있습니다 .exec
--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에게 감사합니다.
exec git commit --amend --reset-author -C HEAD
?
Someone else's commit
대신에 시작 my bad commit 1
합니까? 방금 HEAD^^
마지막 2 개의 커밋을 수정 하려고 시도했지만 완벽하게 작동했습니다.
git rebase -i HEAD^^^^^^
당신도 쓸 수 있습니다git rebase -i HEAD~6
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"
'
git reset --hard HEAD^
, 이전 버전을 얻기 위해 다른 지역 저장소에 몇 번 git pull
수정 된 버전을 -ed, 여기에 내가 포함 된 선없이 오전 unknown <stupid-windows-user@.StupidWindowsDomain.local>
(사랑 자식의 디폴트에에 도착).
git push -f
. 또한이 후 로컬 리포지토리를 다시 복제해야합니다.
교리가 언급했듯이, 역사를 다시 쓰는 것은 위험하며 다른 사람들의 저장소를 깨뜨릴 것입니다.
그러나 정말로 그렇게하고 싶고 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
--tag-name-filter cat
"작동"옵션입니다.
--tag-name-filter cat
합니다. 이것은 실제로 기본 행동이었습니다.
다른 저자의 병합되지 않은 커밋을 인계 할 때이를 쉽게 처리 할 수 있습니다.
git commit --amend --reset-author
--no-edit
일반적으로 대부분의 사람들은 커밋 메시지가 아닌 전자 메일 주소 만 업데이트하기를 원하기 때문에 이것을 더 쉽게 만들 수 있습니다.
이를 별명으로 사용 하여 다음을 수행 할 수 있습니다.
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
도움이 되길 바랍니다.
이것은 @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
다음 오류 중 하나가 나타날 수 있습니다.
이러한 오류에도 불구하고 강제로 실행하려면 --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
대신 사용하는 것입니다. 즉, 현재 분기 에서만 모든 개정을 필터링합니다 . 그리고 다시 작성된 브랜치에는 태그 (또는 다른 참조)가 없습니다.
마지막 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
그런 다음 여전히 일부 행을 수정하여 작성자를 변경하려는 위치를 볼 수 있습니다. 이를 통해 자동화와 제어 사이의 중간 정도를 얻을 수 있습니다. 실행할 단계를 확인하고 일단 저장하면 모든 것이 한 번에 적용됩니다.
git rebase -i master -x ...
git rebase -i <sha1 or ref of starting point>
edit
(또는 e
)모든 커밋을 처리 할 때까지 다음 두 명령을 반복하십시오.
git commit --amend --reuse-message=HEAD --author="New Author <new@author.email>"
;
git rebase --continue
이렇게하면 다른 모든 커밋 정보 (날짜 포함)가 유지됩니다. 이 --reuse-message=HEAD
옵션은 메시지 편집기가 시작되지 않도록합니다.
다음을 사용하여 태그 및 모든 분기를 포함한 전체 저장소의 작성자를 다시 작성합니다.
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
--tag-name-filter cat
. 그렇지 않으면 태그는 원래 커밋 체인에 남아 있습니다. 다른 답변은 이것을 언급하지 않습니다.
나는 간단한 것을 섭취함으로써 작동하는 이 솔루션 을 채택했다 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
유일한 문제는 저자 / 이메일이 당신의 평소와 다르다는 것이라면 문제가되지 않는다는 것을 지적해야합니다. 올바른 수정은 다음 .mailmap
과 같은 행을 사용하여 디렉토리의 기본에서 호출되는 파일을 작성하는 것입니다
Name you want <email you want> Name you don't want <email you don't want>
그리고 그때부터 같은 명령 git shortlog
은 두 이름이 같은 것으로 간주합니다 (구체적으로 말하지 않는 한). 자세한 내용은 http://schacon.github.com/git/git-shortlog.html 을 참조하십시오.
여기에는 다른 모든 솔루션의 이점이 있습니다. 히스토리를 다시 작성할 필요가 없기 때문에 업스트림이있는 경우 문제가 발생할 수 있으며 항상 실수로 데이터를 잃을 수있는 좋은 방법입니다.
물론 자신이 무언가를 저지른 상태에서 다른 사람이되어야하고이 시점에서 기록을 다시 쓰지 않아도된다면 커밋 작성자를 변경하는 것이 저작자 표시 목적에 대한 좋은 아이디어 일 것입니다. 다른 답변은 여기에 있습니다).
제시된 버전을 공격적으로 활용할 수있는 방법을 찾았습니다. 특히 다른 개발자의 패치를 커밋하면 본질적으로 코드를 훔칩니다.
아래 버전은 모든 브랜치에서 작동하며이를 방지하기 위해 작성자와 커미터를 개별적으로 변경합니다.
모든 옵션에 대해 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
로 커밋 author name & email
을 변경 Amend
한 다음 다음을 대체하십시오 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
다른 방법 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
가장 빠르고 쉬운 방법은 git rebase의 --exec 인수를 사용하는 것입니다.
git rebase -i -p --exec 'git commit --amend --reset-author --no-edit'
이렇게하면 다음과 같은 할일 목록이 만들어집니다.
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
...
그리고 이것은 모두 자동으로 작동하며 수백 개의 커밋이있을 때 작동합니다.
이 저장소의 유일한 사용자 인 경우에, 당신은 할 수 있습니다 역사를 다시 쓰는 중 하나를 사용하여 git filter-branch
(같은 svick 쓴 ) 또는 git fast-export
/ git fast-import
플러스 필터 (에서 참조 문서에 설명되어있는 것처럼 스크립트 docgnome 답 ) 또는 대화 형 REBASE . 그러나 그 중 하나는 처음 변경된 커밋부터 개정을 변경합니다. 이는 브랜치 사전 다시 쓰기에 대한 변경 내용을 기반으로하는 모든 사람에게 문제가 있음을 의미합니다.
회복
다른 개발자가 사전 재 작성 버전을 기반으로하지 않은 경우 가장 간단한 해결책은 다시 복제하는 것입니다.
또는 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에서 사용 가능한 참조 / 바꾸기 / 메커니즘 을 사용하는 것 입니다. 이 솔루션에서는 잘못된 이메일을 가진 커밋을 대체 할 수 있습니다. 다음 가져 오는 사람이 심판 (같은 '대신' fetch = +refs/replace/*:refs/replace/*
적절한 장소에 refspec 자신의 .git/config
투명하게 얻을 것이다 대체), 오래된 커밋을 볼 것 그 심판을 가져 오지 않는 사람들을.
절차는 다음과 같습니다.
잘못된 이메일로 커밋 찾기 (예 :
$ git log --author=user@wrong.email --all
각각의 잘못된 커밋에 대해 대체 커밋을 생성하여 객체 데이터베이스에 추가
$ 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>
이제 객체 데이터베이스에서 커밋을 수정 했으므로 git에게 git replace
명령을 사용하여 잘못된 커밋을 자동으로 투명하게 대체하도록 지시해야합니다 .
$ git replace <ID of wrong commit> <ID of corrected commit>
마지막으로이 절차가 성공했는지 확인하기 위해 모든 교체품을 나열하십시오.
$ git replace -l
교체가 있는지 확인
$ git log --author=user@wrong.email --all
물론이 절차를 자동화 할 수 있습니다. git replace
(아직) 배치 모드가없는 것을 사용 하는 것을 제외하고는 모두 그렇기 때문에 쉘 루프를 사용하거나 "수동으로"교체해야합니다.
검증되지 않은! YMMV.
refs/replace/
매커니즘을 사용할 때 약간의 문제가 발생할 수 있습니다 . 새롭지 만 아직 잘 테스트되지 않았습니다 .
수정하려는 커밋이 최신 사람들, 그들 중 단지 몇이 경우의 조합을 사용할 수 있습니다 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
EGit과 함께 Eclipse를 사용하는 경우 매우 쉬운 해결책이 있습니다.
가정 : 유효하지 않은 사용자로 인해 로컬 분기 'local_master_user_x'에 원격 분기 'master'로 푸시 할 수없는 커밋이 있습니다.
git 은 커미터 (변경자를 커밋 한 사람)와 저자를 위한 두 개의 서로 다른 이메일 주소를 저장 합니다. (변경 사항을 쓴 사람)를 .
커미터 정보는 대부분의 위치에 표시되지 않지만 함께 확인할 수 있습니다 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
있습니다. 아직 완전히 삭제하기 위해 무엇을해야할지 잘 모르겠습니다. 불행히도 수정 (?)은 지워지지 않는 것 같습니다.
작성자 이름의 UTF8 문자로 인해 빌드 서버에서 문제가 발생하는 문제가 발생하여이 문제를 해결하기 위해 기록을 다시 작성해야했습니다. 취한 단계는 다음과 같습니다.
1 단계 : 다음 지침에 따라 모든 향후 커밋에 대해 git에서 사용자 이름을 변경하십시오. https://help.github.com/articles/setting-your-username-in-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 시스템에서 다시 실행해야했습니다.
당신의 문제는 정말 일반적입니다. "를 참조 수정 저자 힘내에서 목록에 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 <branch> <branch2>
저장소에 기존 사용자 표시
$ git changemail --show-both
그건 그렇고, 변경을 한 후 git-backup-clean 을 사용하여 필터 브랜치에서 백업을 정리하십시오.
이것을 시도하십시오. 위에서 언급 한 것과 동일하지만 대화식으로 수행됩니다.
bash <(curl -s https://raw.githubusercontent.com/majdarbash/git-author-change-script/master/run.sh)
예도 추가하고 싶습니다. 주어진 매개 변수 로 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;
}
이 리포지토리의 유일한 사용자이거나 다른 사용자에 대한 리포지토리를 무너 뜨릴 염려가 없다면, 그렇습니다. 이 커밋을 푸시하고 다른 사람이 액세스 할 수있는 곳에 존재한다면 다른 사람들의 저장소를 깨는 것에 신경 쓰지 않는 한 그렇지 않습니다. 문제는 이러한 커밋을 변경하여 새 SHA를 생성하여 다른 커밋으로 취급하게하는 것입니다. 누군가가 변경된 커밋을 가져 오려고하면 역사가 다릅니다.
이 페이지는 http://inputvalidation.blogspot.com/2008/08/how-to-change-git-commit-author.html에서 설명합니다. (YMMV를 시도하지 않았습니다)
refs/replace/
메커니즘을 사용해보십시오 .