Change of postal address in every message

I made multiple commits ( not pushed ) using the original tree with the wrong email address.

To fix this error I did some research and found this script to edit a good post commit. The fact is that when I first pulled the project from git, there were already over 200 commits from several users.

When I used the script, it got my mail addresses back correctly, but the rest were destroyed:

ex : a.my@mail.com became a.my@5030863e-2e11-0d4c-b7c1-a084646f5798

      

Do you know how I can deal with this problem?

#!/bin/sh

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

OLD_EMAIL="a.bbbb@5030863e-2e11-0d4c-b7c1-a084646f5798"
CORRECT_NAME="a.bbbb"
CORRECT_EMAIL="a.bbbb@mail.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

      

EDIT1:

I used the script for other email addresses

it fixed everything before that, but sourcetree tells me that the 248up / 248down master is:

enter image description here

How can I get to this status?

EDIT2:

As I said,

git branch -f master origin/master

      

it fixed the repo status (248up / 248down disappeared)

but I still have 2 times history in the sourcetree, in purple we can see the last commit in the remote repo (with incorrect mail changes that I changed), starting from the blue part, there is a correct history, at the end my local one (develops branch and features with good mail):

enter image description here

+3


source to share


1 answer


Since you only have a few commits and not the whole history, I would do it manually using git rebase -i -p

and git commit --amend --author "a.jard <a.jard@mail.com>"

.

It covers this answer , which is not the accepted answer, but has double votes.

As for why you are getting the result with your script, it has to do with the nature of git and how rebase works. rebase does not rewrite history, it cannot. Git entries are immutable. The commit ID is tied to the content of the commit itself, including metadata such as date, log message, author, and committer. rebase writes new history.

Another clue to the puzzle is the commit ID, calculated using the ID of its parents. You cannot change the parent without changing it. This makes git push and pull very efficient if I say I have ABC123 and if you committed ABC123 we both know we have the same story.

For example, let's say you have a simple repository with five commits like this. master and origin / master both point to E.

A - B - C - D - E [master] [origin/master]

      

B has an invalid email address. A, C, D and E are all right. You run the filter-branch command. He will look at A, see that there is no change, and leave him alone. It will look at B, change the committer, and write a new commit with A as the parent. Let's call it B1.

A - B - C - D - E [master] [origin/master]
 \
  B1

      

Now he looks at C. Nothing will change there, but B1 is needed for his parent. Since the id contains the parent id, it must make a new commit.

A - B - C - D - E [master] [origin/master]
 \
  B1 - C1

      

And it's the same with D and E.

A - B - C - D - E [master] [origin/master]
 \
  B1 - C1 - D1 - E1

      

Done, the filter branch is moved [master] to E1.

A - B - C - D - E [origin/master]
 \
  B1 - C1 - D1 - E1 [master]

      

And that's why changing one commit in the past will cause everything after it to diverge.

Since the author of this script did not instruct you to limit what changes git -filter-branch should filter, he followed the entire history of the current branch.

Luckily, you can undo this by moving the master back to the start / master. There are several ways to do this. git branch -f master origin/master

is the simplest.

UPDATE This covers your new issue where the development branch stays hovering on a filtered branch. Let it start from the beginning. You had such a situation ...

A - B - C - D - E [master] [origin/master]

      

You are up git author-rewrite

and running with it.

A - B - C - D - E [origin/master]
 \
  B1 - C1 - D1 - E1 [master]

      

You have detached the master and started making new commits.



A - B - C - D - E [origin/master]
 \
  B1 - C1 - D1 - E1 [master] - F - G - H [devel]

      

You have completed git branch -f master origin/master

to cancel your filter. Branches in git are only tags pointing to commits, so only the main tag was moved. Your development branch is still hanging from filtered commits.

A - B - C - D - E [origin/master] [master]
 \
  B1 - C1 - D1 - E1 - F - G - H [devel]

      

Now you need to get devel and F, G and H hanging from the master. The first order of the business is to move development to the master. If we do this, it will be difficult to find F, G and H again. You could just write down the IDs, or you can take out the insurances using a tag. git tag tmp devel

...

A - B - C - D - E [origin/master] [master]
 \
  B1 - C1 - D1 - E1 - F - G - H [devel] <tmp>

      

Now switch to design mode with git branch -f devel master

. The tmp tag keeps the filtered branch available.

A - B - C - D - E [origin/master] [master] [devel]
 \
  B1 - C1 - D1 - E1 - F - G - H <tmp>

      

Now you can use git cherry-pick

to copy every single change in devel. The contents of the commit won't change, but the parents are, so they must be copied.

git checkout devel
git cherry-pick F^..tmp

      

To explain the part F^..tmp

, we want everything from H to F. to F..H

say that they include the parents of H, but exclude the parents of F, that only H and G. Since we want to include F in the list we use F^

to exclude the parents from F ...

You complete this.

A - B - C - D - E [origin/master] [master] - F1 - G1 - H1 [devel]
 \
  B1 - C1 - D1 - E1 - F - G - H <tmp>

      

Once you check it, remove the tmp tag with git tag -d tmp

.

A - B - C - D - E [origin/master] [master] - F1 - G1 - H1 [devel]

      

Don't worry if you mess up your commits, there will still be weeks before they get garbage collected.

You can now check development and fix your commits using the reinstallation technique described above. You are done with this.

A - B - C - D - E [origin/master] [master]
 \
  B2 - C2 - D2 - E2 - F2 - G2 - H2 [devel]

      

Manually move the master to E2 with git branch -f master E2

.

A - B - C - D - E [origin/master]
 \
  B2 - C2 - D2 - E2 [master] - F2 - G2 - H2 [devel]

      

You disperse anyway. Pushing your changes will still need to be forced, and everyone else will be forced to pull. This part cannot be avoided. Changing history after clicking it is always messy.

There are many other ways to accomplish all of this. One of the benefits of using it git filter-branch

is to move all tags and branches changed along the way for you. For small changes like yours and new users, I prefer to do it in small steps. It's easier to understand what's going on.

+1


source







All Articles