0

This was a problem I wanted to solve. When I searched up this question, I saw answers using git filter-branch and git filter-repo.

I can say with 100% confidence that git filter-branch is too slow and I don't like that it can change the same commit in multiple branches. Not a useful method.

Next is git filter-repo. It seems like a good solution but I'm using Ubuntu 20.04 LTS which doesn't seem to be supported. I would need to spend a little time to update to 22.04 LTS. So only useful on supported distros and versions.

Now here is my answer:

initialCommit=$(git log original-branch --format=format:"%h" | tail -1)
readarray -t commitsArray < <(git log original-branch --author="Original Author <originalauthor@email.com>" --format=format:"%h")
startCommitIndex=$(("${#commitsArray[@]}"-1))

git checkout -b new-branch "$initialCommit"
if [[ "$initialCommit" == "${commitsArray[$startCommitIndex]}" ]]; then
    git commit --amend --author "New Author <newauthor@email.com>"
    startCommitIndex=$(($startCommitIndex - 1))
fi
for (( commitIndex=$startCommitIndex; commitIndex >= 0; commitIndex-- )); do
    git cherry-pick "${commitsArray[$commitIndex]}"
    git commit --amend --author "New Author <newauthor@email.com>"
done

We learned that git commit --amend --author "New Author <newauthor@email.com>" modifies the latest commit, also known as the HEAD commit (git log -1 --format=format:"%h").

Regarding --format=format:"%h", we can retrieve a commit's hash in two ways:

  1. --format=format:"%H": A long hash. Retrieves the full hash of the commit (40 characters long).
  2. --format=format:"%h": A shortened version of the hash that uses the first 7 to 9 characters (length varies depending on history length). Git is smart enough to figure out what commit is meant with this hash.

The git cherry-pick command allows you to pick a commit's hash from any branch and drop the contents of that commit into another branch. This creates a new commit hash in the branch with those contents, which becomes a HEAD commit.

git checkout -b new-branch "$initialCommit" creates a new branch with $initialCommit becoming the HEAD commit.

In this way, we are able to change the author and author email for multiple commits (that we found with readarray -t commitsArray < <(git log original-branch --author="Original Author <originalauthor@email.com>" --format=format:"%h")).

Afterwards, we could choose to remove our original branch (git branch -D original-branch) and rename our new branch (git branch -m new-branch original-branch). Then if satisfied later decide to push our changes to GitHub, GitLab, or wherever your git project is stored in remotely. Done!

Dennis
  • 1
  • 1
  • 1
  • 1
    Ubuntu 20.04 should be good. You can read this : [How do you install git-filter-repo?](https://superuser.com/a/1589985/659315) – Asif Kamran Malick Sep 16 '22 at 17:17
  • Not a bad solution @AsifKamranMalick. But the answer I propose solves this problem using only built-in git commands. It doesn't require python (version 3) like git-filter-repo does. Personally, I find this solution uses less time to do what I need it to do. I do have python 3 but there is a chance some machines may not have python 3. So basically this solution does not depend on python. Only Git (and basic bash syntax). – Dennis Sep 16 '22 at 18:27
  • What is the question here? – knittl Oct 18 '22 at 18:54
  • What does mean "git filter-branch can change a commit in multiple branches"? filter-branch will rewrite all commit ranges given on the commandline plus refs – knittl Oct 18 '22 at 19:03
  • @knittl This is the scenario: You have a git repository with multiple branches. Some branches are feature branches, checked out from the main branch. If you use "git log" to look at the commit hashes across multiple branches, I believe some of these commits share the same exact hash. So, when I used "git filter-branch", I saw it rewrote the same commit across multiple branches which I thought was dangerous! – Dennis Nov 07 '22 at 22:03
  • @knittl The question of this post is the title: How do I change the author and author name for multiple commits? I saw multiple solutions and thought there should be a better way to solve it. I have no problems with some of them, like git-filter-repo if it works for you, however maybe my solution is more intuitive. It solves a git problem in git while git-filter-repo solves a git problem in python. – Dennis Nov 07 '22 at 22:09
  • @Dennis your premise is wrong. "commits on different branches share the same exact hash". That's not correct. Commits do not "share hashes". It's only a single commit. A branch is not "a thing" in Git. A branch points to a single commit and this commit points to its parent, which points to its parent(s), and so on. If you run filter-branch on all branches/refs, then a new commit will be created. The refs/branches will be updated to include this new commit as their ancestor. So I'm still not sure what your question is, because a commit only exists once; therefore you can only rewrite it once :) – knittl Nov 08 '22 at 06:53

0 Answers0